Git · dadoum.zone
Repositories
Help
Report an Issue
apple-crates
Code
Commits
Branches
Tags
Search
Tree:
a74924e
Branches
Tags
main
apple-crates
android-coreadi
src
windows.rs
Refactor and unify a lot of things for another project and implement airdrop support
Dadoum
commited
a74924e
at 2026-10-25 22:15:58
windows.rs
Blame
History
Raw
#![allow(unsafe_op_in_unsafe_fn)] #![allow(non_camel_case_types)] // TODO: finish that use crate::linux_libc::*; use elf_loader::linux_cc; use std::ffi::{CStr, CString}; use std::mem; use std::mem::MaybeUninit; pub type __time32_t = libc::c_long; pub type __time64_t = libc::c_longlong; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _timespec64 { pub tv_sec: __time64_t, pub tv_nsec: libc::c_long, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _timespec32 { pub tv_sec: __time32_t, pub tv_nsec: libc::c_long, } // Import a few windows functions that are not defined in libc unsafe extern "C" { fn _errno() -> *mut libc::c_int; fn _timespec64_get(__ts: *mut _timespec64, __base: libc::c_int) -> libc::c_int; fn _timespec32_get(__ts: *mut _timespec32, __base: libc::c_int) -> libc::c_int; fn _chsize_s(handle: libc::c_int, length: i64) -> libc::c_int; } #[linux_cc] pub unsafe fn chmod(path: *const libc::c_char, mode: mode_t) -> libc::c_int { libc::chmod(linux_path_to_windows(path).as_ptr(), mode as libc::c_int) } #[linux_cc] pub unsafe fn close(fd: libc::c_int) -> libc::c_int { libc::close(fd) } #[linux_cc] pub unsafe fn errno() -> *mut libc::c_int { // HACK we should also translate the errnos, but eh it works fine right now _errno() } #[linux_cc] pub unsafe fn free(p: *mut libc::c_void) { libc::free(p) } #[linux_cc] pub unsafe fn ftruncate(handle: libc::c_int, length: i64) -> libc::c_int { let result = _chsize_s(handle, length); if result == 0 { 0 } else { *_errno() = result; -1 } } #[linux_cc] pub unsafe fn gettimeofday(tp: *mut timeval, _tz: *mut libc::c_void) -> libc::c_int { let mut time = MaybeUninit::uninit(); #[cfg(target_pointer_width = "32")] let result = _timespec32_get(time.as_mut_ptr(), 1); #[cfg(target_pointer_width = "64")] let result = _timespec64_get(time.as_mut_ptr(), 1); if result != 1 { return -1; } let time = time.assume_init(); *tp = timeval { tv_sec: time.tv_sec as _, tv_usec: (time.tv_nsec / 1000) as _, }; 0 } #[linux_cc] pub unsafe fn malloc(size: libc::size_t) -> *mut libc::c_void { libc::malloc(size) } #[linux_cc] pub unsafe fn mkdir(path: *const libc::c_char, _mode: mode_t) -> libc::c_int { libc::mkdir(linux_path_to_windows(path).as_ptr()) } #[linux_cc] pub unsafe fn read(fd: libc::c_int, buf: *mut libc::c_void, count: libc::c_uint) -> libc::c_int { libc::read(fd, buf, count) } #[linux_cc] pub unsafe fn strncpy( dst: *mut libc::c_char, src: *const libc::c_char, n: libc::size_t, ) -> *mut libc::c_char { libc::strncpy(dst, src, n) } #[linux_cc] pub unsafe fn umask(mask: usize) -> usize { // Wrong but works fine. mask } #[linux_cc] pub unsafe fn write(fd: libc::c_int, buf: *const libc::c_void, count: libc::c_uint) -> libc::c_int { libc::write(fd, buf, count) } #[inline] unsafe fn local_stat_to_linux(buf: libc::stat) -> stat { stat { st_dev: buf.st_dev as _, st_ino: buf.st_ino as _, st_nlink: buf.st_nlink as _, st_mode: buf.st_mode as _, st_uid: buf.st_uid as _, st_gid: buf.st_gid as _, st_rdev: buf.st_rdev as _, st_size: buf.st_size as _, st_atime: buf.st_atime as _, // st_atime_nsec: buf.st_atime_nsec as _, st_mtime: buf.st_mtime as _, // st_mtime_nsec: buf.st_mtime_nsec as _, st_ctime: buf.st_ctime as _, // st_ctime_nsec: buf.st_ctime_nsec as _, ..mem::zeroed() } } #[inline] unsafe fn linux_path_to_windows(path: *const libc::c_char) -> CString { let path = CStr::from_ptr(path) .to_str() .expect("The provisioning path is UTF-8.") .replace('/', "\\"); // No null byte can appear when processing a C string. CString::new(path.trim_start_matches("\\\\?\\")).expect("The path contains a null byte??") } #[linux_cc] pub unsafe fn lstat(path: *const libc::c_char, buf: *mut stat) -> libc::c_int { let mut local_buf = mem::zeroed(); let return_code = libc::stat(linux_path_to_windows(path).as_ptr(), &mut local_buf); *buf = local_stat_to_linux(local_buf); return_code } #[linux_cc] pub unsafe fn fstat(fildes: libc::c_int, buf: *mut stat) -> libc::c_int { let mut local_buf = mem::zeroed(); let return_code = libc::fstat(fildes, &mut local_buf); *buf = local_stat_to_linux(local_buf); return_code } #[linux_cc] pub unsafe fn open(path: *const libc::c_char, oflag: libc::c_int) -> libc::c_int { let access = match oflag & 3 { O_WRONLY => libc::O_WRONLY, O_RDWR => libc::O_RDWR, _ => libc::O_RDONLY, }; let mut local_flag = access | libc::O_BINARY; for (linux, windows) in [ (O_CREAT, libc::O_CREAT), (0o200, libc::O_EXCL), (0o1000, libc::O_TRUNC), (0o2000, libc::O_APPEND), ] { if oflag & linux != 0 { local_flag |= windows; } } // The CRT requires a mode argument when creating a file. ADI uses private // provisioning files; Windows ACLs determine access beyond these mode bits. libc::open( linux_path_to_windows(path).as_ptr(), local_flag, libc::S_IREAD | libc::S_IWRITE, ) } #[cfg(test)] mod tests { use super::*; #[test] fn provisioning_files_round_trip_binary_data_and_report_linux_stat() { let directory = tempfile::tempdir().unwrap(); let path = directory.path().join("provisioning"); let path_c = CString::new(path.to_str().unwrap()).unwrap(); let data = [0, 10, 13, 10, 26, 255]; unsafe { let fd = open(path_c.as_ptr(), O_WRONLY | O_CREAT); assert!(fd >= 0); assert_eq!( write(fd, data.as_ptr().cast(), data.len() as _), data.len() as _ ); assert_eq!(close(fd), 0); assert_eq!(std::fs::read(&path).unwrap(), data); let fd = open(path_c.as_ptr(), O_RDONLY); assert!(fd >= 0); let mut actual = [0; 6]; assert_eq!(read(fd, actual.as_mut_ptr().cast(), actual.len() as _), 6); assert_eq!(actual, data); let mut stat = std::mem::zeroed(); assert_eq!(fstat(fd, &mut stat), 0); assert_eq!(stat.st_size, 6); assert_eq!(stat.st_mode & 0o170000, 0o100000); assert!(stat.st_mtime > 1_500_000_000); assert_eq!(close(fd), 0); let fd = open(path_c.as_ptr(), O_RDWR); assert_eq!(ftruncate(fd, 2), 0); assert_eq!(close(fd), 0); assert_eq!(std::fs::metadata(&path).unwrap().len(), 2); } } }