Skip to content

Commit 139c55b

Browse files
committed
add support for link|linkat
1 parent 97c4ca2 commit 139c55b

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
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::{link, linkat}`
28+
([#755](https://github.com/nix-rust/nix/pull/755))
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: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,36 @@ 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+
/// Call the link function to create a link to a file
816+
/// ([see link(2)](http://man7.org/linux/man-pages/man2/link.2.html)).
817+
pub fn link<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(oldpath: &P1, newpath: &P2) -> Result<()> {
818+
let res = try!(try!(oldpath.with_nix_path(|old|
819+
newpath.with_nix_path(|new|
820+
unsafe {
821+
libc::link(old.as_ptr() as *const c_char, new.as_ptr() as *const c_char)
822+
}
823+
)
824+
)));
825+
826+
Errno::result(res).map(drop)
827+
}
828+
829+
/// Call the link function to create a link to a file
830+
/// ([see linkat(2)](http://man7.org/linux/man-pages/man2/linkat.2.html)).
831+
pub fn linkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(olddirfd: RawFd, oldpath: &P1,
832+
newdirfd: RawFd, newpath: &P2, flags: AtFlags) -> Result<()> {
833+
let res = try!(try!(oldpath.with_nix_path(|old|
834+
newpath.with_nix_path(|new|
835+
unsafe {
836+
libc::linkat(olddirfd, old.as_ptr() as *const c_char,
837+
newdirfd, new.as_ptr() as *const c_char, flags.bits())
838+
}
839+
)
840+
)));
841+
842+
Errno::result(res).map(drop)
843+
}
844+
815845
pub fn pipe() -> Result<(RawFd, RawFd)> {
816846
unsafe {
817847
let mut fds: [c_int; 2] = mem::uninitialized();

test/test_unistd.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,36 @@ fn test_fpathconf_limited() {
250250
assert!(path_max.expect("fpathconf failed").expect("PATH_MAX is unlimited") > 0);
251251
}
252252

253+
#[test]
254+
fn test_linkat() {
255+
let tempdir = TempDir::new("nix-test_linkat").unwrap();
256+
let src = tempdir.path().join("foo");
257+
let dst = tempdir.path().join("bar");
258+
File::create(&src).unwrap();
259+
260+
let dirfd = fcntl::open(tempdir.path(),
261+
fcntl::OFlag::empty(),
262+
stat::Mode::empty());
263+
linkat(dirfd.unwrap(),
264+
&src.file_name(),
265+
dirfd.unwrap(),
266+
&dst.file_name(),
267+
fcntl::AtFlags::empty()).unwrap();
268+
assert!(dst.exists());
269+
}
270+
271+
#[test]
272+
fn test_link() {
273+
let tempdir = TempDir::new("nix-test_link").unwrap();
274+
let src = tempdir.path().join("foo");
275+
let dst = tempdir.path().join("bar");
276+
File::create(&src).unwrap();
277+
278+
link(&src, &dst).unwrap();
279+
assert!(dst.exists());
280+
}
281+
282+
253283
#[test]
254284
fn test_pathconf_limited() {
255285
// AFAIK, PATH_MAX is limited on all platforms, so it makes a good test

0 commit comments

Comments
 (0)