Browse Source

Add statvfs and strtold

Jeremy Soller 6 years ago
parent
commit
74af56d71b

+ 1 - 0
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");
 

+ 14 - 0
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 */

+ 3 - 0
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;

+ 5 - 0
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);
+}

+ 1 - 0
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;

+ 1 - 0
src/header/stdlib/cbindgen.toml

@@ -1,5 +1,6 @@
 sys_includes = ["stddef.h", "alloca.h"]
 include_guard = "_STDLIB_H"
+trailer = "#include <bits/stdlib.h>"
 language = "C"
 style = "Tag"
 

+ 7 - 0
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

+ 45 - 0
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
+}

+ 46 - 0
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
     }

+ 3 - 0
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;

+ 28 - 0
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
     }

+ 3 - 0
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;