Merge branch 'unlinkat-symlinkat-linkat' into 'master'
add unlinkat(2), symlinkat(2), linkat(2) and expose openat(2) See merge request redox-os/relibc!1212
This commit is contained in:
+12
-1
@@ -80,6 +80,17 @@ pub unsafe extern "C" fn fcntl(fildes: c_int, cmd: c_int, mut __valist: ...) ->
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/open.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn open(path: *const c_char, oflag: c_int, mut __valist: ...) -> c_int {
|
||||
unsafe { openat(AT_FDCWD, path, oflag, __valist) }
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/openat.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn openat(
|
||||
fd: c_int,
|
||||
path: *const c_char,
|
||||
oflag: c_int,
|
||||
mut __valist: ...
|
||||
) -> c_int {
|
||||
let mode = if oflag & O_CREAT == O_CREAT
|
||||
/* || oflag & O_TMPFILE == O_TMPFILE */
|
||||
{
|
||||
@@ -89,7 +100,7 @@ pub unsafe extern "C" fn open(path: *const c_char, oflag: c_int, mut __valist: .
|
||||
};
|
||||
|
||||
let path = unsafe { CStr::from_ptr(path) };
|
||||
Sys::open(path, oflag, mode).or_minus_one_errno()
|
||||
Sys::openat(fd, path, oflag, mode).or_minus_one_errno()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
|
||||
@@ -31,5 +31,6 @@ pub const O_NDELAY: c_int = O_NONBLOCK;
|
||||
// Flags for capability based "at" functions
|
||||
pub const AT_FDCWD: c_int = -100;
|
||||
pub const AT_SYMLINK_NOFOLLOW: c_int = 0x0200;
|
||||
pub const AT_SYMLINK_FOLLOW: c_int = 0x2000;
|
||||
pub const AT_EMPTY_PATH: c_int = 0x4000;
|
||||
pub const AT_REMOVEDIR: c_int = 0x200;
|
||||
|
||||
@@ -577,7 +577,7 @@ pub unsafe extern "C" fn gethostname(mut name: *mut c_char, mut len: size_t) ->
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/getlogin.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn getlogin() -> *mut c_char {
|
||||
const LOGIN_LEN: usize = 256;
|
||||
const LOGIN_LEN: usize = limits::LOGIN_NAME_MAX as usize;
|
||||
static mut LOGIN: [c_char; LOGIN_LEN] = [0; LOGIN_LEN];
|
||||
if getlogin_r((&raw mut LOGIN).cast(), LOGIN_LEN) == 0 {
|
||||
(&raw mut LOGIN).cast()
|
||||
@@ -707,6 +707,22 @@ pub unsafe extern "C" fn link(path1: *const c_char, path2: *const c_char) -> c_i
|
||||
Sys::link(path1, path2).map(|()| 0).or_minus_one_errno()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/linkat.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn linkat(
|
||||
fd1: c_int,
|
||||
path1: *const c_char,
|
||||
fd2: c_int,
|
||||
path2: *const c_char,
|
||||
flags: c_int,
|
||||
) -> c_int {
|
||||
let path1 = unsafe { CStr::from_ptr(path1) };
|
||||
let path2 = unsafe { CStr::from_ptr(path2) };
|
||||
Sys::linkat(fd1, path1, fd2, path2, flags)
|
||||
.map(|()| 0)
|
||||
.or_minus_one_errno()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/lockf.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
|
||||
@@ -1010,6 +1026,16 @@ pub unsafe extern "C" fn symlink(path1: *const c_char, path2: *const c_char) ->
|
||||
Sys::symlink(path1, path2).map(|()| 0).or_minus_one_errno()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/symlinkat.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn symlinkat(path1: *const c_char, fd: c_int, path2: *const c_char) -> c_int {
|
||||
let path1 = unsafe { CStr::from_ptr(path1) };
|
||||
let path2 = unsafe { CStr::from_ptr(path2) };
|
||||
Sys::symlinkat(path1, fd, path2)
|
||||
.map(|()| 0)
|
||||
.or_minus_one_errno()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sync.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn sync() {
|
||||
@@ -1123,6 +1149,15 @@ pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
|
||||
Sys::unlink(path).map(|()| 0).or_minus_one_errno()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/unlinkat.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn unlinkat(fd: c_int, path: *const c_char, flags: c_int) -> c_int {
|
||||
let path = unsafe { CStr::from_ptr(path) };
|
||||
Sys::unlinkat(fd, path, flags)
|
||||
.map(|()| 0)
|
||||
.or_minus_one_errno()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/009695399/functions/usleep.html>.
|
||||
///
|
||||
/// # Deprecation
|
||||
|
||||
+16
-13
@@ -487,17 +487,12 @@ impl Pal for Sys {
|
||||
}
|
||||
|
||||
fn link(path1: CStr, path2: CStr) -> Result<()> {
|
||||
e_raw(unsafe {
|
||||
syscall!(
|
||||
LINKAT,
|
||||
AT_FDCWD,
|
||||
path1.as_ptr(),
|
||||
AT_FDCWD,
|
||||
path2.as_ptr(),
|
||||
0
|
||||
)
|
||||
})
|
||||
.map(|_| ())
|
||||
Sys::linkat(AT_FDCWD, path1, AT_FDCWD, path2, 0)
|
||||
}
|
||||
|
||||
fn linkat(fd1: c_int, path1: CStr, fd2: c_int, path2: CStr, flags: c_int) -> Result<()> {
|
||||
e_raw(unsafe { syscall!(LINKAT, fd1, path1.as_ptr(), fd2, path2.as_ptr(), flags) })
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> Result<off_t> {
|
||||
@@ -817,7 +812,11 @@ impl Pal for Sys {
|
||||
}
|
||||
|
||||
fn symlink(path1: CStr, path2: CStr) -> Result<()> {
|
||||
e_raw(unsafe { syscall!(SYMLINKAT, path1.as_ptr(), AT_FDCWD, path2.as_ptr()) }).map(|_| ())
|
||||
Sys::symlinkat(path1, AT_FDCWD, path2)
|
||||
}
|
||||
|
||||
fn symlinkat(path1: CStr, fd: c_int, path2: CStr) -> Result<()> {
|
||||
e_raw(unsafe { syscall!(SYMLINKAT, path1.as_ptr(), fd, path2.as_ptr()) }).map(|_| ())
|
||||
}
|
||||
|
||||
fn sync() -> Result<()> {
|
||||
@@ -874,7 +873,11 @@ impl Pal for Sys {
|
||||
}
|
||||
|
||||
fn unlink(path: CStr) -> Result<()> {
|
||||
e_raw(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), 0) }).map(|_| ())
|
||||
Sys::unlinkat(AT_FDCWD, path, 0)
|
||||
}
|
||||
|
||||
fn unlinkat(fd: c_int, path: CStr, flags: c_int) -> Result<()> {
|
||||
e_raw(unsafe { syscall!(UNLINKAT, fd, path.as_ptr(), flags) }).map(|_| ())
|
||||
}
|
||||
|
||||
fn waitpid(pid: pid_t, stat_loc: Option<Out<c_int>>, options: c_int) -> Result<pid_t> {
|
||||
|
||||
@@ -225,6 +225,9 @@ pub trait Pal {
|
||||
/// Platform implementation of [`link()`](crate::header::unistd::link) from [`unistd.h`](crate::header::unistd).
|
||||
fn link(path1: CStr, path2: CStr) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`linkat()`](crate::header::unistd::linkat) from [`unistd.h`](crate::header::unistd).
|
||||
fn linkat(fd1: c_int, oldpath: CStr, fd2: c_int, newpath: CStr, flags: c_int) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`lseek()`](crate::header::unistd::lseek) from [`unistd.h`](crate::header::unistd).
|
||||
fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> Result<off_t>;
|
||||
|
||||
@@ -370,6 +373,9 @@ pub trait Pal {
|
||||
/// Platform implementation of [`symlink()`](crate::header::unistd::symlink) from [`unistd.h`](crate::header::unistd).
|
||||
fn symlink(path1: CStr, path2: CStr) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`symlinkat()`](crate::header::unistd::symlinkat) from [`unistd.h`](crate::header::unistd).
|
||||
fn symlinkat(path1: CStr, fd: c_int, path2: CStr) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`sync()`](crate::header::unistd::sync) from [`unistd.h`](crate::header::unistd).
|
||||
fn sync() -> Result<()>;
|
||||
|
||||
@@ -400,6 +406,9 @@ pub trait Pal {
|
||||
/// Platform implementation of [`unlink()`](crate::header::unistd::unlink) from [`unistd.h`](crate::header::unistd).
|
||||
fn unlink(path: CStr) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`unlinkat()`](crate::header::unistd::unlinkat) from [`unistd.h`](crate::header::unistd).
|
||||
fn unlinkat(fd: c_int, path: CStr, flags: c_int) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`waitpid()`](crate::header::sys_wait::waitpid) from [`sys/wait.h`](crate::header::sys_wait).
|
||||
fn waitpid(pid: pid_t, stat_loc: Option<Out<c_int>>, options: c_int) -> Result<pid_t>;
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ use crate::{
|
||||
ENOSYS, EOPNOTSUPP, EPERM,
|
||||
},
|
||||
fcntl::{
|
||||
self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_GETLK, F_OFD_SETLK,
|
||||
F_RDLCK, F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock,
|
||||
self, AT_EMPTY_PATH, AT_FDCWD, AT_REMOVEDIR, AT_SYMLINK_FOLLOW, AT_SYMLINK_NOFOLLOW,
|
||||
F_GETLK, F_OFD_GETLK, F_OFD_SETLK, F_RDLCK, F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock,
|
||||
},
|
||||
limits,
|
||||
pthread::{pthread_cancel, pthread_create},
|
||||
@@ -772,6 +772,29 @@ impl Pal for Sys {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn linkat(fd1: c_int, oldpath: CStr, fd2: c_int, newpath: CStr, flags: c_int) -> Result<()> {
|
||||
// make sure the flags passed are valid.
|
||||
// valid states: AT_SYMLINK_FOLLOW, or 0.
|
||||
if (flags & !(AT_SYMLINK_FOLLOW)) != 0 {
|
||||
return Err(Errno(EINVAL));
|
||||
}
|
||||
let newpath = newpath.to_str().map_err(|_| Errno(EINVAL))?;
|
||||
|
||||
// By default, we don't follow the symlink if there is one.
|
||||
// We only follow it if AT_SYMLINK_FOLLOW is passed in flags.
|
||||
// We represent this by setting O_NOFOLLOW by default, and clearing it
|
||||
// if AT_SYMLINK_FOLLOW is present.
|
||||
let mut oflags = fcntl::O_PATH | fcntl::O_CLOEXEC | fcntl::O_NOFOLLOW;
|
||||
if (flags & AT_SYMLINK_FOLLOW) == AT_SYMLINK_FOLLOW {
|
||||
oflags &= !fcntl::O_NOFOLLOW;
|
||||
}
|
||||
|
||||
let file = File::openat(fd1, oldpath, oflags)?;
|
||||
let newpath = openat2_path(fd2, newpath, 0)?;
|
||||
syscall::flink(*file as usize, newpath)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t> {
|
||||
Ok(syscall::lseek(fd as usize, offset as isize, whence as usize)? as off_t)
|
||||
}
|
||||
@@ -1240,7 +1263,12 @@ impl Pal for Sys {
|
||||
}
|
||||
|
||||
fn symlink(path1: CStr, path2: CStr) -> Result<()> {
|
||||
let mut file = File::create(
|
||||
Sys::symlinkat(path1, AT_FDCWD, path2)
|
||||
}
|
||||
|
||||
fn symlinkat(path1: CStr, fd: c_int, path2: CStr) -> Result<()> {
|
||||
let mut file = File::createat(
|
||||
fd,
|
||||
path2,
|
||||
fcntl::O_WRONLY | fcntl::O_SYMLINK | fcntl::O_CLOEXEC,
|
||||
0o777,
|
||||
@@ -1511,6 +1539,17 @@ impl Pal for Sys {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unlinkat(fd: c_int, path: CStr, flags: c_int) -> Result<()> {
|
||||
if (flags & !AT_REMOVEDIR) != 0 {
|
||||
return Err(Errno(EINVAL));
|
||||
}
|
||||
let path = path.to_str().map_err(|_| Errno(EINVAL))?;
|
||||
let path = openat2_path(fd, path, 0)?;
|
||||
let canon = canonicalize(&path)?;
|
||||
redox_rt::sys::unlink(&canon, flags.try_into().map_err(|_| Errno(EINVAL))?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn waitpid(pid: pid_t, stat_loc: Option<Out<'_, c_int>>, options: c_int) -> Result<pid_t> {
|
||||
let res = None;
|
||||
let mut status = 0;
|
||||
|
||||
Reference in New Issue
Block a user