4 Commits
Author SHA1 Message Date
pancake 0c3277646a Remove Travis badge - no longer used 2026-03-09 23:46:37 +01:00
pancake c504deaff8 Update the CI badge 2026-03-09 23:46:16 +01:00
pancake 7cd1560585 Add support for Windows 2026-03-09 23:41:26 +01:00
pancake ee36c46657 Use libload instead of dlopen for portability reasons 2026-02-20 16:00:28 +01:00
5 changed files with 86 additions and 9 deletions

No files matched your search

+25 -3
View File
@@ -1,4 +1,7 @@
name: R2pipe Rust CI
name: ci
env:
R2V: 6.1.0
on:
push:
@@ -10,10 +13,10 @@ on:
jobs:
build_and_test:
name: R2pipe.rs
name: R2pipe.rs (Ubuntu)
runs-on: ubuntu-latest
steps:
- run: wget https://github.com/radareorg/radare2/releases/download/5.8.0/radare2_5.8.0_amd64.deb && sudo dpkg -i radare2*.deb
- run: wget https://github.com/radareorg/radare2/releases/download/${{env.R2V}}/radare2_${{env.R2V}}_amd64.deb && sudo dpkg -i radare2*.deb
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
@@ -22,17 +25,36 @@ jobs:
override: true
- run: rustup component add rustfmt clippy
- uses: actions-rs/cargo@v1
name: Building
with:
command: build
args: --release --all-features
- uses: actions-rs/cargo@v1
name: Testing
with:
command: test
- uses: actions-rs/cargo@v1
name: Format
with:
command: fmt
args: --all -- --check
- uses: actions-rs/cargo@v1
name: Clippy
with:
command: clippy
args: -- -D warnings
build_and_test_windows:
name: R2pipe.rs (Windows)
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Install radare2
run: |
Invoke-WebRequest -Uri "https://github.com/radareorg/radare2/releases/download/${{env.R2V}}/radare2-${{env.R2V}}-w64.zip" -OutFile "radare2.zip"
Expand-Archive -Path "radare2.zip" -DestinationPath "C:\radare2"
$r2path = (Get-ChildItem -Path "C:\radare2" -Directory | Select-Object -First 1).FullName
echo "$r2path\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- uses: dtolnay/rust-toolchain@stable
- run: cargo build --release --all-features
- run: cargo test
+1
View File
@@ -22,6 +22,7 @@ license = "MIT OR Apache-2.0"
[features]
docsrs = []
http = []
[dependencies]
libloading = "0.8"
+1 -2
View File
@@ -1,5 +1,4 @@
![R2pipe Rust CI](https://github.com/radareorg/r2pipe.rs/workflows/R2pipe%20Rust%20CI/badge.svg)
[![Travis](https://travis-ci.org/radareorg/r2pipe.rs.svg?branch=master)](https://travis-ci.org/radareorg/r2pipe.rs)
[![ci](https://github.com/radareorg/r2pipe.rs/actions/workflows/main.yml/badge.svg)](https://github.com/radareorg/r2pipe.rs/actions/workflows/main.yml)
[![Documentation](https://docs.rs/r2pipe/badge.svg)](https://docs.rs/r2pipe)
[![Cargo](https://img.shields.io/crates/v/r2pipe.svg)](https://crates.io/crates/r2pipe)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](
+54 -2
View File
@@ -6,6 +6,31 @@ use std::sync::Mutex;
pub struct LibHandle(Mutex<Library>);
impl LibHandle {
#[cfg(windows)]
fn load_library(path: &str) -> std::result::Result<Library, libloading::Error> {
use libloading::os::windows::{
Library as WindowsLibrary, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR,
};
if path.contains('\\') || path.contains('/') {
unsafe {
WindowsLibrary::load_with_flags(
path,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
)
.map(Into::into)
}
} else {
unsafe { Library::new(path) }
}
}
#[cfg(not(windows))]
fn load_library(path: &str) -> std::result::Result<Library, libloading::Error> {
unsafe { Library::new(path) }
}
/// Load a shared library by name with platform-specific extension.
pub fn new(name: &str, end: Option<&str>) -> Result<LibHandle> {
let ext = if cfg!(windows) {
@@ -16,8 +41,35 @@ impl LibHandle {
".so"
};
let lib_name = format!("{}{}{}", name, ext, end.unwrap_or(""));
let lib = unsafe { Library::new(&lib_name) }?;
Ok(LibHandle(Mutex::new(lib)))
// Prepare list of paths to try
let mut lib_paths = vec![lib_name.clone()];
// On Windows, add common radare2 installation paths
if cfg!(windows) {
// CI installs to C:\radare2\<version>\bin, where version changes
// So we need to search for the latest version directory
lib_paths.push(format!("C:\\radare2\\bin\\{}", lib_name));
// Also try the versioned path pattern from CI
if let Ok(entries) = std::fs::read_dir("C:\\radare2") {
for entry in entries.flatten() {
if entry.file_type().is_ok_and(|ft| ft.is_dir()) {
let version_path = format!("{}\\bin\\{}", entry.path().display(), lib_name);
lib_paths.push(version_path);
}
}
}
}
// Try each path until we find one that works
for lib_path in &lib_paths {
if let Ok(lib) = Self::load_library(lib_path) {
return Ok(LibHandle(Mutex::new(lib)));
}
}
// If none worked, return the error from the first attempt
Err(Self::load_library(&lib_paths[0]).unwrap_err().into())
}
/// Load a symbol from the library and transmute it to the desired type.
+5 -2
View File
@@ -379,7 +379,8 @@ pub struct R2PipeNative {
impl R2PipeNative {
pub fn open(file: &str) -> Result<R2PipeNative> {
let mut lib = dlfcn::LibHandle::new("libr_core", None)?;
let lib_name = if cfg!(windows) { "r_core" } else { "libr_core" };
let mut lib = dlfcn::LibHandle::new(lib_name, None)?;
let r_core_new: fn() -> *mut libc::c_void = unsafe { lib.load_sym("r_core_new")? };
let r_core_cmd_str_handle = unsafe { lib.load_sym("r_core_cmd_str")? };
let r_core = r_core_new();
@@ -424,9 +425,11 @@ impl Drop for R2PipeNative {
mod test {
use super::Pipe;
use super::R2PipeNative;
#[cfg(not(windows))]
use crate::R2Pipe;
#[test]
#[cfg(not(windows))]
fn spawn_test() {
let mut pipe = R2Pipe::spawn("/bin/ls", None).unwrap();
assert_eq!(pipe.cmd("echo test").unwrap(), "test\n");
@@ -434,7 +437,7 @@ mod test {
#[test]
fn native_test() {
let mut r2p = R2PipeNative::open("/bin/ls").unwrap();
let mut r2p = R2PipeNative::open("malloc://32").unwrap();
assert_eq!("a\n", r2p.cmd("echo a").unwrap());
}
}