Skip to content

Commit fd1ff37

Browse files
committed
add support for symlink|symlinkat
1 parent 97c4ca2 commit fd1ff37

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2424
([#739](https://github.com/nix-rust/nix/pull/739))
2525
- Added nix::sys::ptrace::detach.
2626
([#749](https://github.com/nix-rust/nix/pull/749))
27+
- Added nix::unistd::{symlink,symlinkat}.
28+
([#756](https://github.com/nix-rust/nix/pull/756))
2729

2830
### Changed
2931
- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))

src/unistd.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,39 @@ pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc:
812812
Errno::result(res).map(|r| r as libc::off64_t)
813813
}
814814

815+
/// Make a new name for a file
816+
/// ([see symlink(2)](http://man7.org/linux/man-pages/man2/symlink.2.html)).
817+
pub fn symlink<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(target: &P1,
818+
linkpath: &P2) -> Result<()> {
819+
let res = try!(try!(target.with_nix_path(|t|
820+
linkpath.with_nix_path(|l|
821+
unsafe {
822+
libc::symlink(t.as_ptr() as *const c_char, l.as_ptr() as *const c_char)
823+
}
824+
)
825+
)));
826+
827+
Errno::result(res).map(drop)
828+
}
829+
830+
/// Make a new name for a file
831+
/// ([see symlinkat(2)](http://man7.org/linux/man-pages/man2/symlinkat.2.html)).
832+
pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(target: &P1,
833+
newdirfd: RawFd,
834+
linkpath: &P2) -> Result<()> {
835+
let res = try!(try!(target.with_nix_path(|t|
836+
linkpath.with_nix_path(|l|
837+
unsafe {
838+
libc::symlinkat(t.as_ptr() as *const c_char,
839+
newdirfd,
840+
l.as_ptr() as *const c_char)
841+
}
842+
)
843+
)));
844+
845+
Errno::result(res).map(drop)
846+
}
847+
815848
pub fn pipe() -> Result<(RawFd, RawFd)> {
816849
unsafe {
817850
let mut fds: [c_int; 2] = mem::uninitialized();

test/test_fcntl.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use nix::fcntl::{openat, open, OFlag, O_RDONLY, readlink, readlinkat};
22
use nix::sys::stat::Mode;
3-
use nix::unistd::{close, read};
3+
use nix::unistd::{close, read, symlink, symlinkat};
44
use tempdir::TempDir;
55
use tempfile::NamedTempFile;
66
use std::io::prelude::*;
7-
use std::os::unix::fs;
87

98
#[test]
109
fn test_openat() {
@@ -30,19 +29,29 @@ fn test_openat() {
3029

3130
#[test]
3231
fn test_readlink() {
33-
let tempdir = TempDir::new("nix-test_readdir")
32+
let tempdir = TempDir::new("nix-test_readdlink")
33+
.unwrap_or_else(|e| panic!("tempdir failed: {}", e));
34+
let src = tempdir.path().join("a");
35+
let dst = tempdir.path().join("b");
36+
symlink(src.as_path(), dst.as_path()).unwrap();
37+
38+
let mut buf = vec![0; src.to_str().unwrap().len() + 1];
39+
assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
40+
src.to_str().unwrap());
41+
}
42+
43+
#[test]
44+
fn test_readlinkat() {
45+
let tempdir = TempDir::new("nix-test_readlinkat")
3446
.unwrap_or_else(|e| panic!("tempdir failed: {}", e));
3547
let src = tempdir.path().join("a");
3648
let dst = tempdir.path().join("b");
37-
println!("a: {:?}, b: {:?}", &src, &dst);
38-
fs::symlink(&src.as_path(), &dst.as_path()).unwrap();
3949
let dirfd = open(tempdir.path(),
4050
OFlag::empty(),
4151
Mode::empty()).unwrap();
52+
symlinkat(src.as_path(), dirfd, dst.file_name().unwrap()).unwrap();
4253

4354
let mut buf = vec![0; src.to_str().unwrap().len() + 1];
44-
assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
45-
src.to_str().unwrap());
4655
assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(),
4756
src.to_str().unwrap());
4857
}

0 commit comments

Comments
 (0)