diff --git a/changelog/2582.changed.md b/changelog/2582.changed.md new file mode 100644 index 0000000000..fb5b66d9eb --- /dev/null +++ b/changelog/2582.changed.md @@ -0,0 +1 @@ +linkat: allow distinct types for path arguments diff --git a/src/unistd.rs b/src/unistd.rs index 1130318294..9c803d8c9a 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1577,11 +1577,11 @@ impl LinkatFlags { /// # References /// See also [linkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html) #[cfg(not(target_os = "redox"))] // Redox does not have this yet -pub fn linkat( +pub fn linkat( olddirfd: Fd1, - oldpath: &P, + oldpath: &P1, newdirfd: Fd2, - newpath: &P, + newpath: &P2, flag: AtFlags, ) -> Result<()> { use std::os::fd::AsRawFd; diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 5cb019bd95..19b9f94284 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -927,6 +927,40 @@ fn test_linkat_file() { assert!(newfilepath.exists()); } +#[test] +#[cfg(not(any(target_os = "redox", target_os = "haiku")))] +/// This test is the same as [test_linkat_file], but ensures that two different types can be used +/// as the path arguments. +fn test_linkat_pathtypes() { + use nix::fcntl::AtFlags; + + let tempdir = tempdir().unwrap(); + let oldfilename = "foo.txt"; + let oldfilepath = tempdir.path().join(oldfilename); + + let newfilename = "bar.txt"; + let newfilepath = tempdir.path().join(newfilename); + + // Create file + File::create(oldfilepath).unwrap(); + + // Get file descriptor for base directory + let dirfd = + fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) + .unwrap(); + + // Attempt hard link file at relative path + linkat( + &dirfd, + PathBuf::from(oldfilename).as_path(), + &dirfd, + newfilename, + AtFlags::AT_SYMLINK_FOLLOW, + ) + .unwrap(); + assert!(newfilepath.exists()); +} + #[test] #[cfg(not(any(target_os = "redox", target_os = "haiku")))] fn test_linkat_olddirfd_none() {