Skip to content

Commit

Permalink
Implement symlinkat
Browse files Browse the repository at this point in the history
  • Loading branch information
oblique committed Dec 11, 2018
1 parent f1b12d6 commit 723ae99
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
28 changes: 28 additions & 0 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,34 @@ pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
Errno::result(res).map(drop)
}

/// Creates a symbolic link at `path2` which points to `path1`.
///
/// If `dirfd` has a value, then `path2` is relative to directory associated
/// with the file descriptor.
///
/// If `dirfd` is `None`, then `path2` is relative to the current working directory.
/// This is identical to `libc::symlink(path1, path2)`.
///
/// See also [symlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
path1: &P1,
dirfd: Option<RawFd>,
path2: &P2) -> Result<()> {
let res =
path1.with_nix_path(|path1| {
path2.with_nix_path(|path2| {
unsafe {
libc::symlinkat(
path1.as_ptr(),
dirfd.unwrap_or(libc::AT_FDCWD),
path2.as_ptr()
)
}
})
})??;
Errno::result(res).map(drop)
}

/// Returns the current directory as a `PathBuf`
///
/// Err is returned if the current user doesn't have the permission to read or search a component
Expand Down
21 changes: 20 additions & 1 deletion test/test_unistd.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use nix::fcntl::{fcntl, FcntlArg, FdFlag, open, OFlag};
use nix::fcntl::{fcntl, FcntlArg, FdFlag, open, OFlag, readlink};
use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
Expand Down Expand Up @@ -543,3 +543,22 @@ fn test_canceling_alarm() {
assert_eq!(alarm::set(60), None);
assert_eq!(alarm::cancel(), Some(60));
}

#[test]
fn test_symlinkat() {
let mut buf = [0; 1024];
let tempdir = tempfile::tempdir().unwrap();

let target = tempdir.path().join("a");
let linkpath = tempdir.path().join("b");
symlinkat(&target, None, &linkpath).unwrap();
assert_eq!(readlink(&linkpath, &mut buf).unwrap().to_str().unwrap(),
target.to_str().unwrap());

let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
let target = "c";
let linkpath = "d";
symlinkat(target, Some(dirfd), linkpath).unwrap();
assert_eq!(readlink(&tempdir.path().join(linkpath), &mut buf).unwrap().to_str().unwrap(),
target);
}

0 comments on commit 723ae99

Please sign in to comment.