libc: add pwd.h, dirent.h, fcntl.h, setjmp.h, signal.h
This commit is contained in:
parent
4519e5385a
commit
457e82d2e3
8
userspace/lib/ygglibc/include/bits/dirent.h
Normal file
8
userspace/lib/ygglibc/include/bits/dirent.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _YGGDRASIL_DIRENT
|
||||
#define _YGGDRASIL_DIRENT 1
|
||||
|
||||
struct __DIR;
|
||||
|
||||
typedef struct __DIR DIR;
|
||||
|
||||
#endif
|
8
userspace/lib/ygglibc/include/bits/fcntl.h
Normal file
8
userspace/lib/ygglibc/include/bits/fcntl.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _YGGDRASIL_FCNTL_H
|
||||
#define _YGGDRASIL_FCNTL_H 1
|
||||
|
||||
int fcntl(int fd, int cmd, ...);
|
||||
int open(const char *pathname, int opts, ...);
|
||||
int openat(int atfd, const char *pathname, int opts, ...);
|
||||
|
||||
#endif
|
7
userspace/lib/ygglibc/include/bits/setjmp.h
Normal file
7
userspace/lib/ygglibc/include/bits/setjmp.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _YGGDRASIL_SETJMP_H
|
||||
#define _YGGDRASIL_SETJMP_H 1
|
||||
|
||||
int setjmp(jmp_buf env);
|
||||
[[noreturn]] void longjmp(jmp_buf env, int val);
|
||||
|
||||
#endif
|
16
userspace/lib/ygglibc/include/bits/signal.h
Normal file
16
userspace/lib/ygglibc/include/bits/signal.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef _YGGDRASIL_SIGNAL_H
|
||||
#define _YGGDRASIL_SIGNAL_H 1
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
typedef _Atomic int sig_atomic_t;
|
||||
|
||||
#define SIG_IGN __sig_ignore
|
||||
// TODO
|
||||
#define SIG_ERR __sig_terminate
|
||||
// TODO
|
||||
#define SIG_HOLD __sig_terminate
|
||||
|
||||
#define SIG_DFL ((sig_handler_t) 0)
|
||||
|
||||
#endif
|
47
userspace/lib/ygglibc/include/inttypes.h
Normal file
47
userspace/lib/ygglibc/include/inttypes.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef _INTTYPES_H
|
||||
#define _INTTYPES_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PRIo64 "lo"
|
||||
#define PRId64 "ld"
|
||||
#define PRIu64 "lu"
|
||||
#define PRIx64 "lx"
|
||||
|
||||
#define PRIo32 "o"
|
||||
#define PRId32 "d"
|
||||
#define PRIu32 "u"
|
||||
#define PRIx32 "x"
|
||||
|
||||
#define PRIo16 "ho"
|
||||
#define PRId16 "hd"
|
||||
#define PRIu16 "hu"
|
||||
#define PRIx16 "hx"
|
||||
|
||||
#define PRIo8 "hho"
|
||||
#define PRId8 "hhd"
|
||||
#define PRIu8 "hhu"
|
||||
#define PRIx8 "hhx"
|
||||
|
||||
#define SCNo64 PRIo64
|
||||
#define SCNd64 PRId64
|
||||
#define SCNu64 PRIu64
|
||||
#define SCNx64 PRIx64
|
||||
|
||||
#define SCNo32 PRIo32
|
||||
#define SCNd32 PRId32
|
||||
#define SCNu32 PRIu32
|
||||
#define SCNx32 PRIx32
|
||||
|
||||
#define SCNo16 PRIo16
|
||||
#define SCNd16 PRId16
|
||||
#define SCNu16 PRIu16
|
||||
#define SCNx16 PRIx16
|
||||
|
||||
#define SCNo8 PRIo8
|
||||
#define SCNd8 PRId8
|
||||
#define SCNu8 PRIu8
|
||||
#define SCNx8 PRIx8
|
||||
|
||||
#endif
|
@ -102,6 +102,13 @@ impl<T> EResult<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map<U, F: FnOnce(T) -> U>(self, map: F) -> EResult<U> {
|
||||
match self {
|
||||
Self::Ok(value) => EResult::Ok(map(value)),
|
||||
Self::Err(err) => EResult::Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_err(self) -> Errno {
|
||||
match self {
|
||||
Self::Ok(_) => panic!("Expected an error"),
|
||||
|
20
userspace/lib/ygglibc/src/headers/dirent/cbindgen.toml
Normal file
20
userspace/lib/ygglibc/src/headers/dirent/cbindgen.toml
Normal file
@ -0,0 +1,20 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"stdint.h",
|
||||
"sys/types.h",
|
||||
"bits/dirent.h",
|
||||
"limits.h",
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_DIRENT_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["dirent"]
|
||||
exclude = ["DIR"]
|
163
userspace/lib/ygglibc/src/headers/dirent/mod.rs
Normal file
163
userspace/lib/ygglibc/src/headers/dirent/mod.rs
Normal file
@ -0,0 +1,163 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int, c_long},
|
||||
mem::MaybeUninit,
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use yggdrasil_rt::io::{DirectoryEntry, RawFd};
|
||||
|
||||
use crate::{
|
||||
error::{CIntZeroResult, CPtrResult, EResult, TryFromExt},
|
||||
io::{dir::DirReader, FromRawFd},
|
||||
util::{PointerExt, PointerStrExt},
|
||||
};
|
||||
|
||||
use super::{errno::ESUCCESS, sys_types::ino_t};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct DIR {
|
||||
reader: DirReader,
|
||||
buffer: MaybeUninit<dirent>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct dirent {
|
||||
pub d_ino: ino_t,
|
||||
pub d_name: [c_char; 256],
|
||||
}
|
||||
|
||||
pub type __scandir_filter_fn_t = extern "C" fn(*const dirent) -> c_int;
|
||||
pub type __scandir_compar_fn_t = extern "C" fn(*mut *const dirent, *mut *const dirent) -> c_int;
|
||||
|
||||
impl DIR {
|
||||
unsafe fn close(mut dir_ptr: NonNull<Self>) -> EResult<()> {
|
||||
let dir = dir_ptr.as_mut();
|
||||
let result = dir.reader.close();
|
||||
drop(Box::from_raw(dir_ptr.as_ptr()));
|
||||
result
|
||||
}
|
||||
|
||||
fn read_entry(&mut self) -> EResult<NonNull<dirent>> {
|
||||
match self.reader.read_entry() {
|
||||
EResult::Ok(Some(entry)) => {
|
||||
self.buffer.write(dirent::from(entry));
|
||||
EResult::Ok(unsafe { NonNull::new_unchecked(self.buffer.as_mut_ptr()) })
|
||||
}
|
||||
EResult::Ok(None) => EResult::Err(ESUCCESS),
|
||||
EResult::Err(err) => EResult::Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DirectoryEntry> for dirent {
|
||||
fn from(value: DirectoryEntry) -> Self {
|
||||
let mut d_name = [0; 256];
|
||||
let len = value.name.len();
|
||||
|
||||
if len >= 255 {
|
||||
todo!("Name too long");
|
||||
}
|
||||
|
||||
// SAFETY this is just to cast u8 to i8, so transmute should be safe
|
||||
d_name[..len].copy_from_slice(unsafe { core::mem::transmute(value.name.as_bytes()) });
|
||||
d_name[len] = 0;
|
||||
|
||||
Self {
|
||||
// TODO
|
||||
d_ino: 0,
|
||||
d_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Primary stuff
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn opendir(pathname: *const c_char) -> CPtrResult<DIR> {
|
||||
let pathname = pathname.ensure_str();
|
||||
|
||||
let reader = DirReader::open_at(None, pathname)?;
|
||||
let dir = NonNull::from(Box::leak(Box::new(DIR {
|
||||
reader,
|
||||
buffer: MaybeUninit::uninit(),
|
||||
})));
|
||||
CPtrResult::success(dir)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fdopendir(fd: c_int) -> CPtrResult<DIR> {
|
||||
let fd = RawFd::e_try_from(fd)?;
|
||||
let reader = DirReader::from_raw_fd(fd);
|
||||
let dir = NonNull::from(Box::leak(Box::new(DIR {
|
||||
reader,
|
||||
buffer: MaybeUninit::uninit(),
|
||||
})));
|
||||
CPtrResult::success(dir)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn closedir(dir: *mut DIR) -> CIntZeroResult {
|
||||
let dir = NonNull::new(dir).unwrap();
|
||||
DIR::close(dir)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dirfd(dir: *mut DIR) -> c_int {
|
||||
let dir = dir.ensure_mut();
|
||||
dir.reader.as_raw_fd().into_raw().try_into().unwrap()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn readdir(dir: *mut DIR) -> CPtrResult<dirent> {
|
||||
let dir = dir.as_mut().unwrap();
|
||||
let dirent = dir.read_entry()?;
|
||||
CPtrResult::success(dirent)
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
// #[no_mangle]
|
||||
// unsafe extern "C" fn readdir_r(
|
||||
// dir: *mut DIR,
|
||||
// buffer: *mut dirent,
|
||||
// outptr: *mut *mut dirent,
|
||||
// ) -> c_int {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
// Seeking
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn seekdir(_dir: *mut DIR, _offset: c_long) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rewinddir(_dir: *mut DIR) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn telldir(_dir: *mut DIR) -> c_long {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Directory scan and sorting
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn scandir(
|
||||
_dirp: *const c_char,
|
||||
_namelist: *mut *mut *mut dirent,
|
||||
_filter: __scandir_filter_fn_t,
|
||||
_compar: __scandir_compar_fn_t,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn alphasort(_a: *const *const dirent, _b: *const *const dirent) -> c_int {
|
||||
todo!()
|
||||
}
|
23
userspace/lib/ygglibc/src/headers/fcntl/cbindgen.toml
Normal file
23
userspace/lib/ygglibc/src/headers/fcntl/cbindgen.toml
Normal file
@ -0,0 +1,23 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"stdint.h",
|
||||
"sys/types.h",
|
||||
"sys/stat.h",
|
||||
"unistd.h",
|
||||
|
||||
"bits/fcntl.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_FCNTL_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["flock"]
|
||||
# Varargs are broken for these
|
||||
exclude = ["fcntl", "open", "openat"]
|
178
userspace/lib/ygglibc/src/headers/fcntl/mod.rs
Normal file
178
userspace/lib/ygglibc/src/headers/fcntl/mod.rs
Normal file
@ -0,0 +1,178 @@
|
||||
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 {
|
||||
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())
|
||||
}
|
@ -6,10 +6,10 @@
|
||||
// <complex.h> -
|
||||
// <cpio.h> -
|
||||
// <ctype.h> +
|
||||
// <dirent.h> -
|
||||
// <dirent.h> +
|
||||
// <dlfcn.h> -
|
||||
// <errno.h> +
|
||||
// <fcntl.h> -
|
||||
// <fcntl.h> +
|
||||
// <fenv.h> -
|
||||
// <float.h> -
|
||||
// <fmtmsg.h> -
|
||||
@ -18,12 +18,12 @@
|
||||
// <glob.h> -
|
||||
// <grp.h> -
|
||||
// <iconv.h> -
|
||||
// <inttypes.h> -
|
||||
// <inttypes.h> +
|
||||
// <iso646.h> -
|
||||
// <langinfo.h> -
|
||||
// <libgen.h> -
|
||||
// <limits.h> -
|
||||
// <locale.h> ~
|
||||
// <limits.h> ?
|
||||
// <locale.h> =
|
||||
// <math.h> -
|
||||
// <monetary.h> -
|
||||
// <mqueue.h> -
|
||||
@ -35,18 +35,18 @@
|
||||
// <nl_types.h> -
|
||||
// <poll.h> -
|
||||
// <pthread.h> -
|
||||
// <pwd.h> -
|
||||
// <pwd.h> =
|
||||
// <regex.h> -
|
||||
// <sched.h> -
|
||||
// <search.h> -
|
||||
// <semaphore.h> -
|
||||
// <setjmp.h> -
|
||||
// <signal.h> -
|
||||
// <setjmp.h> +
|
||||
// <signal.h> =
|
||||
// <spawn.h> -
|
||||
// <stdarg.h> -
|
||||
// <stdbool.h> -
|
||||
// <stddef.h> -
|
||||
// <stdint.h> -
|
||||
// <stdarg.h> +
|
||||
// <stdbool.h> +
|
||||
// <stddef.h> +
|
||||
// <stdint.h> +
|
||||
// <stdio.h> +
|
||||
// <stdlib.h> -
|
||||
// <string.h> +
|
||||
@ -84,12 +84,17 @@
|
||||
// <wordexp.h> -
|
||||
|
||||
pub mod ctype;
|
||||
pub mod dirent;
|
||||
pub mod errno;
|
||||
pub mod fcntl;
|
||||
pub mod locale;
|
||||
pub mod pwd;
|
||||
pub mod setjmp;
|
||||
pub mod stdio;
|
||||
pub mod stdlib;
|
||||
pub mod string;
|
||||
pub mod strings;
|
||||
pub mod unistd;
|
||||
pub mod signal;
|
||||
|
||||
pub mod sys_types;
|
||||
|
14
userspace/lib/ygglibc/src/headers/pwd/cbindgen.toml
Normal file
14
userspace/lib/ygglibc/src/headers/pwd/cbindgen.toml
Normal file
@ -0,0 +1,14 @@
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
sys_includes = ["stddef.h", "sys/types.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_PWD_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["passwd"]
|
||||
exclude = []
|
60
userspace/lib/ygglibc/src/headers/pwd/mod.rs
Normal file
60
userspace/lib/ygglibc/src/headers/pwd/mod.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use core::ffi::{c_char, c_int};
|
||||
|
||||
use super::sys_types::{gid_t, uid_t};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct passwd {
|
||||
pub pw_name: *mut c_char,
|
||||
pub pw_uid: uid_t,
|
||||
pub pw_gid: gid_t,
|
||||
pub pw_dir: *mut c_char,
|
||||
pub pw_shell: *mut c_char,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn endpwent() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getpwent() -> *mut passwd {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getpwnam(_name: *const c_char) -> *mut passwd {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getpwnam_r(
|
||||
_name: *const c_char,
|
||||
_pwd: *mut passwd,
|
||||
_buf: *mut c_char,
|
||||
_buflen: usize,
|
||||
_result: *mut *mut passwd,
|
||||
) -> c_int {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getpwuid(_uid: uid_t) -> *mut passwd {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn getpwuid_r(
|
||||
_uid: uid_t,
|
||||
_pwd: *mut passwd,
|
||||
_buf: *mut c_char,
|
||||
_buflen: usize,
|
||||
_result: *mut *mut passwd,
|
||||
) -> c_int {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn setpwent() {
|
||||
unimplemented!()
|
||||
}
|
15
userspace/lib/ygglibc/src/headers/setjmp/cbindgen.toml
Normal file
15
userspace/lib/ygglibc/src/headers/setjmp/cbindgen.toml
Normal file
@ -0,0 +1,15 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = ["stdarg.h", "stddef.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SETJMP_H"
|
||||
trailer = "#include <bits/setjmp.h>"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["jmp_buf"]
|
||||
exclude = []
|
5
userspace/lib/ygglibc/src/headers/setjmp/mod.rs
Normal file
5
userspace/lib/ygglibc/src/headers/setjmp/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||
mod x86_64;
|
||||
|
||||
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
|
||||
pub type jmp_buf = *mut x86_64::__jmp_buf;
|
46
userspace/lib/ygglibc/src/headers/setjmp/x86_64.S
Normal file
46
userspace/lib/ygglibc/src/headers/setjmp/x86_64.S
Normal file
@ -0,0 +1,46 @@
|
||||
.global setjmp
|
||||
.global longjmp
|
||||
|
||||
.global _setjmp
|
||||
.global _longjmp
|
||||
|
||||
.section .text
|
||||
// args:
|
||||
// %rdi -- __jmp_buf *env
|
||||
setjmp:
|
||||
_setjmp:
|
||||
movq %rbx, 0(%rdi)
|
||||
movq %rbp, 8(%rdi)
|
||||
movq %r12, 16(%rdi)
|
||||
movq %r13, 24(%rdi)
|
||||
movq %r14, 32(%rdi)
|
||||
movq %r15, 40(%rdi)
|
||||
// Calculate return stack and rip
|
||||
leaq 8(%rsp), %rax
|
||||
movq %rax, 48(%rdi)
|
||||
movq (%rsp), %rax
|
||||
movq %rax, 56(%rdi)
|
||||
|
||||
movq $0, %rax
|
||||
ret
|
||||
|
||||
// args:
|
||||
// %rdi -- __jmp_buf *env
|
||||
// %rsi -- int val
|
||||
longjmp:
|
||||
_longjmp:
|
||||
// Restore registers
|
||||
movq 0(%rdi), %rbx
|
||||
movq 8(%rdi), %rbp
|
||||
movq 16(%rdi), %r12
|
||||
movq 24(%rdi), %r13
|
||||
movq 32(%rdi), %r14
|
||||
movq 40(%rdi), %r15
|
||||
movq 48(%rdi), %rsp
|
||||
movq 56(%rdi), %rax
|
||||
pushq %rax
|
||||
|
||||
// Setup return value
|
||||
movq %rsi, %rax
|
||||
|
||||
ret
|
15
userspace/lib/ygglibc/src/headers/setjmp/x86_64.rs
Normal file
15
userspace/lib/ygglibc/src/headers/setjmp/x86_64.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use core::arch::global_asm;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct __jmp_buf {
|
||||
rip: usize,
|
||||
rsp: usize,
|
||||
r15: usize,
|
||||
r14: usize,
|
||||
r13: usize,
|
||||
r12: usize,
|
||||
rbp: usize,
|
||||
rbx: usize,
|
||||
}
|
||||
|
||||
global_asm!(include_str!("x86_64.S"), options(att_syntax));
|
19
userspace/lib/ygglibc/src/headers/signal/cbindgen.toml
Normal file
19
userspace/lib/ygglibc/src/headers/signal/cbindgen.toml
Normal file
@ -0,0 +1,19 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = [
|
||||
"stddef.h",
|
||||
"stdint.h",
|
||||
"sys/types.h",
|
||||
"bits/signal.h"
|
||||
]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_SIGNAL_H"
|
||||
|
||||
usize_type = "size_t"
|
||||
isize_type = "ssize_t"
|
||||
|
||||
[export]
|
||||
include = ["sig_handler_t", "SIGABRT"]
|
||||
exclude = []
|
106
userspace/lib/ygglibc/src/headers/signal/mod.rs
Normal file
106
userspace/lib/ygglibc/src/headers/signal/mod.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use core::ffi::c_int;
|
||||
|
||||
use yggdrasil_rt::process::Signal;
|
||||
|
||||
use super::sys_types::pid_t;
|
||||
|
||||
pub type sig_handler_t = unsafe extern "C" fn(SigNumber);
|
||||
|
||||
extern "C" {
|
||||
fn __sig_terminate(_: SigNumber);
|
||||
fn __sig_ignore(_: SigNumber);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct SigNumber(pub c_int);
|
||||
|
||||
// TODO generate these based on the ABI
|
||||
pub const SIGSEGV: SigNumber = SigNumber(1);
|
||||
pub const SIGABRT: SigNumber = SigNumber(2);
|
||||
pub const SIGKILL: SigNumber = SigNumber(3);
|
||||
pub const SIGINT: SigNumber = SigNumber(4);
|
||||
|
||||
// TODO not yet defined signals
|
||||
pub const SIGALRM: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGBUS: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGCHLD: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGCONT: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGFPE: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGHUP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGPIPE: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGQUIT: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGSTOP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTERM: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTSTP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTTIN: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTTOU: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGUSR1: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGUSR2: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGPOLL: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGPROF: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGSYS: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGTRAP: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGURG: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGVTALRM: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGXCPU: SigNumber = SigNumber::INVALID;
|
||||
pub const SIGXFSZ: SigNumber = SigNumber::INVALID;
|
||||
|
||||
impl SigNumber {
|
||||
pub const INVALID: Self = Self(-65536);
|
||||
}
|
||||
|
||||
impl TryFrom<SigNumber> for Signal {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: SigNumber) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
SIGSEGV => Ok(Signal::MemoryAccessViolation),
|
||||
SIGABRT => Ok(Signal::Aborted),
|
||||
SIGKILL => Ok(Signal::Killed),
|
||||
SIGINT => Ok(Signal::Interrupted),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signal> for SigNumber {
|
||||
fn from(value: Signal) -> Self {
|
||||
match value {
|
||||
Signal::Aborted => SIGABRT,
|
||||
Signal::Interrupted => SIGINT,
|
||||
Signal::Killed => SIGKILL,
|
||||
Signal::MemoryAccessViolation => SIGSEGV,
|
||||
Signal::Debug => SIGTRAP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn kill(_pid: pid_t, _signum: SigNumber) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn killpg(_pid: pid_t, _signum: SigNumber) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn raise(_signum: SigNumber) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn signal(_signum: SigNumber, _handler: sig_handler_t) -> sig_handler_t {
|
||||
todo!()
|
||||
// // NOTE handler might be NULL, so check that
|
||||
// let Ok(signal) = Signal::try_from(signum) else {
|
||||
// // Ignore
|
||||
// return __sig_terminate;
|
||||
// };
|
||||
// let handler_ptr = handler as usize;
|
||||
// let handler = (handler_ptr != 0).then_some(handler);
|
||||
|
||||
// signal::set_handler(signal, handler)
|
||||
}
|
104
userspace/lib/ygglibc/src/io/dir.rs
Normal file
104
userspace/lib/ygglibc/src/io/dir.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use yggdrasil_rt::{
|
||||
io::{DirectoryEntry, RawFd},
|
||||
path::Path,
|
||||
sys as syscall,
|
||||
};
|
||||
|
||||
use crate::{error::EResult, headers::errno};
|
||||
|
||||
use super::{AsRawFd, FromRawFd};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirReader {
|
||||
fd: Option<RawFd>,
|
||||
|
||||
// Read buffer
|
||||
buffer: Box<[MaybeUninit<DirectoryEntry>]>,
|
||||
position: usize,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl DirReader {
|
||||
const BUFFER_SIZE: usize = 16;
|
||||
|
||||
pub fn open_at<P: AsRef<Path>>(at: Option<RawFd>, path: P) -> EResult<Self> {
|
||||
let fd = unsafe { syscall::open_directory(at, path.as_ref().as_str()) }?;
|
||||
EResult::Ok(unsafe { Self::from_raw_fd(fd) })
|
||||
}
|
||||
|
||||
pub unsafe fn close(&mut self) -> EResult<()> {
|
||||
if let Some(fd) = self.fd.take() {
|
||||
unsafe { syscall::close(fd) }?;
|
||||
EResult::Ok(())
|
||||
} else {
|
||||
EResult::Err(errno::EBADF)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd.unwrap()
|
||||
}
|
||||
|
||||
fn fill_buf(&mut self) -> EResult<&[DirectoryEntry]> {
|
||||
let Some(fd) = self.fd else {
|
||||
return EResult::Err(errno::EBADF);
|
||||
};
|
||||
|
||||
if self.position == self.len {
|
||||
let count = unsafe { syscall::read_directory_entries(fd, &mut self.buffer) }?;
|
||||
|
||||
self.position = 0;
|
||||
self.len = count;
|
||||
}
|
||||
|
||||
EResult::Ok(unsafe {
|
||||
MaybeUninit::slice_assume_init_ref(&self.buffer[self.position..self.len])
|
||||
})
|
||||
}
|
||||
|
||||
fn consume(&mut self, count: usize) {
|
||||
self.position = (self.position + count).min(self.len);
|
||||
}
|
||||
|
||||
pub fn read_entry(&mut self) -> EResult<Option<DirectoryEntry>> {
|
||||
let buf = self.fill_buf()?;
|
||||
|
||||
if let Some(&entry) = buf.get(0) {
|
||||
self.consume(1);
|
||||
EResult::Ok(Some(entry))
|
||||
} else {
|
||||
EResult::Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for DirReader {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for DirReader {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
Self {
|
||||
fd: Some(fd),
|
||||
|
||||
buffer: Box::new_uninit_slice(Self::BUFFER_SIZE),
|
||||
position: 0,
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DirReader {
|
||||
fn drop(&mut self) {
|
||||
if self.fd.is_some() {
|
||||
unsafe {
|
||||
self.close().ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
use core::{ffi::{c_int, c_long}, mem::MaybeUninit};
|
||||
use core::{ffi::c_int, mem::MaybeUninit};
|
||||
|
||||
use yggdrasil_rt::{io::{PipeOptions, RawFd, SeekFrom}, sys as syscall};
|
||||
use yggdrasil_rt::{
|
||||
io::{PipeOptions, RawFd, SeekFrom},
|
||||
sys as syscall,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{EResult, TryFromExt},
|
||||
@ -11,9 +14,10 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
pub mod raw;
|
||||
pub mod managed;
|
||||
pub mod buffer;
|
||||
pub mod managed;
|
||||
pub mod raw;
|
||||
pub mod dir;
|
||||
|
||||
pub trait Write {
|
||||
fn write(&mut self, data: &[u8]) -> EResult<usize>;
|
||||
@ -39,7 +43,7 @@ pub trait Write {
|
||||
match self.write(data) {
|
||||
EResult::Ok(n) if n == data.len() => EResult::Ok(()),
|
||||
EResult::Ok(_) => todo!(),
|
||||
EResult::Err(err) => EResult::Err(err)
|
||||
EResult::Err(err) => EResult::Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,7 +55,7 @@ pub trait Read {
|
||||
match self.read(buf) {
|
||||
EResult::Ok(n) if n == buf.len() => EResult::Ok(()),
|
||||
EResult::Ok(_) => todo!(),
|
||||
EResult::Err(err) => EResult::Err(err)
|
||||
EResult::Err(err) => EResult::Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
use core::ffi::{c_char, CStr};
|
||||
use core::ffi::{c_char, c_int, CStr};
|
||||
|
||||
use yggdrasil_rt::io::RawFd;
|
||||
|
||||
use crate::{error::{EResult, TryFromExt}, headers::{errno, fcntl::AT_FDCWD}};
|
||||
|
||||
pub trait PointerExt {
|
||||
unsafe fn ensure(self: *const Self) -> &'static Self;
|
||||
@ -48,3 +52,11 @@ impl PointerStrExt for c_char {
|
||||
CStr::from_ptr(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn at_fd(fd: c_int) -> EResult<Option<RawFd>> {
|
||||
match fd {
|
||||
AT_FDCWD => EResult::Ok(None),
|
||||
0.. => RawFd::e_try_from(fd).map(Some),
|
||||
_ => EResult::Err(errno::EBADF),
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user