Skip to content

Commit 833828e

Browse files
authored
feat: AT_EMPTY_PATH for fchownat on Linux/Android/FreeBSD/Hurd (#2267)
1 parent 0e8efe9 commit 833828e

File tree

5 files changed

+23
-18
lines changed

5 files changed

+23
-18
lines changed

changelog/2267.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enable the `AT_EMPTY_PATH` flag for the `fchownat()` function

changelog/2267.removed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The `FchownatFlags` type has been deprecated, please use `AtFlags` instead.

src/fcntl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use crate::{sys::stat::Mode, NixPath, Result};
4343
pub use self::posix_fadvise::{posix_fadvise, PosixFadviseAdvice};
4444

4545
#[cfg(not(target_os = "redox"))]
46-
#[cfg(any(feature = "fs", feature = "process"))]
46+
#[cfg(any(feature = "fs", feature = "process", feature = "user"))]
4747
libc_bitflags! {
4848
#[cfg_attr(docsrs, doc(cfg(any(feature = "fs", feature = "process"))))]
4949
pub struct AtFlags: c_int {

src/unistd.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -737,11 +737,17 @@ pub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
737737
Errno::result(res).map(drop)
738738
}
739739

740-
/// Flags for `fchownat` function.
741-
#[derive(Clone, Copy, Debug)]
742-
pub enum FchownatFlags {
743-
FollowSymlink,
744-
NoFollowSymlink,
740+
// Just a wrapper around `AtFlags` so that we can help our users migrate.
741+
#[cfg(not(target_os = "redox"))]
742+
pub type FchownatFlags = AtFlags;
743+
#[cfg(not(target_os = "redox"))]
744+
impl FchownatFlags {
745+
#[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
746+
#[allow(non_upper_case_globals)]
747+
pub const FollowSymlink: FchownatFlags = FchownatFlags::empty();
748+
#[deprecated(since = "0.28.0", note = "The variant is deprecated, please use `AtFlags` instead")]
749+
#[allow(non_upper_case_globals)]
750+
pub const NoFollowSymlink: FchownatFlags = FchownatFlags::AT_SYMLINK_NOFOLLOW;
745751
}
746752

747753
/// Change the ownership of the file at `path` to be owned by the specified
@@ -755,10 +761,10 @@ pub enum FchownatFlags {
755761
/// with the file descriptor `dirfd` or the current working directory
756762
/// if `dirfd` is `None`.
757763
///
758-
/// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link,
764+
/// If `flag` is `AtFlags::AT_SYMLINK_NOFOLLOW` and `path` names a symbolic link,
759765
/// then the mode of the symbolic link is changed.
760766
///
761-
/// `fchownat(None, path, owner, group, FchownatFlags::NoFollowSymlink)` is identical to
767+
/// `fchownat(None, path, owner, group, AtFlags::AT_SYMLINK_NOFOLLOW)` is identical to
762768
/// a call `libc::lchown(path, owner, group)`. That's why `lchown` is unimplemented in
763769
/// the `nix` crate.
764770
///
@@ -771,20 +777,16 @@ pub fn fchownat<P: ?Sized + NixPath>(
771777
path: &P,
772778
owner: Option<Uid>,
773779
group: Option<Gid>,
774-
flag: FchownatFlags,
780+
flag: AtFlags,
775781
) -> Result<()> {
776-
let atflag = match flag {
777-
FchownatFlags::FollowSymlink => AtFlags::empty(),
778-
FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
779-
};
780782
let res = path.with_nix_path(|cstr| unsafe {
781783
let (uid, gid) = chown_raw_ids(owner, group);
782784
libc::fchownat(
783785
at_rawfd(dirfd),
784786
cstr.as_ptr(),
785787
uid,
786788
gid,
787-
atflag.bits() as libc::c_int,
789+
flag.bits()
788790
)
789791
})?;
790792

test/test_unistd.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ fn test_fchown() {
551551
#[test]
552552
#[cfg(not(target_os = "redox"))]
553553
fn test_fchownat() {
554+
use nix::fcntl::AtFlags;
555+
554556
let _dr = crate::DirRestore::new();
555557
// Testing for anything other than our own UID/GID is hard.
556558
let uid = Some(getuid());
@@ -564,14 +566,13 @@ fn test_fchownat() {
564566

565567
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
566568

567-
fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink)
568-
.unwrap();
569+
fchownat(Some(dirfd), "file", uid, gid, AtFlags::empty()).unwrap();
569570

570571
chdir(tempdir.path()).unwrap();
571-
fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
572+
fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap();
572573

573574
fs::remove_file(&path).unwrap();
574-
fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err();
575+
fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap_err();
575576
}
576577

577578
#[test]

0 commit comments

Comments
 (0)