use std::{
ffi::c_void,
os::fd::{AsRawFd, BorrowedFd},
path::Path,
};
use crate::PosixError;
use libc::{self, c_char, c_int, c_uint, off_t, size_t, ssize_t};
use super::{StatFs, cstring_from_path};
pub(crate) fn get_errno() -> i32 {
unsafe { *libc::__errno_location() }
}
pub(super) fn set_errno(errno: i32) {
unsafe { *libc::__errno_location() = errno };
}
pub(super) unsafe fn renameat2(
olddirfd: c_int,
oldpath: *const c_char,
newdirfd: c_int,
newpath: *const c_char,
flags: c_uint,
) -> c_int {
unsafe { libc::renameat2(olddirfd, oldpath, newdirfd, newpath, flags) }
}
pub(super) unsafe fn fdatasync(fd: c_int) -> c_int {
unsafe { libc::fdatasync(fd) }
}
pub(super) unsafe fn fallocate(fd: c_int, mode: c_int, offset: off_t, len: off_t) -> c_int {
unsafe { libc::fallocate(fd, mode, offset, len) }
}
pub(super) unsafe fn setxattr(
path: *const c_char,
name: *const c_char,
value: *const c_void,
size: size_t,
_position: u32,
flags: c_int,
) -> c_int {
unsafe { libc::setxattr(path, name, value, size, flags) }
}
pub(super) unsafe fn getxattr(
path: *const c_char,
name: *const c_char,
value: *mut c_void,
size: size_t,
) -> ssize_t {
unsafe { libc::getxattr(path, name, value, size) }
}
pub(super) unsafe fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t {
unsafe { libc::listxattr(path, list, size) }
}
pub(super) unsafe fn removexattr(path: *const c_char, name: *const c_char) -> c_int {
unsafe { libc::removexattr(path, name) }
}
pub fn statfs(path: &Path) -> Result<StatFs, PosixError> {
let c_path = cstring_from_path(path)?;
let mut stat: libc::statvfs64 = unsafe { std::mem::zeroed() };
let result = unsafe { libc::statvfs64(c_path.as_ptr(), &mut stat) };
if result != 0 {
return Err(PosixError::last_error(format!(
"{}: statfs failed",
path.display()
)));
}
Ok(StatFs {
total_blocks: stat.f_blocks as u64,
free_blocks: stat.f_bfree as u64,
available_blocks: stat.f_bavail as u64,
total_files: stat.f_files as u64,
free_files: stat.f_ffree as u64,
block_size: stat.f_bsize as u32,
max_filename_length: stat.f_namemax as u32,
fragment_size: stat.f_frsize as u32,
})
}
pub fn copy_file_range(
fd_in: BorrowedFd,
offset_in: i64,
fd_out: BorrowedFd,
offset_out: i64,
len: u64,
) -> Result<u32, PosixError> {
let result = unsafe {
libc::copy_file_range(
fd_in.as_raw_fd(),
offset_in as *mut libc::off_t,
fd_out.as_raw_fd(),
offset_out as *mut libc::off_t,
len as usize,
0, )
};
if result == -1 {
return Err(PosixError::last_error("copyfilerange failed"));
}
Ok(result as u32)
}