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