Verified Commit 418a960f authored by jD91mZM2's avatar jD91mZM2
Browse files

Implement realpath

parent 26d62967
Pipeline #1444 failed with stages
in 9 minutes and 18 seconds
#ifndef _BITS_LIMIT_H
#define _BITS_LIMIT_H
#define MB_LEN_MAX 4 // unicode
#define CHAR_BIT __CHAR_BIT__
......@@ -28,4 +31,4 @@
#define USHRT_MAX ((1 << 16) - 1)
#define WORD_BIT 32
#define PATH_MAX 4096
#endif
sys_includes = []
include_guard = "_LIMITS_H"
language = "C"
style = "Tag"
trailer = "#include <bits/limits.h>"
[enum]
prefix_with_name = true
//! limits.h implementation for relibc
pub const PATH_MAX: usize = 4096;
......@@ -10,6 +10,7 @@ pub mod fnmatch;
pub mod getopt;
pub mod grp;
pub mod inttypes;
pub mod limits;
pub mod locale;
pub mod netdb;
pub mod netinet_in;
......
//! stdlib implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html
use core::{intrinsics, iter, mem, ptr};
use core::{intrinsics, iter, mem, ptr, slice};
use rand::distributions::Alphanumeric;
use rand::prng::XorShiftRng;
use rand::rngs::JitterRng;
......@@ -12,6 +12,7 @@ use header::fcntl::*;
use header::string::*;
use header::time::constants::CLOCK_MONOTONIC;
use header::time::timespec;
use header::limits;
use header::wchar::*;
use header::{ctype, errno, unistd};
use platform;
......@@ -572,9 +573,24 @@ pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void
platform::realloc(ptr, size)
}
// #[no_mangle]
pub extern "C" fn realpath(file_name: *const c_char, resolved_name: *mut c_char) -> *mut c_char {
unimplemented!();
#[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 slice = if resolved.is_null() {
&mut path
} else {
slice::from_raw_parts_mut(resolved as *mut u8, 4096)
};
if Sys::realpath(CStr::from_ptr(pathname), slice) < 0 {
return ptr::null_mut();
}
}
if !resolved.is_null() {
resolved
} else {
strdup(path.as_ptr() as *const i8)
}
}
// #[no_mangle]
......
......@@ -3,7 +3,7 @@
use core::{ptr, slice};
use c_str::CStr;
use header::sys_time;
use header::{limits, sys_time};
use header::time::timespec;
use platform;
use platform::types::*;
......@@ -35,8 +35,6 @@ pub const STDIN_FILENO: c_int = 0;
pub const STDOUT_FILENO: c_int = 1;
pub const STDERR_FILENO: c_int = 2;
const PATH_MAX: usize = 4096;
#[no_mangle]
pub extern "C" fn _exit(status: c_int) {
Sys::exit(status)
......@@ -190,7 +188,7 @@ pub extern "C" fn ftruncate(fildes: c_int, length: off_t) -> c_int {
#[no_mangle]
pub extern "C" fn getcwd(mut buf: *mut c_char, mut size: size_t) -> *mut c_char {
let alloc = buf.is_null();
let mut stack_buf = [0; PATH_MAX];
let mut stack_buf = [0; limits::PATH_MAX];
if alloc {
buf = stack_buf.as_mut_ptr();
size = stack_buf.len();
......@@ -305,7 +303,7 @@ pub extern "C" fn getuid() -> uid_t {
#[no_mangle]
pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char {
getcwd(path_name, PATH_MAX)
getcwd(path_name, limits::PATH_MAX)
}
#[no_mangle]
......
use core::fmt::Write;
use alloc::vec::Vec;
use core::fmt::Write as _WriteFmt;
use core::{mem, ptr};
use core_io::Write;
use super::types::*;
use super::{errno, FileWriter, Pal};
use c_str::CStr;
use fs::File;
use header::dirent::dirent;
use header::errno::{EINVAL, ENOSYS};
use header::fcntl;
use header::signal::SIGCHLD;
use header::sys_ioctl::{winsize, TCGETS, TCSETS, TIOCGWINSZ};
// use header::sys_resource::rusage;
......@@ -302,6 +306,39 @@ 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
}
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() - 1;
let read = readlink(CStr::from_bytes_with_nul(&proc_path).unwrap(), &mut out[..len]);
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
}
......
......@@ -112,6 +112,10 @@ pub trait Pal {
fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t;
//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;
......
......@@ -616,6 +616,15 @@ impl Pal for Sys {
e(syscall::read(fd as usize, buf)) as ssize_t
}
fn realpath(pathname: &CStr, out: &mut [u8]) -> c_int {
let file = match File::open(pathname, fcntl::O_PATH) {
Ok(fd) => fd,
Err(_) => return -1
};
e(syscall::fpath(*file as usize, out)) as c_int
}
fn rename(oldpath: &CStr, newpath: &CStr) -> c_int {
match syscall::open(oldpath.to_bytes(), O_WRONLY | O_CLOEXEC) {
Ok(fd) => {
......
......@@ -85,6 +85,7 @@ BINS=\
stdlib/alloc \
stdlib/bsearch \
stdlib/mktemp \
stdlib/realpath \
time/gettimeofday \
unistd/chdir \
unistd/getcwd \
......
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char* path = realpath("stdlib/realpath.c", NULL);
if (!path) {
perror("realpath");
return -1;
}
puts(path);
free(path);
path = malloc(PATH_MAX);
memset(path, 0, PATH_MAX);
realpath("stdlib/realpath.c", path);
if (!path) {
perror("realpath");
free(path);
return -1;
}
puts(path);
free(path);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment