1758: Add chflags r=rtzoeller a=asomers



Co-authored-by: musikid <musikid@outlook.com>
This commit is contained in:
bors[bot] 2022-07-14 04:15:39 +00:00 committed by GitHub
commit e5f354cf58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 178 additions and 1 deletions

View File

@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1761](https://github.com/nix-rust/nix/pull/1761))
- Added const constructors for `TimeSpec` and `TimeVal`
(#[1760](https://github.com/nix-rust/nix/pull/1760))
- Added `chflags`.
(#[1758](https://github.com/nix-rust/nix/pull/1758))
- Added `aio_writev` and `aio_readv`.
(#[1713](https://github.com/nix-rust/nix/pull/1713))
- impl `From<uid_t>` for `Uid` and `From<gid_t>` for `Gid`

View File

@ -27,7 +27,7 @@ targets = [
]
[dependencies]
libc = { version = "0.2.126", features = [ "extra_traits" ] }
libc = { git = "https://github.com/rust-lang/libc", rev = "8dbd2c9", features = [ "extra_traits" ] }
bitflags = "1.1"
cfg-if = "1.0"
pin-utils = { version = "0.1.0", optional = true }

View File

@ -1,4 +1,12 @@
pub use libc::{dev_t, mode_t};
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
pub use libc::c_uint;
#[cfg(any(
target_os = "netbsd",
target_os = "freebsd",
target_os = "dragonfly"
))]
pub use libc::c_ulong;
pub use libc::stat as FileStat;
use crate::{Result, NixPath, errno::Errno};
@ -43,6 +51,110 @@ libc_bitflags! {
}
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os="openbsd"))]
pub type type_of_file_flag = c_uint;
#[cfg(any(
target_os = "netbsd",
target_os = "freebsd",
target_os = "dragonfly"
))]
pub type type_of_file_flag = c_ulong;
#[cfg(any(
target_os = "openbsd",
target_os = "netbsd",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "macos",
target_os = "ios"
))]
libc_bitflags! {
/// File flags.
#[cfg_attr(docsrs, doc(cfg(all())))]
pub struct FileFlag: type_of_file_flag {
/// The file may only be appended to.
SF_APPEND;
/// The file has been archived.
SF_ARCHIVED;
#[cfg(any(target_os = "dragonfly"))]
SF_CACHE;
/// The file may not be changed.
SF_IMMUTABLE;
/// Indicates a WAPBL journal file.
#[cfg(any(target_os = "netbsd"))]
SF_LOG;
/// Do not retain history for file
#[cfg(any(target_os = "dragonfly"))]
SF_NOHISTORY;
/// The file may not be renamed or deleted.
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
SF_NOUNLINK;
/// Mask of superuser changeable flags
SF_SETTABLE;
/// Snapshot is invalid.
#[cfg(any(target_os = "netbsd"))]
SF_SNAPINVAL;
/// The file is a snapshot file.
#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
SF_SNAPSHOT;
#[cfg(any(target_os = "dragonfly"))]
SF_XLINK;
/// The file may only be appended to.
UF_APPEND;
/// The file needs to be archived.
#[cfg(any(target_os = "freebsd"))]
UF_ARCHIVE;
#[cfg(any(target_os = "dragonfly"))]
UF_CACHE;
/// File is compressed at the file system level.
#[cfg(any(target_os = "macos", target_os = "ios"))]
UF_COMPRESSED;
/// The file may be hidden from directory listings at the application's
/// discretion.
#[cfg(any(
target_os = "freebsd",
target_os = "macos",
target_os = "ios",
))]
UF_HIDDEN;
/// The file may not be changed.
UF_IMMUTABLE;
/// Do not dump the file.
UF_NODUMP;
#[cfg(any(target_os = "dragonfly"))]
UF_NOHISTORY;
/// The file may not be renamed or deleted.
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
UF_NOUNLINK;
/// The file is offline, or has the Windows and CIFS
/// `FILE_ATTRIBUTE_OFFLINE` attribute.
#[cfg(any(target_os = "freebsd"))]
UF_OFFLINE;
/// The directory is opaque when viewed through a union stack.
UF_OPAQUE;
/// The file is read only, and may not be written or appended.
#[cfg(any(target_os = "freebsd"))]
UF_READONLY;
/// The file contains a Windows reparse point.
#[cfg(any(target_os = "freebsd"))]
UF_REPARSE;
/// Mask of owner changeable flags.
UF_SETTABLE;
/// The file has the Windows `FILE_ATTRIBUTE_SPARSE_FILE` attribute.
#[cfg(any(target_os = "freebsd"))]
UF_SPARSE;
/// The file has the DOS, Windows and CIFS `FILE_ATTRIBUTE_SYSTEM`
/// attribute.
#[cfg(any(target_os = "freebsd"))]
UF_SYSTEM;
/// File renames and deletes are tracked.
#[cfg(any(target_os = "macos", target_os = "ios"))]
UF_TRACKED;
#[cfg(any(target_os = "dragonfly"))]
UF_XLINK;
}
}
/// Create a special or ordinary file, by pathname.
pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
let res = path.with_nix_path(|cstr| unsafe {

View File

@ -6,6 +6,18 @@ use crate::errno::{self, Errno};
use crate::fcntl::{at_rawfd, AtFlags};
#[cfg(feature = "fs")]
use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag};
#[cfg(all(
feature = "fs",
any(
target_os = "openbsd",
target_os = "netbsd",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "macos",
target_os = "ios"
)
))]
use crate::sys::stat::FileFlag;
#[cfg(feature = "fs")]
use crate::sys::stat::Mode;
use crate::{Error, NixPath, Result};
@ -3288,3 +3300,26 @@ pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
}
}
feature! {
#![all(feature = "fs")]
/// Set the file flags.
///
/// See also [chflags(2)](https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2)
#[cfg(any(
target_os = "openbsd",
target_os = "netbsd",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "macos",
target_os = "ios"
))]
pub fn chflags<P: ?Sized + NixPath>(path: &P, flags: FileFlag) -> Result<()> {
let res = path.with_nix_path(|cstr| unsafe {
libc::chflags(cstr.as_ptr(), flags.bits())
})?;
Errno::result(res).map(drop)
}
}

View File

@ -29,6 +29,7 @@ mod test_signalfd;
mod test_socket;
#[cfg(not(any(target_os = "redox")))]
mod test_sockopt;
mod test_stat;
#[cfg(any(target_os = "android", target_os = "linux"))]
mod test_sysinfo;
#[cfg(not(any(

27
test/sys/test_stat.rs Normal file
View File

@ -0,0 +1,27 @@
#[cfg(target_os = "freebsd")]
#[test]
fn test_chflags() {
use nix::{
sys::stat::{fstat, FileFlag},
unistd::chflags,
};
use std::os::unix::io::AsRawFd;
use tempfile::NamedTempFile;
let f = NamedTempFile::new().unwrap();
let initial = FileFlag::from_bits_truncate(
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
);
// UF_OFFLINE is preserved by all FreeBSD file systems, but not interpreted
// in any way, so it's handy for testing.
let commanded = initial ^ FileFlag::UF_OFFLINE;
chflags(f.path(), commanded).unwrap();
let changed = FileFlag::from_bits_truncate(
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
);
assert_eq!(commanded, changed);
}