Skip to content

Commit c841902

Browse files
committed
enhanced renameat2 to support raw syscalls
- replace libc::renameat2() with libc::syscall() for broader compatibility - define syscall numbers manually for multiple architectures - update conditional compilation to support all Linux environments - expand test coverage for additional architectures added changelog entry for renameat2 support rust fmt handle all linux archs instead of explictly defining them
1 parent a72936d commit c841902

File tree

3 files changed

+18
-44
lines changed

3 files changed

+18
-44
lines changed

changelog/2657.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Changed `renameat2` to use raw syscalls instead of libc functions, enabling support for musl libc and other Linux environments beyond GNU libc.

src/fcntl.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -444,22 +444,24 @@ pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath, Fd1: std::os::fd::As
444444
}
445445
}
446446

447-
#[cfg(all(target_os = "linux", target_env = "gnu"))]
447+
#[cfg(target_os = "linux")]
448448
#[cfg(feature = "fs")]
449-
libc_bitflags! {
449+
bitflags::bitflags! {
450450
/// Flags for use with [`renameat2`].
451451
#[cfg_attr(docsrs, doc(cfg(feature = "fs")))]
452+
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
453+
#[repr(transparent)]
452454
pub struct RenameFlags: u32 {
453455
/// Atomically exchange `old_path` and `new_path`.
454-
RENAME_EXCHANGE;
456+
const RENAME_EXCHANGE = 1 << 1;
455457
/// Don't overwrite `new_path` of the rename. Return an error if `new_path` already
456458
/// exists.
457-
RENAME_NOREPLACE;
459+
const RENAME_NOREPLACE = 1 << 0;
458460
/// creates a "whiteout" object at the source of the rename at the same time as performing
459461
/// the rename.
460462
///
461463
/// This operation makes sense only for overlay/union filesystem implementations.
462-
RENAME_WHITEOUT;
464+
const RENAME_WHITEOUT = 1 << 2;
463465
}
464466
}
465467

@@ -471,7 +473,7 @@ feature! {
471473
///
472474
/// # See Also
473475
/// * [`rename`](https://man7.org/linux/man-pages/man2/rename.2.html)
474-
#[cfg(all(target_os = "linux", target_env = "gnu"))]
476+
#[cfg(target_os = "linux")]
475477
pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath, Fd1: std::os::fd::AsFd, Fd2: std::os::fd::AsFd>(
476478
old_dirfd: Fd1,
477479
old_path: &P1,
@@ -483,7 +485,10 @@ pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath, Fd1: std::os::fd::A
483485

484486
let res = old_path.with_nix_path(|old_cstr| {
485487
new_path.with_nix_path(|new_cstr| unsafe {
486-
libc::renameat2(
488+
// Use raw syscall instead of libc::renameat2 to support musl libc and other
489+
// environments where the libc function may not be available.
490+
libc::syscall(
491+
libc::SYS_renameat2,
487492
old_dirfd.as_fd().as_raw_fd(),
488493
old_cstr.as_ptr(),
489494
new_dirfd.as_fd().as_raw_fd(),
@@ -492,7 +497,7 @@ pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath, Fd1: std::os::fd::A
492497
)
493498
})
494499
})??;
495-
Errno::result(res).map(drop)
500+
Errno::result(res as c_int).map(drop)
496501
}
497502

498503
fn wrap_readlink_result(mut v: Vec<u8>, len: ssize_t) -> Result<OsString> {

test/test_fcntl.rs

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,7 @@ use nix::fcntl::{openat, readlinkat, renameat};
88
#[cfg(target_os = "linux")]
99
use nix::fcntl::{openat2, OpenHow, ResolveFlag};
1010

11-
#[cfg(all(
12-
target_os = "linux",
13-
target_env = "gnu",
14-
any(
15-
target_arch = "x86_64",
16-
target_arch = "powerpc",
17-
target_arch = "s390x"
18-
)
19-
))]
11+
#[cfg(target_os = "linux")]
2012
use nix::fcntl::{renameat2, RenameFlags};
2113
#[cfg(not(target_os = "redox"))]
2214
use nix::sys::stat::Mode;
@@ -132,15 +124,7 @@ fn test_renameat() {
132124
}
133125

134126
#[test]
135-
#[cfg(all(
136-
target_os = "linux",
137-
target_env = "gnu",
138-
any(
139-
target_arch = "x86_64",
140-
target_arch = "powerpc",
141-
target_arch = "s390x"
142-
)
143-
))]
127+
#[cfg(target_os = "linux")]
144128
fn test_renameat2_behaves_like_renameat_with_no_flags() {
145129
let old_dir = tempfile::tempdir().unwrap();
146130
let old_dirfd =
@@ -161,15 +145,7 @@ fn test_renameat2_behaves_like_renameat_with_no_flags() {
161145
}
162146

163147
#[test]
164-
#[cfg(all(
165-
target_os = "linux",
166-
target_env = "gnu",
167-
any(
168-
target_arch = "x86_64",
169-
target_arch = "powerpc",
170-
target_arch = "s390x"
171-
)
172-
))]
148+
#[cfg(target_os = "linux")]
173149
fn test_renameat2_exchange() {
174150
let old_dir = tempfile::tempdir().unwrap();
175151
let old_dirfd =
@@ -206,15 +182,7 @@ fn test_renameat2_exchange() {
206182
}
207183

208184
#[test]
209-
#[cfg(all(
210-
target_os = "linux",
211-
target_env = "gnu",
212-
any(
213-
target_arch = "x86_64",
214-
target_arch = "powerpc",
215-
target_arch = "s390x"
216-
)
217-
))]
185+
#[cfg(target_os = "linux")]
218186
fn test_renameat2_noreplace() {
219187
let old_dir = tempfile::tempdir().unwrap();
220188
let old_dirfd =

0 commit comments

Comments
 (0)