Skip to content

Commit

Permalink
feat: AT_EMPTY_PATH for linkat() (#2284)
Browse files Browse the repository at this point in the history
* feat: AT_EMPTY_PATH for linkat()

* try fixing import

* fix changelog name
  • Loading branch information
SteveLauC authored Jan 8, 2024
1 parent f55dee9 commit 3554102
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 18 deletions.
1 change: 1 addition & 0 deletions changelog/2284.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enable the `AT_EMPTY_PATH` flag for the `linkat()` function
1 change: 1 addition & 0 deletions changelog/2284.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The `LinkatFlags` type has been deprecated, please use `AtFlags` instead.
26 changes: 13 additions & 13 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1253,19 +1253,24 @@ pub fn isatty(fd: RawFd) -> Result<bool> {
}
}

/// Flags for `linkat` function.
#[derive(Clone, Copy, Debug)]
pub enum LinkatFlags {
SymlinkFollow,
NoSymlinkFollow,
#[cfg(not(target_os = "redox"))]
pub type LinkatFlags = AtFlags;
#[cfg(not(target_os = "redox"))]
impl LinkatFlags {
#[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
#[allow(non_upper_case_globals)]
pub const SymlinkFollow: LinkatFlags = LinkatFlags::AT_SYMLINK_FOLLOW;
#[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
#[allow(non_upper_case_globals)]
pub const NoSymlinkFollow: LinkatFlags = LinkatFlags::empty();
}

/// Link one file to another file
///
/// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the
/// case of a relative `oldpath`, the path is interpreted relative to the directory associated
/// with file descriptor `olddirfd` instead of the current working directory and similiarly for
/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and
/// `newpath` and file descriptor `newdirfd`. In case `flag` is `AtFlags::AT_SYMLINK_FOLLOW` and
/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created.
/// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath`
/// and/or `newpath` is then interpreted relative to the current working directory of the calling
Expand All @@ -1279,21 +1284,16 @@ pub fn linkat<P: ?Sized + NixPath>(
oldpath: &P,
newdirfd: Option<RawFd>,
newpath: &P,
flag: LinkatFlags,
flag: AtFlags,
) -> Result<()> {
let atflag = match flag {
LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW,
LinkatFlags::NoSymlinkFollow => AtFlags::empty(),
};

let res = oldpath.with_nix_path(|oldcstr| {
newpath.with_nix_path(|newcstr| unsafe {
libc::linkat(
at_rawfd(olddirfd),
oldcstr.as_ptr(),
at_rawfd(newdirfd),
newcstr.as_ptr(),
atflag.bits() as libc::c_int,
flag.bits(),
)
})
})??;
Expand Down
20 changes: 15 additions & 5 deletions test/test_unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,8 @@ fn test_symlinkat() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_file() {
use nix::fcntl::AtFlags;

let tempdir = tempdir().unwrap();
let oldfilename = "foo.txt";
let oldfilepath = tempdir.path().join(oldfilename);
Expand All @@ -918,7 +920,7 @@ fn test_linkat_file() {
oldfilename,
Some(dirfd),
newfilename,
LinkatFlags::SymlinkFollow,
AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
Expand All @@ -927,6 +929,8 @@ fn test_linkat_file() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_olddirfd_none() {
use nix::fcntl::AtFlags;

let _dr = crate::DirRestore::new();

let tempdir_oldfile = tempdir().unwrap();
Expand Down Expand Up @@ -955,7 +959,7 @@ fn test_linkat_olddirfd_none() {
oldfilename,
Some(dirfd),
newfilename,
LinkatFlags::SymlinkFollow,
AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
Expand All @@ -964,6 +968,8 @@ fn test_linkat_olddirfd_none() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_newdirfd_none() {
use nix::fcntl::AtFlags;

let _dr = crate::DirRestore::new();

let tempdir_oldfile = tempdir().unwrap();
Expand Down Expand Up @@ -992,7 +998,7 @@ fn test_linkat_newdirfd_none() {
oldfilename,
None,
newfilename,
LinkatFlags::SymlinkFollow,
AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
Expand All @@ -1001,6 +1007,8 @@ fn test_linkat_newdirfd_none() {
#[test]
#[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))]
fn test_linkat_no_follow_symlink() {
use nix::fcntl::AtFlags;

let _m = crate::CWD_LOCK.read();

let tempdir = tempdir().unwrap();
Expand Down Expand Up @@ -1030,7 +1038,7 @@ fn test_linkat_no_follow_symlink() {
symoldfilename,
Some(dirfd),
newfilename,
LinkatFlags::NoSymlinkFollow,
AtFlags::empty(),
)
.unwrap();

Expand All @@ -1044,6 +1052,8 @@ fn test_linkat_no_follow_symlink() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_follow_symlink() {
use nix::fcntl::AtFlags;

let _m = crate::CWD_LOCK.read();

let tempdir = tempdir().unwrap();
Expand Down Expand Up @@ -1073,7 +1083,7 @@ fn test_linkat_follow_symlink() {
symoldfilename,
Some(dirfd),
newfilename,
LinkatFlags::SymlinkFollow,
AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();

Expand Down

0 comments on commit 3554102

Please sign in to comment.