mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-15 01:03:53 +00:00
Move part of libbase to Rust
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "base"
|
||||
version = "0.1.0"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
@@ -8,3 +8,4 @@ path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
cxx = { path = "../external/cxx-rs" }
|
||||
libc = "0.2"
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#![feature(format_args_nl)]
|
||||
|
||||
pub use libc;
|
||||
pub use logging::*;
|
||||
pub use misc::*;
|
||||
pub use xwrap::*;
|
||||
|
||||
mod logging;
|
||||
mod misc;
|
||||
mod xwrap;
|
||||
|
||||
#[cxx::bridge]
|
||||
pub mod ffi {
|
||||
|
||||
@@ -7,11 +7,11 @@ use crate::ffi::LogLevel;
|
||||
// Ugly hack to avoid using enum
|
||||
#[allow(non_snake_case, non_upper_case_globals)]
|
||||
mod LogFlag {
|
||||
pub const DisableError: u32 = 0x1;
|
||||
pub const DisableWarn: u32 = 0x2;
|
||||
pub const DisableInfo: u32 = 0x4;
|
||||
pub const DisableDebug: u32 = 0x8;
|
||||
pub const ExitOnError: u32 = 0x10;
|
||||
pub const DisableError: u32 = 1 << 0;
|
||||
pub const DisableWarn: u32 = 1 << 1;
|
||||
pub const DisableInfo: u32 = 1 << 2;
|
||||
pub const DisableDebug: u32 = 1 << 3;
|
||||
pub const ExitOnError: u32 = 1 << 4;
|
||||
}
|
||||
|
||||
// We don't need to care about thread safety, because all
|
||||
@@ -92,7 +92,6 @@ pub fn cmdline_logging() {
|
||||
eprint!("{}", args);
|
||||
}
|
||||
}
|
||||
|
||||
fn write(level: LogLevel, msg: &[u8]) {
|
||||
if level == LogLevel::Info {
|
||||
stdout().write_all(msg).ok();
|
||||
@@ -111,29 +110,48 @@ pub fn cmdline_logging() {
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! perror {
|
||||
($fmt:expr) => {
|
||||
$crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!(
|
||||
concat!($fmt, " failed with {}: {}"),
|
||||
crate::errno(),
|
||||
crate::error_str()
|
||||
))
|
||||
};
|
||||
($fmt:expr, $($args:tt)*) => {
|
||||
$crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!(
|
||||
concat!($fmt, " failed with {}: {}"),
|
||||
$($args)*,
|
||||
crate::errno(),
|
||||
crate::error_str()
|
||||
))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! error {
|
||||
($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!($($arg)+)))
|
||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!($($args)+)))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! warn {
|
||||
($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Warn, format_args_nl!($($arg)+)))
|
||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Warn, format_args_nl!($($args)+)))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! info {
|
||||
($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Info, format_args_nl!($($arg)+)))
|
||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Info, format_args_nl!($($args)+)))
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[macro_export]
|
||||
macro_rules! debug {
|
||||
($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Debug, format_args_nl!($($arg)+)))
|
||||
($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Debug, format_args_nl!($($args)+)))
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[macro_export]
|
||||
macro_rules! debug {
|
||||
($($arg:tt)+) => {};
|
||||
($($args:tt)+) => {};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::cmp::min;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::fmt::Arguments;
|
||||
|
||||
@@ -39,3 +40,77 @@ pub fn fmt_to_buf(buf: &mut [u8], args: Arguments) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
// The cstr! macro is inspired by https://github.com/Nugine/const-str
|
||||
|
||||
macro_rules! const_assert {
|
||||
($s: expr) => {
|
||||
assert!($s)
|
||||
};
|
||||
}
|
||||
|
||||
pub struct ToCStr<'a>(pub &'a str);
|
||||
|
||||
impl ToCStr<'_> {
|
||||
const fn assert_no_nul(&self) {
|
||||
let bytes = self.0.as_bytes();
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
const_assert!(bytes[i] != 0);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn eval_len(&self) -> usize {
|
||||
self.assert_no_nul();
|
||||
self.0.as_bytes().len() + 1
|
||||
}
|
||||
|
||||
pub const fn eval_bytes<const N: usize>(&self) -> [u8; N] {
|
||||
let mut buf = [0; N];
|
||||
let mut pos = 0;
|
||||
let bytes = self.0.as_bytes();
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
const_assert!(bytes[i] != 0);
|
||||
buf[pos] = bytes[i];
|
||||
pos += 1;
|
||||
i += 1;
|
||||
}
|
||||
pos += 1;
|
||||
const_assert!(pos == N);
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cstr {
|
||||
($s:literal) => {{
|
||||
const LEN: usize = $crate::ToCStr($s).eval_len();
|
||||
const BUF: [u8; LEN] = $crate::ToCStr($s).eval_bytes();
|
||||
unsafe { CStr::from_bytes_with_nul_unchecked(&BUF) }
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! r_cstr {
|
||||
($s:literal) => {
|
||||
cstr!($s).as_ptr()
|
||||
};
|
||||
}
|
||||
|
||||
pub unsafe fn ptr_to_str<'a, T>(ptr: *const T) -> &'a str {
|
||||
CStr::from_ptr(ptr.cast()).to_str().unwrap_or("")
|
||||
}
|
||||
|
||||
pub fn errno() -> &'static mut i32 {
|
||||
// On Android, errno is obtained through the __errno function for thread local storage
|
||||
extern "C" {
|
||||
fn __errno() -> *mut i32;
|
||||
}
|
||||
unsafe { &mut *__errno() }
|
||||
}
|
||||
|
||||
pub fn error_str() -> &'static str {
|
||||
unsafe { ptr_to_str(libc::strerror(*errno())) }
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ void byte_stream::resize(size_t new_pos, bool zero) {
|
||||
resize = true;
|
||||
}
|
||||
if (resize) {
|
||||
_buf = (uint8_t *) xrealloc(_buf, _cap);
|
||||
_buf = (uint8_t *) realloc(_buf, _cap);
|
||||
if (zero)
|
||||
memset(_buf + old_cap, 0, _cap - old_cap);
|
||||
}
|
||||
|
||||
@@ -14,54 +14,6 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
FILE *xfopen(const char *pathname, const char *mode) {
|
||||
FILE *fp = fopen(pathname, mode);
|
||||
if (fp == nullptr) {
|
||||
PLOGE("fopen: %s", pathname);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
FILE *xfdopen(int fd, const char *mode) {
|
||||
FILE *fp = fdopen(fd, mode);
|
||||
if (fp == nullptr) {
|
||||
PLOGE("fopen");
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int xopen(const char *pathname, int flags) {
|
||||
int fd = open(pathname, flags);
|
||||
if (fd < 0) {
|
||||
PLOGE("open: %s", pathname);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
int xopen(const char *pathname, int flags, mode_t mode) {
|
||||
int fd = open(pathname, flags, mode);
|
||||
if (fd < 0) {
|
||||
PLOGE("open: %s", pathname);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
int xopenat(int dirfd, const char *pathname, int flags) {
|
||||
int fd = openat(dirfd, pathname, flags);
|
||||
if (fd < 0) {
|
||||
PLOGE("openat: %s", pathname);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
int xopenat(int dirfd, const char *pathname, int flags, mode_t mode) {
|
||||
int fd = openat(dirfd, pathname, flags, mode);
|
||||
if (fd < 0) {
|
||||
PLOGE("openat: %s", pathname);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Write exact same size as count
|
||||
ssize_t xwrite(int fd, const void *buf, size_t count) {
|
||||
size_t write_sz = 0;
|
||||
@@ -215,30 +167,6 @@ int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
void *xmalloc(size_t size) {
|
||||
void *p = malloc(size);
|
||||
if (p == nullptr) {
|
||||
PLOGE("malloc");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *xcalloc(size_t nmemb, size_t size) {
|
||||
void *p = calloc(nmemb, size);
|
||||
if (p == nullptr) {
|
||||
PLOGE("calloc");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void *xrealloc(void *ptr, size_t size) {
|
||||
void *p = realloc(ptr, size);
|
||||
if (p == nullptr) {
|
||||
PLOGE("realloc");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags) {
|
||||
int sent = sendmsg(sockfd, msg, flags);
|
||||
if (sent < 0) {
|
||||
@@ -515,10 +443,3 @@ int xmknod(const char *pathname, mode_t mode, dev_t dev) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
long xptrace(int request, pid_t pid, void *addr, void *data) {
|
||||
long ret = ptrace(request, pid, addr, data);
|
||||
if (ret < 0)
|
||||
PLOGE("ptrace %d", pid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
FILE *xfopen(const char *pathname, const char *mode);
|
||||
FILE *xfdopen(int fd, const char *mode);
|
||||
int xopen(const char *pathname, int flags);
|
||||
int xopen(const char *pathname, int flags, mode_t mode);
|
||||
int xopenat(int dirfd, const char *pathname, int flags);
|
||||
int xopenat(int dirfd, const char *pathname, int flags, mode_t mode);
|
||||
int xopen(const char *pathname, int flags, mode_t mode = 0);
|
||||
int xopenat(int dirfd, const char *pathname, int flags, mode_t mode = 0);
|
||||
ssize_t xwrite(int fd, const void *buf, size_t count);
|
||||
ssize_t xread(int fd, void *buf, size_t count);
|
||||
ssize_t xxread(int fd, void *buf, size_t count);
|
||||
@@ -24,16 +24,12 @@ struct dirent *xreaddir(DIR *dirp);
|
||||
pid_t xsetsid();
|
||||
int xsocket(int domain, int type, int protocol);
|
||||
int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int xconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
int xlisten(int sockfd, int backlog);
|
||||
int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
|
||||
void *xmalloc(size_t size);
|
||||
void *xcalloc(size_t nmemb, size_t size);
|
||||
void *xrealloc(void *ptr, size_t size);
|
||||
ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags);
|
||||
ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags);
|
||||
int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg);
|
||||
void *(*start_routine)(void *), void *arg);
|
||||
int xaccess(const char *path, int mode);
|
||||
int xstat(const char *pathname, struct stat *buf);
|
||||
int xlstat(const char *pathname, struct stat *buf);
|
||||
@@ -64,8 +60,5 @@ int xpoll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||
int xinotify_init1(int flags);
|
||||
char *xrealpath(const char *path, char *resolved_path);
|
||||
int xmknod(const char *pathname, mode_t mode, dev_t dev);
|
||||
long xptrace(int request, pid_t pid, void *addr = nullptr, void *data = nullptr);
|
||||
static inline long xptrace(int request, pid_t pid, void *addr, uintptr_t data) {
|
||||
return xptrace(request, pid, addr, reinterpret_cast<void *>(data));
|
||||
}
|
||||
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
|
||||
|
||||
} // extern "C"
|
||||
|
||||
57
native/src/base/xwrap.rs
Normal file
57
native/src/base/xwrap.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use libc::{c_char, c_uint, mode_t};
|
||||
|
||||
use crate::{perror, ptr_to_str};
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xfopen(path: *const c_char, mode: *const c_char) -> *mut libc::FILE {
|
||||
unsafe {
|
||||
let fp = libc::fopen(path, mode);
|
||||
if fp.is_null() {
|
||||
perror!("fopen: {}", ptr_to_str(path));
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xfdopen(fd: i32, mode: *const c_char) -> *mut libc::FILE {
|
||||
unsafe {
|
||||
let fp = libc::fdopen(fd, mode);
|
||||
if fp.is_null() {
|
||||
perror!("fdopen");
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xopen(path: *const c_char, flags: i32, mode: mode_t) -> i32 {
|
||||
unsafe {
|
||||
let r = libc::open(path, flags, mode as c_uint);
|
||||
if r < 0 {
|
||||
perror!("open: {}", ptr_to_str(path));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xopenat(dirfd: i32, path: *const c_char, flags: i32, mode: mode_t) -> i32 {
|
||||
unsafe {
|
||||
let r = libc::openat(dirfd, path, flags, mode as c_uint);
|
||||
if r < 0 {
|
||||
perror!("openat: {}", ptr_to_str(path));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! xopen {
|
||||
($path:expr, $flags:expr) => {
|
||||
xopen($path, $flags, 0)
|
||||
};
|
||||
($path:expr, $flags:expr, $mode:expr) => {
|
||||
xopen($path, $flags, $mode)
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user