Files
RedBear-OS/src/header/sys_stat/mod.rs
T
2026-01-18 21:17:21 +01:00

243 lines
7.3 KiB
Rust

//! `sys/stat.h` implementation.
//!
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_stat.h.html>.
use crate::{
c_str::CStr,
error::ResultExt,
header::{
fcntl::{O_NOFOLLOW, O_PATH},
time::timespec,
},
out::Out,
platform::{
Pal, Sys,
types::{
blkcnt_t, blksize_t, c_char, c_int, dev_t, gid_t, ino_t, mode_t, nlink_t, off_t, uid_t,
useconds_t,
},
},
};
pub const S_IFMT: c_int = 0o0_170_000;
pub const S_IFDIR: c_int = 0o040_000;
pub const S_IFCHR: c_int = 0o020_000;
pub const S_IFBLK: c_int = 0o060_000;
pub const S_IFREG: c_int = 0o100_000;
pub const S_IFIFO: c_int = 0o010_000;
pub const S_IFLNK: c_int = 0o120_000;
pub const S_IFSOCK: c_int = 0o140_000;
pub const S_IRWXU: c_int = 0o0_700;
pub const S_IRUSR: c_int = 0o0_400;
pub const S_IWUSR: c_int = 0o0_200;
pub const S_IXUSR: c_int = 0o0_100;
// Defined for compatibility
pub const S_IREAD: c_int = S_IRUSR;
pub const S_IWRITE: c_int = S_IWUSR;
pub const S_IEXEC: c_int = S_IXUSR;
pub const S_IRWXG: c_int = 0o0_070;
pub const S_IRGRP: c_int = 0o0_040;
pub const S_IWGRP: c_int = 0o0_020;
pub const S_IXGRP: c_int = 0o0_010;
pub const S_IRWXO: c_int = 0o0_007;
pub const S_IROTH: c_int = 0o0_004;
pub const S_IWOTH: c_int = 0o0_002;
pub const S_IXOTH: c_int = 0o0_001;
pub const S_ISUID: c_int = 0o4_000;
pub const S_ISGID: c_int = 0o2_000;
pub const S_ISVTX: c_int = 0o1_000;
pub const UTIME_NOW: useconds_t = (1 << 30) - 1;
pub const UTIME_OMIT: useconds_t = (1 << 30) - 2;
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_stat.h.html>.
#[repr(C)]
#[derive(Default)]
pub struct stat {
pub st_dev: dev_t,
pub st_ino: ino_t,
pub st_nlink: nlink_t,
pub st_mode: mode_t,
pub st_uid: uid_t,
pub st_gid: gid_t,
pub st_rdev: dev_t,
pub st_size: off_t,
pub st_blksize: blksize_t,
pub st_blocks: blkcnt_t,
pub st_atim: timespec,
pub st_mtim: timespec,
pub st_ctim: timespec,
// Compared to glibc, our struct is for some reason 24 bytes too small.
// Accessing atime works, so clearly the struct isn't incorrect...
// This works.
pub _pad: [c_char; 24],
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/chmod.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn chmod(path: *const c_char, mode: mode_t) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::chmod(path, mode).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fchmod.html>.
#[unsafe(no_mangle)]
pub extern "C" fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
Sys::fchmod(fildes, mode).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fchmodat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn fchmodat(
dirfd: c_int,
path: *const c_char,
mode: mode_t,
flags: c_int,
) -> c_int {
let path = unsafe { CStr::from_nullable_ptr(path) };
Sys::fchmodat(dirfd, path, mode, flags)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fstat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
let buf = unsafe { Out::nonnull(buf) };
Sys::fstat(fildes, buf).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fstatat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn fstatat(
fildes: c_int,
path: *const c_char,
buf: *mut stat,
flags: c_int,
) -> c_int {
let path = unsafe { CStr::from_nullable_ptr(path) };
let buf = unsafe { Out::nonnull(buf) };
Sys::fstatat(fildes, path, buf, flags)
.map(|()| 0)
.or_minus_one_errno()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __fxstat(_ver: c_int, fildes: c_int, buf: *mut stat) -> c_int {
unsafe { fstat(fildes, buf) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/futimens.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
unsafe { Sys::futimens(fd, times) }
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/lstat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
let buf = unsafe { Out::nonnull(buf) };
// TODO: Rustify
let fd = Sys::open(path, O_PATH | O_NOFOLLOW, 0).or_minus_one_errno();
if fd < 0 {
return -1;
}
// TODO: Rustify
let res = Sys::fstat(fd, buf).map(|()| 0).or_minus_one_errno();
Sys::close(fd);
res
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkdirat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mkdirat(dirfd: c_int, path: *const c_char, mode: mode_t) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::mkdirat(dirfd, path, mode)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkdir.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::mkdir(path, mode).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkfifoat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mkfifoat(dirfd: c_int, path: *const c_char, mode: mode_t) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::mkfifoat(dirfd, path, mode)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/mkfifo.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::mkfifo(path, mode).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/mknod.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mknod(path: *const c_char, mode: mode_t, dev: dev_t) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::mknod(path, mode, dev).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/mknodat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mknodat(
dirfd: c_int,
path: *const c_char,
mode: mode_t,
dev: dev_t,
) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::mknodat(dirfd, path, mode, dev)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/stat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn stat(file: *const c_char, buf: *mut stat) -> c_int {
let file = unsafe { CStr::from_ptr(file) };
let buf = unsafe { Out::nonnull(buf) };
// TODO: Rustify
let fd = Sys::open(file, O_PATH, 0).or_minus_one_errno();
if fd < 0 {
return -1;
}
// TODO: Rustify
let res = Sys::fstat(fd, buf).map(|()| 0).or_minus_one_errno();
Sys::close(fd);
res
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/umask.html>.
#[unsafe(no_mangle)]
pub extern "C" fn umask(mask: mode_t) -> mode_t {
Sys::umask(mask)
}