use std::os::raw::c_char;
pub unsafe fn real_stat(path: *const c_char, buf: *mut libc::stat) -> i32 {
unsafe { libc::stat(path, buf) }
}
pub unsafe fn real_fstat(fd: i32, buf: *mut libc::stat) -> i32 {
unsafe { libc::fstat(fd, buf) }
}
pub unsafe fn real_lstat(path: *const c_char, buf: *mut libc::stat) -> i32 {
unsafe { libc::lstat(path, buf) }
}
pub unsafe fn real_fstatat(
dirfd: i32,
pathname: *const c_char,
buf: *mut libc::stat,
flags: i32,
) -> i32 {
unsafe { libc::fstatat(dirfd, pathname, buf, flags) }
}
pub unsafe fn real_chmod(path: *const c_char, mode: libc::mode_t) -> i32 {
unsafe { libc::chmod(path, mode) }
}
pub unsafe fn real_fchmod(fd: i32, mode: libc::mode_t) -> i32 {
unsafe { libc::fchmod(fd, mode) }
}
pub unsafe fn real_fchmodat(
dirfd: i32,
path: *const c_char,
mode: libc::mode_t,
flags: i32,
) -> i32 {
unsafe { libc::fchmodat(dirfd, path, mode, flags) }
}
pub unsafe fn real_unlink(path: *const c_char) -> i32 {
unsafe { libc::unlink(path) }
}
pub unsafe fn real_unlinkat(dirfd: i32, path: *const c_char, flags: i32) -> i32 {
unsafe { libc::unlinkat(dirfd, path, flags) }
}
pub unsafe fn real_rmdir(path: *const c_char) -> i32 {
unsafe { libc::rmdir(path) }
}
pub unsafe fn real_rename(oldpath: *const c_char, newpath: *const c_char) -> i32 {
unsafe { libc::rename(oldpath, newpath) }
}
pub unsafe fn real_renameat(
olddirfd: i32,
oldpath: *const c_char,
newdirfd: i32,
newpath: *const c_char,
) -> i32 {
unsafe { libc::renameat(olddirfd, oldpath, newdirfd, newpath) }
}
pub unsafe fn real_mknod(pathname: *const c_char, mode: libc::mode_t, dev: libc::dev_t) -> i32 {
unsafe { libc::mknod(pathname, mode, dev) }
}
pub unsafe fn real_mknodat(
dirfd: i32,
pathname: *const c_char,
mode: libc::mode_t,
dev: libc::dev_t,
) -> i32 {
unsafe { libc::mknodat(dirfd, pathname, mode, dev) }
}
unsafe fn getxattr_impl(
path: *const c_char,
name: *const c_char,
value: *mut std::ffi::c_void,
size: libc::size_t,
options: i32,
) -> i32 {
let ret = unsafe { libc::getxattr(path, name, value, size, 0, options) };
ret.try_into().unwrap_or(-1)
}
pub unsafe fn real_getxattr(
path: *const c_char,
name: *const c_char,
value: *mut std::ffi::c_void,
size: libc::size_t,
) -> i32 {
unsafe { getxattr_impl(path, name, value, size, 0) }
}
pub unsafe fn real_lgetxattr(
path: *const c_char,
name: *const c_char,
value: *mut std::ffi::c_void,
size: libc::size_t,
) -> i32 {
unsafe { getxattr_impl(path, name, value, size, libc::XATTR_NOFOLLOW) }
}
pub unsafe fn real_fgetxattr(
fd: i32,
name: *const c_char,
value: *mut std::ffi::c_void,
size: libc::size_t,
) -> i32 {
let ret = unsafe { libc::fgetxattr(fd, name, value, size, 0, 0) };
ret.try_into().unwrap_or(-1)
}
unsafe fn listxattr_impl(
path: *const c_char,
list: *mut c_char,
size: libc::size_t,
options: i32,
) -> i32 {
let ret = unsafe { libc::listxattr(path, list, size, options) };
ret.try_into().unwrap_or(-1)
}
pub unsafe fn real_listxattr(path: *const c_char, list: *mut c_char, size: libc::size_t) -> i32 {
unsafe { listxattr_impl(path, list, size, 0) }
}
pub unsafe fn real_llistxattr(path: *const c_char, list: *mut c_char, size: libc::size_t) -> i32 {
unsafe { listxattr_impl(path, list, size, libc::XATTR_NOFOLLOW) }
}
pub unsafe fn real_flistxattr(fd: i32, list: *mut c_char, size: libc::size_t) -> i32 {
let ret = unsafe { libc::flistxattr(fd, list, size, 0) };
ret.try_into().unwrap_or(-1)
}
mod macos_xattr {
use crate::ownership::{
fake_getxattr_fd, fake_getxattr_path, fake_listxattr_fd, fake_listxattr_path,
fake_removexattr_fd, fake_removexattr_path, fake_setxattr_fd, fake_setxattr_path,
};
use std::os::raw::c_char;
#[inline]
fn nofollow(options: i32) -> bool {
options & libc::XATTR_NOFOLLOW != 0
}
pub extern "C" fn setxattr(
path: *const c_char,
name: *const c_char,
value: *const std::ffi::c_void,
size: libc::size_t,
_position: u32,
options: i32,
) -> i32 {
fake_setxattr_path(path, name, value, size, nofollow(options))
}
pub extern "C" fn fsetxattr(
fd: i32,
name: *const c_char,
value: *const std::ffi::c_void,
size: libc::size_t,
_position: u32,
_options: i32,
) -> i32 {
fake_setxattr_fd(fd, name, value, size)
}
pub extern "C" fn getxattr(
path: *const c_char,
name: *const c_char,
value: *mut std::ffi::c_void,
size: libc::size_t,
_position: u32,
options: i32,
) -> isize {
fake_getxattr_path(path, name, value, size, nofollow(options)) as isize
}
pub extern "C" fn fgetxattr(
fd: i32,
name: *const c_char,
value: *mut std::ffi::c_void,
size: libc::size_t,
_position: u32,
_options: i32,
) -> isize {
fake_getxattr_fd(fd, name, value, size) as isize
}
pub extern "C" fn listxattr(
path: *const c_char,
list: *mut c_char,
size: libc::size_t,
options: i32,
) -> isize {
fake_listxattr_path(path, list, size, nofollow(options)) as isize
}
pub extern "C" fn flistxattr(
fd: i32,
list: *mut c_char,
size: libc::size_t,
_options: i32,
) -> isize {
fake_listxattr_fd(fd, list, size) as isize
}
pub extern "C" fn removexattr(path: *const c_char, name: *const c_char, options: i32) -> i32 {
fake_removexattr_path(path, name, nofollow(options))
}
pub extern "C" fn fremovexattr(fd: i32, name: *const c_char, _options: i32) -> i32 {
fake_removexattr_fd(fd, name)
}
}
mod interpose {
#[repr(C)]
struct InterposeEntry {
replacement: *const (),
replacee: *const (),
}
unsafe impl Sync for InterposeEntry {}
macro_rules! interpose {
($($entry:ident: $replacee:path => $replacement:path;)+) => {
$(
#[used]
#[unsafe(link_section = "__DATA,__interpose")]
static $entry: InterposeEntry = InterposeEntry {
replacement: $replacement as *const (),
replacee: $replacee as *const (),
};
)+
};
}
interpose! {
GETUID: libc::getuid => crate::getuid;
GETEUID: libc::geteuid => crate::geteuid;
GETGID: libc::getgid => crate::getgid;
GETEGID: libc::getegid => crate::getegid;
SETUID: libc::setuid => crate::setuid;
SETGID: libc::setgid => crate::setgid;
SETREUID: libc::setreuid => crate::setreuid;
SETREGID: libc::setregid => crate::setregid;
SETGROUPS: libc::setgroups => crate::setgroups;
CHOWN: libc::chown => crate::chown;
LCHOWN: libc::lchown => crate::lchown;
FCHOWN: libc::fchown => crate::fchown;
FCHOWNAT: libc::fchownat => crate::fchownat;
STAT: libc::stat => crate::stat;
FSTAT: libc::fstat => crate::fstat;
LSTAT: libc::lstat => crate::lstat;
FSTATAT: libc::fstatat => crate::fstatat;
CHMOD: libc::chmod => crate::chmod;
FCHMOD: libc::fchmod => crate::fchmod;
FCHMODAT: libc::fchmodat => crate::fchmodat;
UNLINK: libc::unlink => crate::unlink;
UNLINKAT: libc::unlinkat => crate::unlinkat;
RMDIR: libc::rmdir => crate::rmdir;
RENAME: libc::rename => crate::rename;
RENAMEAT: libc::renameat => crate::renameat;
MKNOD: libc::mknod => crate::mknod;
MKNODAT: libc::mknodat => crate::mknodat;
SETXATTR: libc::setxattr => super::macos_xattr::setxattr;
FSETXATTR: libc::fsetxattr => super::macos_xattr::fsetxattr;
GETXATTR: libc::getxattr => super::macos_xattr::getxattr;
FGETXATTR: libc::fgetxattr => super::macos_xattr::fgetxattr;
LISTXATTR: libc::listxattr => super::macos_xattr::listxattr;
FLISTXATTR: libc::flistxattr => super::macos_xattr::flistxattr;
REMOVEXATTR: libc::removexattr => super::macos_xattr::removexattr;
FREMOVEXATTR: libc::fremovexattr => super::macos_xattr::fremovexattr;
}
}