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 { 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::() }; 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()) }