use core::ffi::CStr;
use errno::{set_errno, Errno};
use rustix::fd::{BorrowedFd, IntoRawFd};
use rustix::fs::{Mode, OFlags, CWD};
use libc::{c_char, c_int, mode_t};
use crate::convert_res;
macro_rules! openat_impl {
($fd:expr, $pathname:ident, $flags:ident, $args:ident) => {{
let flags = OFlags::from_bits($flags as _).unwrap();
let mode = if flags.contains(OFlags::CREATE) || flags.contains(OFlags::TMPFILE) {
let mode: libc::mode_t = $args.arg();
Mode::from_bits((mode & !libc::S_IFMT) as _).unwrap()
} else {
Mode::empty()
};
match convert_res(rustix::fs::openat(
&$fd,
CStr::from_ptr($pathname.cast()),
flags,
mode,
)) {
Some(fd) => fd.into_raw_fd(),
None => -1,
}
}};
}
#[no_mangle]
unsafe extern "C" fn open(pathname: *const c_char, flags: c_int, mut args: ...) -> c_int {
libc!(libc::open(pathname, flags, args));
openat_impl!(CWD, pathname, flags, args)
}
#[no_mangle]
unsafe extern "C" fn open64(pathname: *const c_char, flags: c_int, mut args: ...) -> c_int {
libc!(libc::open64(pathname, flags, args));
openat_impl!(CWD, pathname, flags, args)
}
#[no_mangle]
unsafe extern "C" fn openat(
fd: c_int,
pathname: *const c_char,
flags: c_int,
mut args: ...
) -> c_int {
libc!(libc::openat(fd, pathname, flags, args));
openat_impl!(BorrowedFd::borrow_raw(fd), pathname, flags, args)
}
#[no_mangle]
unsafe extern "C" fn openat64(
fd: c_int,
pathname: *const c_char,
flags: c_int,
mut args: ...
) -> c_int {
libc!(libc::openat64(fd, pathname, flags, args));
openat_impl!(BorrowedFd::borrow_raw(fd), pathname, flags, args)
}
#[no_mangle]
unsafe extern "C" fn creat(name: *const c_char, mode: mode_t) -> c_int {
libc!(libc::creat(name, mode));
creat64(name, mode)
}
#[no_mangle]
unsafe extern "C" fn creat64(name: *const c_char, mode: mode_t) -> c_int {
libc!(libc::creat64(name, mode));
open(name, libc::O_CREAT | libc::O_WRONLY | libc::O_TRUNC, mode)
}
#[no_mangle]
unsafe extern "C" fn close(fd: c_int) -> c_int {
libc!(libc::close(fd));
if fd == -1 {
set_errno(Errno(libc::EBADF));
return -1;
}
rustix::io::close(fd);
0
}