257 lines
5.9 KiB
Rust
257 lines
5.9 KiB
Rust
use core::{
|
|
ffi::{c_char, c_int, CStr},
|
|
mem::MaybeUninit,
|
|
};
|
|
|
|
use yggdrasil_rt::{
|
|
io::{FileAttr, FileMode, FileType, RawFd},
|
|
path::Path,
|
|
sys as syscall,
|
|
};
|
|
|
|
use crate::{
|
|
error::{self, CZeroResult, EResult},
|
|
io,
|
|
util::Nullable,
|
|
};
|
|
|
|
use super::{
|
|
errno::{Errno, EBADF},
|
|
fcntl::{AT_FDCWD, AT_SYMLINK_NOFOLLOW},
|
|
sys_types::{blkcnt_t, blksize_t, dev_t, gid_t, ino_t, mode_t, nlink_t, off_t, uid_t},
|
|
time::{__ygg_timespec_t, timespec},
|
|
};
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
|
#[repr(C)]
|
|
pub struct stat {
|
|
pub st_dev: dev_t,
|
|
pub st_ino: ino_t,
|
|
pub st_mode: mode_t,
|
|
pub st_nlink: nlink_t,
|
|
pub st_uid: uid_t,
|
|
pub st_gid: gid_t,
|
|
pub st_rdev: dev_t,
|
|
pub st_size: off_t,
|
|
pub st_atim: __ygg_timespec_t,
|
|
pub st_mtim: __ygg_timespec_t,
|
|
pub st_ctim: __ygg_timespec_t,
|
|
pub st_blksize: blksize_t,
|
|
pub st_blocks: blkcnt_t,
|
|
}
|
|
|
|
pub const S_IFMT: c_int = 0xF << 16;
|
|
pub const S_IFBLK: c_int = 1 << 16;
|
|
pub const S_IFCHR: c_int = 2 << 16;
|
|
pub const S_IFIFO: c_int = 3 << 16;
|
|
pub const S_IFREG: c_int = 4 << 16;
|
|
pub const S_IFDIR: c_int = 5 << 16;
|
|
pub const S_IFLNK: c_int = 6 << 16;
|
|
pub const S_IFSOCK: c_int = 7 << 16;
|
|
|
|
pub const S_IRWXU: c_int = 0x7 << 6;
|
|
pub const S_IRUSR: c_int = 0x4 << 6;
|
|
pub const S_IWUSR: c_int = 0x2 << 6;
|
|
pub const S_IXUSR: c_int = 0x1 << 6;
|
|
|
|
pub const S_IRWXG: c_int = 0x7 << 3;
|
|
pub const S_IRGRP: c_int = 0x4 << 3;
|
|
pub const S_IWGRP: c_int = 0x2 << 3;
|
|
pub const S_IXGRP: c_int = 0x1 << 3;
|
|
|
|
pub const S_IRWXO: c_int = 0x7 << 0;
|
|
pub const S_IROTH: c_int = 0x4 << 0;
|
|
pub const S_IWOTH: c_int = 0x2 << 0;
|
|
pub const S_IXOTH: c_int = 0x1 << 0;
|
|
|
|
pub const S_ISUID: c_int = 1 << 11;
|
|
pub const S_ISGID: c_int = 1 << 10;
|
|
pub const S_ISVTX: c_int = 1 << 9;
|
|
|
|
impl From<FileAttr> for stat {
|
|
fn from(value: FileAttr) -> Self {
|
|
// TODO no translation for st_dev/st_rdev/st_ino/etc
|
|
let mut st = Self::default();
|
|
st.st_mode = (value.mode.bits() & 0o777) as _;
|
|
match value.ty {
|
|
FileType::Block => st.st_mode |= S_IFBLK,
|
|
FileType::Char => st.st_mode |= S_IFCHR,
|
|
FileType::File => st.st_mode |= S_IFREG,
|
|
FileType::Directory => st.st_mode |= S_IFDIR,
|
|
FileType::Symlink => st.st_mode |= S_IFLNK,
|
|
}
|
|
st.st_size = value.size.try_into().unwrap();
|
|
// TODO
|
|
st.st_uid = 0;
|
|
st.st_gid = 0;
|
|
// TODO
|
|
st.st_blksize = 512;
|
|
st.st_blocks = (st.st_size + 511) / 512;
|
|
// TODO
|
|
st.st_nlink = 1;
|
|
|
|
st
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn chmod(pathname: *const c_char, mode: mode_t) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn fchmod(fd: c_int, mode: mode_t) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn fchmodat(
|
|
fd: c_int,
|
|
pathname: *const c_char,
|
|
mode: mode_t,
|
|
opt: c_int,
|
|
) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn umask(mode: mode_t) -> mode_t {
|
|
todo!()
|
|
}
|
|
|
|
// Create stuff
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn mkdir(pathname: *const c_char, mode: mode_t) -> c_int {
|
|
mkdirat(AT_FDCWD, pathname, mode)
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn mkdirat(atfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int {
|
|
pathname.ensure();
|
|
let pathname = CStr::from_ptr(pathname).to_str().unwrap();
|
|
|
|
// TODO move this to a function
|
|
let atfd = match atfd {
|
|
// Same as stat()
|
|
AT_FDCWD => None,
|
|
0.. => Some(RawFd(atfd as _)),
|
|
_ => {
|
|
error::set_errno(EBADF);
|
|
return -1;
|
|
}
|
|
};
|
|
|
|
let mode = FileMode::new((mode & 0o777) as u32);
|
|
|
|
io::create_directory(atfd, pathname, mode).into_zero_status()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn mkfifo(pathname: *const c_char, mode: mode_t) -> c_int {
|
|
unimplemented!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn mkfifoat(atfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int {
|
|
unimplemented!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn mknod(pathname: *const c_char, mode: mode_t, dev: dev_t) -> c_int {
|
|
unimplemented!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn mknodat(
|
|
atfd: c_int,
|
|
pathname: *const c_char,
|
|
mode: mode_t,
|
|
dev: dev_t,
|
|
) -> c_int {
|
|
unimplemented!()
|
|
}
|
|
|
|
// File status
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn fstat(fd: c_int, statbuf: *mut stat) -> c_int {
|
|
if fd < 0 {
|
|
error::set_errno(EBADF);
|
|
return -1;
|
|
}
|
|
|
|
let attr = match io::get_metadata(Some(RawFd(fd as _)), "", false) {
|
|
Ok(attr) => attr,
|
|
Err(_) => return -1,
|
|
};
|
|
|
|
if let Some(statbuf) = statbuf.as_mut() {
|
|
*statbuf = attr.into();
|
|
}
|
|
|
|
0
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn fstatat(
|
|
atfd: c_int,
|
|
pathname: *const c_char,
|
|
statbuf: *mut stat,
|
|
opt: c_int,
|
|
) -> c_int {
|
|
pathname.ensure();
|
|
let pathname = CStr::from_ptr(pathname).to_str().unwrap();
|
|
|
|
// TODO move this to a function
|
|
let atfd = match atfd {
|
|
// Same as stat()
|
|
AT_FDCWD => None,
|
|
0.. => Some(RawFd(atfd as _)),
|
|
_ => {
|
|
error::set_errno(EBADF);
|
|
return -1;
|
|
}
|
|
};
|
|
|
|
let follow = opt & AT_SYMLINK_NOFOLLOW == 0;
|
|
|
|
let attr = match io::get_metadata(atfd, pathname, follow) {
|
|
Ok(attr) => attr,
|
|
Err(_) => return -1,
|
|
};
|
|
|
|
if let Some(statbuf) = statbuf.as_mut() {
|
|
*statbuf = attr.into();
|
|
}
|
|
|
|
0
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn lstat(pathname: *const c_char, statbuf: *mut stat) -> c_int {
|
|
fstatat(AT_FDCWD, pathname, statbuf, AT_SYMLINK_NOFOLLOW)
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn stat(pathname: *const c_char, statbuf: *mut stat) -> c_int {
|
|
fstatat(AT_FDCWD, pathname, statbuf, 0)
|
|
}
|
|
|
|
// File time updates
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn futimens(fd: c_int, times: *const __ygg_timespec_t) -> c_int {
|
|
todo!()
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn utimensat(
|
|
atfd: c_int,
|
|
pathname: *const c_char,
|
|
times: *const __ygg_timespec_t,
|
|
opt: c_int,
|
|
) -> c_int {
|
|
todo!()
|
|
}
|