From 74af56d71bd0301eedad10490f55d2c321fd1440 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 14 Dec 2018 12:00:21 -0700 Subject: [PATCH] Add statvfs and strtold --- build.rs | 1 + include/bits/stdlib.h | 14 +++++++++ include/sys/types.h | 3 ++ src/c/stdlib.c | 5 +++ src/header/mod.rs | 1 + src/header/stdlib/cbindgen.toml | 1 + src/header/sys_statvfs/cbindgen.toml | 7 +++++ src/header/sys_statvfs/mod.rs | 45 +++++++++++++++++++++++++++ src/platform/linux/mod.rs | 46 ++++++++++++++++++++++++++++ src/platform/pal/mod.rs | 3 ++ src/platform/redox/mod.rs | 28 +++++++++++++++++ src/platform/types.rs | 3 ++ 12 files changed, 157 insertions(+) create mode 100644 include/bits/stdlib.h create mode 100644 src/c/stdlib.c create mode 100644 src/header/sys_statvfs/cbindgen.toml create mode 100644 src/header/sys_statvfs/mod.rs diff --git a/build.rs b/build.rs index 4ee52afdf9..5d4005b21f 100644 --- a/build.rs +++ b/build.rs @@ -16,6 +16,7 @@ fn main() { .file("src/c/fcntl.c") .file("src/c/stack_chk.c") .file("src/c/stdio.c") + .file("src/c/stdlib.c") .file("src/c/unistd.c") .compile("relibc_c"); diff --git a/include/bits/stdlib.h b/include/bits/stdlib.h new file mode 100644 index 0000000000..8d639cef38 --- /dev/null +++ b/include/bits/stdlib.h @@ -0,0 +1,14 @@ +#ifndef _BITS_STDLIB_H +#define _BITS_STDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +long double strtold(const char *nptr, char **endptr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* _BITS_STDLIB_H */ diff --git a/include/sys/types.h b/include/sys/types.h index c4048845af..e35f48aaa5 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -21,6 +21,9 @@ typedef int clockid_t; typedef void* timer_t; typedef unsigned long int blkcnt_t; +typedef unsigned long int fsblkcnt_t; +typedef unsigned long int fsfilcnt_t; + typedef unsigned char u_char, uchar; typedef unsigned short u_short, ushort; typedef unsigned int u_int, uint; diff --git a/src/c/stdlib.c b/src/c/stdlib.c new file mode 100644 index 0000000000..39e4fb0f44 --- /dev/null +++ b/src/c/stdlib.c @@ -0,0 +1,5 @@ +double strtod(const char *nptr, char **endptr); + +long double strtold(const char *nptr, char **endptr) { + return (long double)strtod(nptr, endptr); +} diff --git a/src/header/mod.rs b/src/header/mod.rs index be83579d19..63add34aa9 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -35,6 +35,7 @@ pub mod sys_mman; pub mod sys_select; pub mod sys_socket; pub mod sys_stat; +pub mod sys_statvfs; pub mod sys_time; pub mod sys_timeb; //pub mod sys_times; diff --git a/src/header/stdlib/cbindgen.toml b/src/header/stdlib/cbindgen.toml index 19233ba276..bd8618caa5 100644 --- a/src/header/stdlib/cbindgen.toml +++ b/src/header/stdlib/cbindgen.toml @@ -1,5 +1,6 @@ sys_includes = ["stddef.h", "alloca.h"] include_guard = "_STDLIB_H" +trailer = "#include " language = "C" style = "Tag" diff --git a/src/header/sys_statvfs/cbindgen.toml b/src/header/sys_statvfs/cbindgen.toml new file mode 100644 index 0000000000..a3524d6385 --- /dev/null +++ b/src/header/sys_statvfs/cbindgen.toml @@ -0,0 +1,7 @@ +sys_includes = ["sys/types.h"] +include_guard = "_SYS_STATVFS_H" +language = "C" +style = "Tag" + +[enum] +prefix_with_name = true diff --git a/src/header/sys_statvfs/mod.rs b/src/header/sys_statvfs/mod.rs new file mode 100644 index 0000000000..27287c73f4 --- /dev/null +++ b/src/header/sys_statvfs/mod.rs @@ -0,0 +1,45 @@ +//! statvfs implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysstatvfs.h.html + +use c_str::CStr; +use header::fcntl::{O_PATH}; +use platform::types::*; +use platform::{Pal, Sys}; + +//pub const ST_RDONLY +//pub const ST_NOSUID + +#[repr(C)] +#[derive(Default)] +pub struct statvfs { + pub f_bsize: c_ulong, + pub f_frsize: c_ulong, + pub f_blocks: fsblkcnt_t, + pub f_bfree: fsblkcnt_t, + pub f_bavail: fsblkcnt_t, + pub f_files: fsfilcnt_t, + pub f_ffree: fsfilcnt_t, + pub f_favail: fsfilcnt_t, + pub f_fsid: c_ulong, + pub f_flag: c_ulong, + pub f_namemax: c_ulong, +} + +#[no_mangle] +pub extern "C" fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int { + Sys::fstatvfs(fildes, buf) +} + +#[no_mangle] +pub unsafe extern "C" fn statvfs(file: *const c_char, buf: *mut statvfs) -> c_int { + let file = CStr::from_ptr(file); + let fd = Sys::open(file, O_PATH, 0); + if fd < 0 { + return -1; + } + + let res = Sys::fstatvfs(fd, buf); + + Sys::close(fd); + + res +} diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 1bf3c83901..56cb816dc8 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -14,6 +14,7 @@ use header::sys_ioctl::{winsize, TCGETS, TCSETS, TIOCGWINSZ}; // use header::sys_resource::rusage; use header::sys_select::fd_set; use header::sys_stat::stat; +use header::sys_statvfs::statvfs; use header::sys_time::{itimerval, timeval, timezone}; // use header::sys_times::tms; use header::sys_utsname::utsname; @@ -27,6 +28,23 @@ const AT_FDCWD: c_int = -100; const AT_EMPTY_PATH: c_int = 0x1000; const AT_REMOVEDIR: c_int = 0x200; +#[repr(C)] +#[derive(Default)] +struct linux_statfs { + f_type: c_long, /* type of file system (see below) */ + f_bsize: c_long, /* optimal transfer block size */ + f_blocks: fsblkcnt_t, /* total data blocks in file system */ + f_bfree: fsblkcnt_t, /* free blocks in fs */ + f_bavail: fsblkcnt_t, /* free blocks available to unprivileged user */ + f_files: fsfilcnt_t, /* total file nodes in file system */ + f_ffree: fsfilcnt_t, /* free file nodes in fs */ + f_fsid: c_long, /* file system id */ + f_namelen: c_long, /* maximum length of filenames */ + f_frsize: c_long, /* fragment size (since Linux 2.6) */ + f_flags: c_long, + f_spare: [c_long; 4], +} + fn e(sys: usize) -> usize { if (sys as isize) < 0 && (sys as isize) >= -256 { unsafe { @@ -141,6 +159,34 @@ impl Pal for Sys { e(unsafe { syscall!(NEWFSTATAT, fildes, empty_ptr, buf, AT_EMPTY_PATH) }) as c_int } + fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int { + let mut kbuf = linux_statfs::default(); + let kbuf_ptr = &mut kbuf as *mut linux_statfs; + let res = e(unsafe { syscall!(FSTATFS, fildes, kbuf_ptr) }) as c_int; + if res == 0 { + unsafe { + if ! buf.is_null() { + (*buf).f_bsize = kbuf.f_bsize as c_ulong; + (*buf).f_frsize = if kbuf.f_frsize != 0 { + kbuf.f_frsize + } else { + kbuf.f_bsize + } as c_ulong; + (*buf).f_blocks = kbuf.f_blocks; + (*buf).f_bfree = kbuf.f_bfree; + (*buf).f_bavail = kbuf.f_bavail; + (*buf).f_files = kbuf.f_files; + (*buf).f_ffree = kbuf.f_ffree; + (*buf).f_favail = kbuf.f_ffree; + (*buf).f_fsid = kbuf.f_fsid as c_ulong; + (*buf).f_flag = kbuf.f_flags as c_ulong; + (*buf).f_namemax = kbuf.f_namelen as c_ulong; + } + } + } + res + } + fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int { e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index bd832ddb63..262fa9fb2b 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -4,6 +4,7 @@ use header::dirent::dirent; use header::poll::{nfds_t, pollfd}; use header::sys_select::fd_set; use header::sys_stat::stat; +use header::sys_statvfs::statvfs; use header::sys_time::{timeval, timezone}; use header::sys_utsname::utsname; use header::termios::termios; @@ -48,6 +49,8 @@ pub trait Pal { fn fstat(fildes: c_int, buf: *mut stat) -> c_int; + fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int; + fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int; fn fork() -> pid_t; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 8fc56b0037..b8b049f11a 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -6,6 +6,7 @@ use core::result::Result as CoreResult; use core::{mem, ptr, slice}; use spin::{Mutex, MutexGuard, Once}; use syscall::data::Stat as redox_stat; +use syscall::data::StatVfs as redox_statvfs; use syscall::data::TimeSpec as redox_timespec; use syscall::{self, Result}; @@ -17,6 +18,7 @@ use header::fcntl; use header::poll::{self, nfds_t, pollfd}; use header::sys_select::fd_set; use header::sys_stat::stat; +use header::sys_statvfs::statvfs; use header::sys_time::{timeval, timezone}; use header::sys_utsname::{utsname, UTSLENGTH}; use header::termios::termios; @@ -362,6 +364,32 @@ impl Pal for Sys { } } + fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int { + let mut kbuf: redox_statvfs = redox_statvfs::default(); + match e(syscall::fstatvfs(fildes as usize, &mut kbuf)) { + 0 => { + unsafe { + if !buf.is_null() { + (*buf).f_bsize = kbuf.f_bsize as c_ulong; + (*buf).f_frsize = kbuf.f_bsize as c_ulong; + (*buf).f_blocks = kbuf.f_blocks; + (*buf).f_bfree = kbuf.f_bfree; + (*buf).f_bavail = kbuf.f_bavail; + //TODO + (*buf).f_files = 0; + (*buf).f_ffree = 0; + (*buf).f_favail = 0; + (*buf).f_fsid = 0; + (*buf).f_flag = 0; + (*buf).f_namemax = 0; + } + } + 0 + } + _ => -1, + } + } + fn fsync(fd: c_int) -> c_int { e(syscall::fsync(fd as usize)) as c_int } diff --git a/src/platform/types.rs b/src/platform/types.rs index dcd5803c38..85e3ba3aaf 100644 --- a/src/platform/types.rs +++ b/src/platform/types.rs @@ -60,6 +60,9 @@ pub type nlink_t = c_ulong; pub type blksize_t = c_long; pub type blkcnt_t = c_ulong; +pub type fsblkcnt_t = c_ulong; +pub type fsfilcnt_t = c_ulong; + pub type useconds_t = c_uint; pub type suseconds_t = c_int;