Skip to content

Commit e2314b7

Browse files
authored
Fix renameat_with with flags on Android. (#892)
When `renameat_with` is passed non-zero flags, fall back to the `syscall!` macro on ABIs such as Android where libc has a `renameat` but not a `renameat2`. Fixes Stebalien/tempfile#259.
1 parent ff9c7fb commit e2314b7

1 file changed

Lines changed: 26 additions & 4 deletions

File tree

src/backend/libc/fs/syscalls.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,6 @@ pub(crate) fn renameat2(
521521
}
522522
}
523523

524-
/// At present, `libc` only has `renameat2` defined for glibc. On other
525-
/// ABIs, `RenameFlags` has no flags defined, and we use plain `renameat`.
526524
#[cfg(any(
527525
target_os = "android",
528526
all(target_os = "linux", not(target_env = "gnu")),
@@ -535,8 +533,32 @@ pub(crate) fn renameat2(
535533
new_path: &CStr,
536534
flags: RenameFlags,
537535
) -> io::Result<()> {
538-
assert!(flags.is_empty());
539-
renameat(old_dirfd, old_path, new_dirfd, new_path)
536+
// At present, `libc` only has `renameat2` defined for glibc. If we have
537+
// no flags, we can use plain `renameat`, but otherwise we use `syscall!`.
538+
// to call `renameat2` ourselves.
539+
if flags.is_empty() {
540+
renameat(old_dirfd, old_path, new_dirfd, new_path)
541+
} else {
542+
syscall! {
543+
fn renameat2(
544+
olddirfd: c::c_int,
545+
oldpath: *const c::c_char,
546+
newdirfd: c::c_int,
547+
newpath: *const c::c_char,
548+
flags: c::c_uint
549+
) via SYS_renameat2 -> c::c_int
550+
}
551+
552+
unsafe {
553+
ret(renameat2(
554+
borrowed_fd(old_dirfd),
555+
c_str(old_path),
556+
borrowed_fd(new_dirfd),
557+
c_str(new_path),
558+
flags.bits(),
559+
))
560+
}
561+
}
540562
}
541563

542564
pub(crate) fn symlink(old_path: &CStr, new_path: &CStr) -> io::Result<()> {

0 commit comments

Comments
 (0)