Move more I/O operations into Rust

This commit is contained in:
topjohnwu
2023-09-26 20:18:37 -07:00
parent 5d07d0b964
commit a55d570213
13 changed files with 470 additions and 257 deletions

View File

@@ -3,12 +3,15 @@
use std::io;
use std::os::fd::{BorrowedFd, OwnedFd, RawFd};
use cfg_if::cfg_if;
use cxx::private::c_char;
use libc::mode_t;
use crate::logging::CxxResultExt;
pub(crate) use crate::xwrap::*;
use crate::{fd_path, map_fd, map_file, Directory, FsPath, Utf8CStr, Utf8CStrSlice};
use crate::{
clone_attr, fclone_attr, fd_path, map_fd, map_file, Directory, FsPath, Utf8CStr, Utf8CStrSlice,
};
pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize {
let mut buf = Utf8CStrSlice::from(buf);
@@ -69,3 +72,102 @@ pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8
.unwrap_or(&mut [])
}
}
pub(crate) unsafe fn readlinkat_for_cxx(
dirfd: RawFd,
path: *const c_char,
buf: *mut u8,
bufsz: usize,
) -> isize {
// readlinkat() may fail on x86 platform, returning random value
// instead of number of bytes placed in buf (length of link)
cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
libc::memset(buf.cast(), 0, bufsz);
let mut r = libc::readlinkat(dirfd, path, buf.cast(), bufsz - 1);
if r > 0 {
r = libc::strlen(buf.cast()) as isize;
}
} else {
let r = libc::readlinkat(dirfd, path, buf.cast(), bufsz - 1);
if r >= 0 {
*buf.offset(r) = b'\0';
}
}
}
r
}
#[export_name = "cp_afc"]
unsafe extern "C" fn cp_afc_for_cxx(src: *const c_char, dest: *const c_char) -> bool {
if let Ok(src) = Utf8CStr::from_ptr(src) {
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
let src = FsPath::from(src);
let dest = FsPath::from(dest);
return src
.copy_to(dest)
.log_cxx_with_msg(|w| {
w.write_fmt(format_args!("cp_afc {} -> {} failed", src, dest))
})
.is_ok();
}
}
false
}
#[export_name = "mv_path"]
unsafe extern "C" fn mv_path_for_cxx(src: *const c_char, dest: *const c_char) -> bool {
if let Ok(src) = Utf8CStr::from_ptr(src) {
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
let src = FsPath::from(src);
let dest = FsPath::from(dest);
return src
.move_to(dest)
.log_cxx_with_msg(|w| {
w.write_fmt(format_args!("mv_path {} -> {} failed", src, dest))
})
.is_ok();
}
}
false
}
#[export_name = "link_path"]
unsafe extern "C" fn link_path_for_cxx(src: *const c_char, dest: *const c_char) -> bool {
if let Ok(src) = Utf8CStr::from_ptr(src) {
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
let src = FsPath::from(src);
let dest = FsPath::from(dest);
return src
.link_to(dest)
.log_cxx_with_msg(|w| {
w.write_fmt(format_args!("link_path {} -> {} failed", src, dest))
})
.is_ok();
}
}
false
}
#[export_name = "clone_attr"]
unsafe extern "C" fn clone_attr_for_cxx(src: *const c_char, dest: *const c_char) -> bool {
if let Ok(src) = Utf8CStr::from_ptr(src) {
if let Ok(dest) = Utf8CStr::from_ptr(dest) {
let src = FsPath::from(src);
let dest = FsPath::from(dest);
return clone_attr(src, dest)
.log_cxx_with_msg(|w| {
w.write_fmt(format_args!("clone_attr {} -> {} failed", src, dest))
})
.is_ok();
}
}
false
}
#[export_name = "fclone_attr"]
unsafe extern "C" fn fclone_attr_for_cxx(a: RawFd, b: RawFd) -> bool {
fclone_attr(a, b)
.log_cxx_with_msg(|w| w.write_str("fclone_attr failed"))
.is_ok()
}