Skip to content

Commit 6454a06

Browse files
committed
Add renameat
renameat is (somewhat oddly, imho) in stdio.h. I put it in nix::fcntl because there's no nix::stdio and all its friends (including the AT_* constants) are in nix::fcntl.
1 parent 500036a commit 6454a06

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1919
([#1091](https://github.com/nix-rust/nix/pull/1091))
2020
- Add `unlinkat`
2121
([#1058](https://github.com/nix-rust/nix/pull/1058))
22+
- Add `renameat`.
23+
([#1097](https://github.com/nix-rust/nix/pull/1097))
2224

2325
### Changed
2426
- Support for `ifaddrs` now present when building for Android.

src/fcntl.rs

+12
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,18 @@ pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag, mode: M
165165
Errno::result(fd)
166166
}
167167

168+
pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(old_dirfd: Option<RawFd>, old_path: &P1,
169+
new_dirfd: Option<RawFd>, new_path: &P2)
170+
-> Result<()> {
171+
let res = old_path.with_nix_path(|old_cstr| {
172+
new_path.with_nix_path(|new_cstr| unsafe {
173+
libc::renameat(at_rawfd(old_dirfd), old_cstr.as_ptr(),
174+
at_rawfd(new_dirfd), new_cstr.as_ptr())
175+
})
176+
})??;
177+
Errno::result(res).map(drop)
178+
}
179+
168180
fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
169181
match Errno::result(res) {
170182
Err(err) => Err(err),

test/test_fcntl.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
use nix::fcntl::{openat, open, OFlag, readlink, readlinkat};
1+
use nix::Error;
2+
use nix::errno::*;
3+
use nix::fcntl::{openat, open, OFlag, readlink, readlinkat, renameat};
24
use nix::sys::stat::Mode;
35
use nix::unistd::{close, read};
46
use tempfile::{self, NamedTempFile};
7+
use std::fs::File;
58
use std::io::prelude::*;
69
use std::os::unix::fs;
710

@@ -27,6 +30,22 @@ fn test_openat() {
2730
close(dirfd).unwrap();
2831
}
2932

33+
#[test]
34+
fn test_renameat() {
35+
let old_dir = tempfile::tempdir().unwrap();
36+
let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
37+
let old_path = old_dir.path().join("old");
38+
File::create(&old_path).unwrap();
39+
let new_dir = tempfile::tempdir().unwrap();
40+
let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
41+
renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap();
42+
assert_eq!(renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(),
43+
Error::Sys(Errno::ENOENT));
44+
close(old_dirfd).unwrap();
45+
close(new_dirfd).unwrap();
46+
assert!(new_dir.path().join("new").exists());
47+
}
48+
3049
#[test]
3150
fn test_readlink() {
3251
let tempdir = tempfile::tempdir().unwrap();

0 commit comments

Comments
 (0)