Skip to content

Commit

Permalink
Add renameat and AT_FDCWD
Browse files Browse the repository at this point in the history
These syscalls are (somewhat oddly, imho) in stdio.h. I put them in
nix::fcntl because there's no nix::stdio and all their friends
(including the AT_* constants) are in nix::fcntl.
  • Loading branch information
scottlamb committed Jul 17, 2019
1 parent 5e463aa commit 0f4a321
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#1084](https://github.com/nix-rust/nix/pull/1084))
- Add `posix_fadvise`.
([#1089](https://github.com/nix-rust/nix/pull/1089))
- Add `renameat` and `AT_FDCWD`.
([#1097](https://github.com/nix-rust/nix/pull/1097))

### Changed
- Support for `ifaddrs` now present when building for Android.
Expand Down
13 changes: 13 additions & 0 deletions src/fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use sys::uio::IoVec; // For vmsplice
target_env = "freebsd"))]
pub use self::posix_fadvise::*;

pub const AT_FDCWD: RawFd = libc::AT_FDCWD as RawFd;

libc_bitflags!{
pub struct AtFlags: c_int {
AT_SYMLINK_NOFOLLOW;
Expand Down Expand Up @@ -164,6 +166,17 @@ pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag, mode: M
Errno::result(fd)
}

pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(old_dirfd: RawFd, old_path: &P1,
new_dirfd: RawFd, new_path: &P2)
-> Result<()> {
let res = old_path.with_nix_path(|old_cstr| {
new_path.with_nix_path(|new_cstr| unsafe {
libc::renameat(old_dirfd, old_cstr.as_ptr(), new_dirfd, new_cstr.as_ptr())
})
})??;
Errno::result(res).map(drop)
}

fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
match Errno::result(res) {
Err(err) => Err(err),
Expand Down
22 changes: 21 additions & 1 deletion test/test_fcntl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use nix::fcntl::{openat, open, OFlag, readlink, readlinkat};
use nix::Error;
use nix::errno::*;
use nix::fcntl::{openat, open, OFlag, readlink, readlinkat, renameat};
use nix::sys::stat::Mode;
use nix::unistd::{close, read};
use tempfile::{self, NamedTempFile};
use std::fs::File;
use std::io::prelude::*;
use std::os::unix::fs;

Expand All @@ -27,6 +30,23 @@ fn test_openat() {
close(dirfd).unwrap();
}

#[test]
fn test_renameat() {
let old_dir = tempfile::tempdir().unwrap();
let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
let old_path = old_dir.path().join("old");
File::create(&old_path).unwrap();
let new_dir = tempfile::tempdir().unwrap();
let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
renameat(old_dirfd, "old", new_dirfd, "new").unwrap();
assert_eq!(renameat(old_dirfd, "old", new_dirfd, "new").unwrap_err(),
Error::Sys(Errno::ENOENT));
close(old_dirfd).unwrap();
close(new_dirfd).unwrap();
assert!(!old_path.exists());
assert!(new_dir.path().join("new").exists());
}

#[test]
fn test_readlink() {
let tempdir = tempfile::tempdir().unwrap();
Expand Down

0 comments on commit 0f4a321

Please sign in to comment.