From 96cc56a0b5d571b05674c7922dfbb04c42ee4428 Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jeremy@system76.com> Date: Sun, 25 Nov 2018 14:56:36 -0700 Subject: [PATCH] Add readlink and symlink --- src/header/regex/mod.rs | 6 ++++++ src/header/unistd/mod.rs | 15 +++++++++------ src/platform/linux/mod.rs | 30 +++++++++++++++++------------- src/platform/pal/mod.rs | 4 +++- src/platform/redox/mod.rs | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/header/regex/mod.rs b/src/header/regex/mod.rs index da746884d..3742a34c7 100644 --- a/src/header/regex/mod.rs +++ b/src/header/regex/mod.rs @@ -50,6 +50,7 @@ pub const REG_ESPACE: c_int = 13; pub const REG_BADRPT: c_int = 14; #[no_mangle] +#[linkage = "weak"] // redefined in GIT pub extern "C" fn regcomp(out: *mut regex_t, pat: *const c_char, cflags: c_int) -> c_int { if cflags & REG_EXTENDED == REG_EXTENDED { return REG_ENOSYS; @@ -84,7 +85,9 @@ pub extern "C" fn regcomp(out: *mut regex_t, pat: *const c_char, cflags: c_int) Err(_) => REG_BADPAT, } } + #[no_mangle] +#[linkage = "weak"] // redefined in GIT pub unsafe extern "C" fn regfree(regex: *mut regex_t) { Vec::from_raw_parts( (*regex).ptr as *mut Vec<(Token, Range)>, @@ -92,7 +95,9 @@ pub unsafe extern "C" fn regfree(regex: *mut regex_t) { (*regex).capacity, ); } + #[no_mangle] +#[linkage = "weak"] // redefined in GIT pub extern "C" fn regexec( regex: *const regex_t, input: *const c_char, @@ -143,6 +148,7 @@ pub extern "C" fn regexec( } #[no_mangle] +#[linkage = "weak"] // redefined in GIT pub extern "C" fn regerror(code: c_int, _regex: *const regex_t, out: *mut c_char, max: c_int) { let string = match code { 0 => "No error\0", diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index c10b0cd21..95dc1b0f5 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -445,7 +445,6 @@ pub extern "C" fn pwrite( #[no_mangle] pub extern "C" fn read(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t { - use core::slice; let buf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, nbyte as usize) }; trace_expr!( Sys::read(fildes, buf), @@ -456,9 +455,11 @@ pub extern "C" fn read(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssiz ) } -// #[no_mangle] -pub extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsize: size_t) -> c_int { - unimplemented!(); +#[no_mangle] +pub extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsize: size_t) -> ssize_t { + let path = unsafe { CStr::from_ptr(path) }; + let buf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, bufsize as usize) }; + Sys::readlink(path, buf) } #[no_mangle] @@ -518,9 +519,11 @@ pub extern "C" fn swab(src: *const c_void, dest: *mut c_void, nbytes: ssize_t) { unimplemented!(); } -// #[no_mangle] +#[no_mangle] pub extern "C" fn symlink(path1: *const c_char, path2: *const c_char) -> c_int { - unimplemented!(); + let path1 = unsafe { CStr::from_ptr(path1) }; + let path2 = unsafe { CStr::from_ptr(path2) }; + Sys::symlink(path1, path2) } // #[no_mangle] diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 3c221b2c4..079b10f64 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -305,19 +305,19 @@ impl Pal for Sys { e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t } - fn realpath(pathname: &CStr, out: &mut [u8]) -> c_int { - fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t { - e(unsafe { - syscall!( - READLINKAT, - AT_FDCWD, - pathname.as_ptr(), - out.as_mut_ptr(), - out.len() - ) - }) as ssize_t - } + fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t { + e(unsafe { + syscall!( + READLINKAT, + AT_FDCWD, + pathname.as_ptr(), + out.as_mut_ptr(), + out.len() + ) + }) 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, @@ -332,7 +332,7 @@ impl Pal for Sys { proc_path.push(0); let len = out.len(); - let read = readlink( + let read = Self::readlink( CStr::from_bytes_with_nul(&proc_path).unwrap(), &mut out[..len - 1], ); @@ -379,6 +379,10 @@ impl Pal for Sys { e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int } + fn symlink(path1: &CStr, path2: &CStr) -> c_int { + e(unsafe { syscall!(SYMLINKAT, path1.as_ptr(), AT_FDCWD, path2.as_ptr()) }) as c_int + } + fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { Self::ioctl(fd, TCGETS, out as *mut c_void) } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 217ff46d5..547a9cd41 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -115,7 +115,7 @@ pub trait Pal { fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t; - //fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t; + fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t; fn realpath(pathname: &CStr, out: &mut [u8]) -> c_int; @@ -138,6 +138,8 @@ pub trait Pal { fn setreuid(ruid: uid_t, euid: uid_t) -> c_int; + fn symlink(path1: &CStr, path2: &CStr) -> c_int; + fn tcgetattr(fd: c_int, out: *mut termios) -> c_int; fn tcsetattr(fd: c_int, act: c_int, value: *const termios) -> c_int; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 4747dee4e..fb7f81b77 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -835,6 +835,26 @@ impl Pal for Sys { e(syscall::read(fd as usize, buf)) as ssize_t } + fn readlink(pathname: &CStr, out: &mut [u8]) -> ssize_t { + let file = match File::open(pathname, fcntl::O_PATH | fcntl::O_SYMLINK) { + Ok(fd) => fd, + 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 realpath(pathname: &CStr, out: &mut [u8]) -> c_int { let file = match File::open(pathname, fcntl::O_PATH) { Ok(fd) => fd, @@ -1019,6 +1039,22 @@ impl Pal for Sys { e(syscall::setreuid(ruid as usize, euid as usize)) as c_int } + fn symlink(path1: &CStr, path2: &CStr) -> c_int { + let mut file = match File::open( + path2, + fcntl::O_CREAT | fcntl::O_WRONLY | fcntl::O_SYMLINK | 0o777, + ) { + Ok(fd) => fd, + Err(_) => return -1, + }; + + if file.write(path1.to_bytes()).is_err() { + return -1; + } + + 0 + } + fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { let dup = e(syscall::dup(fd as usize, b"termios")); if dup == !0 { -- GitLab