summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormusikid <musikid@outlook.com>2022-04-27 12:23:56 +0200
committerAlan Somers <asomers@gmail.com>2022-07-13 21:27:36 -0600
commit137a9abb666661d1546d471e61321a94ead2eca2 (patch)
tree7ce79bcd4233582a876480b8be0db1751d6b93ba
parentfb65331a559ce3a51640ef6431562eea6cd39725 (diff)
downloadnix-137a9abb666661d1546d471e61321a94ead2eca2.zip
Add chflags
-rw-r--r--CHANGELOG.md2
-rw-r--r--Cargo.toml2
-rw-r--r--src/sys/stat.rs112
-rw-r--r--src/unistd.rs35
-rw-r--r--test/sys/mod.rs1
-rw-r--r--test/sys/test_stat.rs27
6 files changed, 178 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1109818b..244455bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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`
diff --git a/Cargo.toml b/Cargo.toml
index 284b5e5e..4214b16e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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 }
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index 5cf2deb7..8b7627d5 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -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 {
diff --git a/src/unistd.rs b/src/unistd.rs
index e738349a..6dd0c164 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -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)
+}
+}
diff --git a/test/sys/mod.rs b/test/sys/mod.rs
index ed4ad736..20312120 100644
--- a/test/sys/mod.rs
+++ b/test/sys/mod.rs
@@ -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(
diff --git a/test/sys/test_stat.rs b/test/sys/test_stat.rs
new file mode 100644
index 00000000..2f26e789
--- /dev/null
+++ b/test/sys/test_stat.rs
@@ -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);
+}