180 lines
4.5 KiB
Rust
180 lines
4.5 KiB
Rust
use core::ffi::{c_char, c_int, c_short, VaList};
|
|
|
|
use yggdrasil_rt::io::{FileMode, OpenOptions};
|
|
|
|
use crate::{
|
|
error::{CFdResult, CIntCountResult, EResult, TryFromExt},
|
|
io::{raw::RawFile, IntoRawFd},
|
|
util::{self, PointerStrExt},
|
|
};
|
|
|
|
use super::{
|
|
errno,
|
|
sys_types::{mode_t, off_t, pid_t},
|
|
};
|
|
|
|
// TODO:
|
|
// POSIX_FADV_DONTNEED
|
|
// POSIX_FADV_NOREUSE
|
|
// POSIX_FADV_NORMAL
|
|
// POSIX_FADV_RANDOM
|
|
// POSIX_FADV_SEQUENTIAL
|
|
// POSIX_FADV_WILLNEED
|
|
// int posix_fadvise(int, off_t, off_t, int);
|
|
// int posix_fallocate(int, off_t, off_t);
|
|
|
|
#[repr(C)]
|
|
pub struct flock {
|
|
pub l_type: c_short,
|
|
pub l_whence: c_short,
|
|
pub l_start: off_t,
|
|
pub l_len: off_t,
|
|
pub l_pid: pid_t,
|
|
}
|
|
|
|
pub const F_DUPFD: c_int = 1;
|
|
pub const F_DUPFD_CLOEXEC: c_int = 2;
|
|
pub const F_GETFD: c_int = 3;
|
|
pub const F_SETFD: c_int = 4;
|
|
pub const F_GETFL: c_int = 5;
|
|
pub const F_SETFL: c_int = 6;
|
|
pub const F_GETLK: c_int = 7;
|
|
pub const F_SETLK: c_int = 8;
|
|
pub const F_SETLKW: c_int = 9;
|
|
pub const F_GETOWN: c_int = 10;
|
|
pub const F_SETOWN: c_int = 11;
|
|
|
|
pub const FD_CLOEXEC: c_int = 1 << 0;
|
|
|
|
pub const F_RDLCK: c_int = 1;
|
|
pub const F_UNLCK: c_int = 2;
|
|
pub const F_WRLCK: c_int = 3;
|
|
|
|
pub const O_CLOEXEC: c_int = 1 << 16;
|
|
pub const O_CREAT: c_int = 1 << 17;
|
|
pub const O_DIRECTORY: c_int = 1 << 18;
|
|
pub const O_EXCL: c_int = 1 << 19;
|
|
pub const O_NOCTTY: c_int = 1 << 20;
|
|
pub const O_NOFOLLOW: c_int = 1 << 21;
|
|
pub const O_TRUNC: c_int = 1 << 22;
|
|
pub const O_TTY_INIT: c_int = 1 << 23;
|
|
|
|
pub const O_APPEND: c_int = 1 << 24;
|
|
pub const O_DSYNC: c_int = 1 << 25;
|
|
pub const O_NONBLOCK: c_int = 1 << 26;
|
|
pub const O_RSYNC: c_int = 1 << 27;
|
|
pub const O_SYNC: c_int = 1 << 28;
|
|
|
|
pub const O_ACCMODE: c_int = 0xFF;
|
|
pub const O_RDONLY: c_int = 1;
|
|
pub const O_WRONLY: c_int = 2;
|
|
pub const O_RDWR: c_int = 3;
|
|
pub const O_EXEC: c_int = 4;
|
|
pub const O_SEARCH: c_int = 5;
|
|
|
|
pub const AT_FDCWD: c_int = -65536;
|
|
|
|
pub const AT_EACCESS: c_int = 1 << 0;
|
|
pub const AT_SYMLINK_NOFOLLOW: c_int = 1 << 1;
|
|
pub const AT_REMOVEDIR: c_int = 1 << 2;
|
|
|
|
enum OpenMode {
|
|
File(OpenOptions, FileMode),
|
|
Directory,
|
|
}
|
|
|
|
fn open_opts(opts: c_int, ap: &mut VaList) -> EResult<OpenMode> {
|
|
if opts & O_DIRECTORY != 0 {
|
|
if opts & !O_DIRECTORY != 0 {
|
|
todo!();
|
|
}
|
|
|
|
return EResult::Ok(OpenMode::Directory);
|
|
}
|
|
|
|
let need_mode = opts & O_CREAT != 0;
|
|
let mut res = OpenOptions::empty();
|
|
|
|
match opts & O_ACCMODE {
|
|
O_RDONLY => res |= OpenOptions::READ,
|
|
O_WRONLY => res |= OpenOptions::WRITE,
|
|
O_RDWR => res |= OpenOptions::READ | OpenOptions::WRITE,
|
|
O_EXEC => todo!(),
|
|
O_SEARCH => todo!(),
|
|
_ => {
|
|
return EResult::Err(errno::EINVAL);
|
|
}
|
|
}
|
|
|
|
if opts & O_CREAT != 0 {
|
|
res |= OpenOptions::CREATE;
|
|
}
|
|
if opts & O_EXCL != 0 {
|
|
res |= OpenOptions::CREATE_EXCL;
|
|
}
|
|
if opts & O_APPEND != 0 {
|
|
res |= OpenOptions::APPEND;
|
|
}
|
|
if opts & O_TRUNC != 0 {
|
|
res |= OpenOptions::TRUNCATE;
|
|
}
|
|
if opts
|
|
& (O_DSYNC | O_RSYNC | O_SYNC | O_TTY_INIT | O_NONBLOCK | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY)
|
|
!= 0
|
|
{
|
|
todo!();
|
|
}
|
|
|
|
let mode = if need_mode {
|
|
let _raw = unsafe { ap.arg::<c_int>() };
|
|
todo!();
|
|
} else {
|
|
FileMode::empty()
|
|
};
|
|
|
|
EResult::Ok(OpenMode::File(res, mode))
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, _args: ...) -> CIntCountResult {
|
|
// TODO kernel support for fcntl
|
|
let _file = RawFile::e_try_from(fd)?;
|
|
|
|
match cmd {
|
|
_ => todo!("fcntl({}, {}, ...)", fd, cmd),
|
|
}
|
|
}
|
|
|
|
unsafe fn vopenat(atfd: c_int, pathname: *const c_char, opts: c_int, mut ap: VaList) -> CFdResult {
|
|
let atfd = util::at_fd(atfd)?;
|
|
let pathname = pathname.ensure_str();
|
|
|
|
let fd = match open_opts(opts, &mut ap)? {
|
|
OpenMode::File(opts, mode) => RawFile::open_at(atfd, pathname, opts, mode)?.into_raw_fd(),
|
|
OpenMode::Directory => todo!(),
|
|
};
|
|
|
|
CFdResult::success(fd)
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn creat(pathname: *const c_char, mode: mode_t) -> CFdResult {
|
|
openat(AT_FDCWD, pathname, O_CREAT | O_WRONLY | O_TRUNC, mode)
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn open(pathname: *const c_char, opts: c_int, mut args: ...) -> CFdResult {
|
|
yggdrasil_rt::debug_trace!("&errno = {:p}", &crate::error::errno);
|
|
vopenat(AT_FDCWD, pathname, opts, args.as_va_list())
|
|
}
|
|
|
|
#[no_mangle]
|
|
unsafe extern "C" fn openat(
|
|
atfd: c_int,
|
|
pathname: *const c_char,
|
|
opts: c_int,
|
|
mut args: ...
|
|
) -> CFdResult {
|
|
vopenat(atfd, pathname, opts, args.as_va_list())
|
|
}
|