From 0dd801da03791772c26d035389b2b714a2865e7e Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jeremy@system76.com> Date: Sun, 27 Jan 2019 17:10:55 -0700 Subject: [PATCH] Implement ttyname by adding fpath function to Sys. Remove realpath function and use fpath internally --- src/header/stdlib/mod.rs | 32 ++++++++++++++++++---------- src/header/unistd/mod.rs | 26 +++++++++++++++++----- src/platform/linux/mod.rs | 45 ++++++++++----------------------------- src/platform/pal/mod.rs | 4 ++-- src/platform/redox/mod.rs | 24 ++++----------------- 5 files changed, 59 insertions(+), 72 deletions(-) diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs index 08d02e11..6b7af699 100644 --- a/src/header/stdlib/mod.rs +++ b/src/header/stdlib/mod.rs @@ -7,6 +7,7 @@ use rand::rngs::JitterRng; use rand::{Rng, SeedableRng}; use c_str::CStr; +use fs::File; use header::errno::*; use header::fcntl::*; use header::limits; @@ -611,22 +612,31 @@ pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void #[no_mangle] pub unsafe extern "C" fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char { - let mut path = [0; limits::PATH_MAX]; + let ptr = if resolved.is_null() { + malloc(limits::PATH_MAX) as *mut c_char + } else { + resolved + }; + + let mut out = slice::from_raw_parts_mut(ptr as *mut u8, limits::PATH_MAX); { - let slice = if resolved.is_null() { - &mut path - } else { - slice::from_raw_parts_mut(resolved as *mut u8, 4096) + let file = match File::open(&CStr::from_ptr(pathname), O_PATH | O_CLOEXEC) { + Ok(file) => file, + Err(_) => return ptr::null_mut(), }; - if Sys::realpath(CStr::from_ptr(pathname), slice) < 0 { + + let len = out.len(); + let read = Sys::fpath( + *file, + &mut out[..len - 1], + ); + if read < 0 { return ptr::null_mut(); } + out[read as usize] = 0; } - if !resolved.is_null() { - resolved - } else { - strdup(path.as_ptr() as *const i8) - } + + ptr } // #[no_mangle] diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index 173104ad..0a1214e2 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -594,14 +594,30 @@ pub extern "C" fn truncate(path: *const c_char, length: off_t) -> c_int { unimplemented!(); } -// #[no_mangle] -pub extern "C" fn ttyname(fildes: c_int) -> *mut c_char { - unimplemented!(); +#[no_mangle] +pub unsafe extern "C" fn ttyname(fildes: c_int) -> *mut c_char { + static mut TTYNAME: [c_char; 4096] = [0; 4096]; + if ttyname_r(fildes, TTYNAME.as_mut_ptr(), TTYNAME.len()) == 0 { + TTYNAME.as_mut_ptr() + } else { + ptr::null_mut() + } } -// #[no_mangle] +#[no_mangle] pub extern "C" fn ttyname_r(fildes: c_int, name: *mut c_char, namesize: size_t) -> c_int { - unimplemented!(); + let name = unsafe { slice::from_raw_parts_mut(name as *mut u8, namesize) }; + if name.is_empty() { + return errno::ERANGE; + } + + let len = Sys::fpath(fildes, &mut name[..namesize - 1]); + if len < 0 { + return unsafe { -platform::errno }; + } + name[len as usize] = 0; + + 0 } #[no_mangle] diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index e28970d2..70c6bf17 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -4,9 +4,7 @@ use core_io::Write; use super::types::*; use super::{errno, Pal}; use c_str::CStr; -use fs::File; use header::dirent::dirent; -use header::fcntl; use header::poll::{nfds_t, pollfd}; use header::signal::SIGCHLD; // use header::sys_resource::rusage; @@ -189,6 +187,17 @@ impl Pal for Sys { e(unsafe { syscall!(CLONE, SIGCHLD, 0, 0, 0, 0) }) as pid_t } + fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t { + let mut proc_path = b"/proc/self/fd/".to_vec(); + write!(proc_path, "{}", fildes).unwrap(); + proc_path.push(0); + + Self::readlink( + CStr::from_bytes_with_nul(&proc_path).unwrap(), + out + ) + } + fn fsync(fildes: c_int) -> c_int { e(unsafe { syscall!(FSYNC, fildes) }) as c_int } @@ -346,38 +355,6 @@ impl Pal for Sys { }) as ssize_t } - fn realpath(pathname: &CStr, out: &mut [u8]) -> c_int { - let file = match File::open(pathname, fcntl::O_PATH) { - Ok(file) => file, - Err(_) => return -1, - }; - - if out.is_empty() { - return 0; - } - - let mut proc_path = b"/proc/self/fd/".to_vec(); - write!(proc_path, "{}", *file).unwrap(); - proc_path.push(0); - - let len = out.len(); - let read = Self::readlink( - CStr::from_bytes_with_nul(&proc_path).unwrap(), - &mut out[..len - 1], - ); - if read < 0 { - return -1; - } - out[read as usize] = 0; - - // TODO: Should these checks from musl be ported? - // https://gitlab.com/bminor/musl/blob/master/src/misc/realpath.c#L33-38 - // I'm not exactly sure what they're checking... - // Seems to be a sanity check whether or not it's still the same file? - - 0 - } - fn rename(old: &CStr, new: &CStr) -> c_int { e(unsafe { syscall!(RENAMEAT, AT_FDCWD, old.as_ptr(), AT_FDCWD, new.as_ptr()) }) as c_int } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 042d7c82..75410834 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -54,6 +54,8 @@ pub trait Pal { fn fork() -> pid_t; + fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t; + fn fsync(fildes: c_int) -> c_int; fn ftruncate(fildes: c_int, length: off_t) -> c_int; @@ -121,8 +123,6 @@ pub trait Pal { fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t; - fn realpath(pathname: &CStr, out: &mut [u8]) -> c_int; - fn rename(old: &CStr, new: &CStr) -> c_int; fn rmdir(path: &CStr) -> c_int; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index eb3abed1..1e568bb0 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -830,6 +830,10 @@ impl Pal for Sys { e(syscall::read(fd as usize, buf)) as ssize_t } + fn fpath(fildes: c_int, out: &mut [u8]) -> ssize_t { + e(syscall::fpath(fildes as usize, out)) as ssize_t + } + fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t { let file = match File::open( pathname, @@ -853,26 +857,6 @@ impl Pal for Sys { 0 } - fn realpath(pathname: &CStr, out: &mut [u8]) -> c_int { - let file = match File::open(pathname, fcntl::O_PATH | fcntl::O_CLOEXEC) { - Ok(ok) => ok, - Err(_) => return -1, - }; - - if out.is_empty() { - return 0; - } - - let len = out.len(); - let read = e(syscall::fpath(*file as usize, &mut out[..len - 1])); - if (read as c_int) < 0 { - return -1; - } - out[read as usize] = 0; - - 0 - } - fn rename(oldpath: &CStr, newpath: &CStr) -> c_int { match File::open(oldpath, fcntl::O_WRONLY | fcntl::O_CLOEXEC) { Ok(file) => e(syscall::frename(*file as usize, newpath.to_bytes())) as c_int, -- GitLab