Skip to content

Commit e5f354c

Browse files
Merge #1758
1758: Add chflags r=rtzoeller a=asomers Co-authored-by: musikid <[email protected]>
2 parents fb65331 + 137a9ab commit e5f354c

File tree

6 files changed

+178
-1
lines changed

6 files changed

+178
-1
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
1010
(#[1761](https://github.com/nix-rust/nix/pull/1761))
1111
- Added const constructors for `TimeSpec` and `TimeVal`
1212
(#[1760](https://github.com/nix-rust/nix/pull/1760))
13+
- Added `chflags`.
14+
(#[1758](https://github.com/nix-rust/nix/pull/1758))
1315
- Added `aio_writev` and `aio_readv`.
1416
(#[1713](https://github.com/nix-rust/nix/pull/1713))
1517
- impl `From<uid_t>` for `Uid` and `From<gid_t>` for `Gid`

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ targets = [
2727
]
2828

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

src/sys/stat.rs

+112
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
pub use libc::{dev_t, mode_t};
2+
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
3+
pub use libc::c_uint;
4+
#[cfg(any(
5+
target_os = "netbsd",
6+
target_os = "freebsd",
7+
target_os = "dragonfly"
8+
))]
9+
pub use libc::c_ulong;
210
pub use libc::stat as FileStat;
311

412
use crate::{Result, NixPath, errno::Errno};
@@ -43,6 +51,110 @@ libc_bitflags! {
4351
}
4452
}
4553

54+
#[cfg(any(target_os = "macos", target_os = "ios", target_os="openbsd"))]
55+
pub type type_of_file_flag = c_uint;
56+
#[cfg(any(
57+
target_os = "netbsd",
58+
target_os = "freebsd",
59+
target_os = "dragonfly"
60+
))]
61+
pub type type_of_file_flag = c_ulong;
62+
63+
#[cfg(any(
64+
target_os = "openbsd",
65+
target_os = "netbsd",
66+
target_os = "freebsd",
67+
target_os = "dragonfly",
68+
target_os = "macos",
69+
target_os = "ios"
70+
))]
71+
libc_bitflags! {
72+
/// File flags.
73+
#[cfg_attr(docsrs, doc(cfg(all())))]
74+
pub struct FileFlag: type_of_file_flag {
75+
/// The file may only be appended to.
76+
SF_APPEND;
77+
/// The file has been archived.
78+
SF_ARCHIVED;
79+
#[cfg(any(target_os = "dragonfly"))]
80+
SF_CACHE;
81+
/// The file may not be changed.
82+
SF_IMMUTABLE;
83+
/// Indicates a WAPBL journal file.
84+
#[cfg(any(target_os = "netbsd"))]
85+
SF_LOG;
86+
/// Do not retain history for file
87+
#[cfg(any(target_os = "dragonfly"))]
88+
SF_NOHISTORY;
89+
/// The file may not be renamed or deleted.
90+
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
91+
SF_NOUNLINK;
92+
/// Mask of superuser changeable flags
93+
SF_SETTABLE;
94+
/// Snapshot is invalid.
95+
#[cfg(any(target_os = "netbsd"))]
96+
SF_SNAPINVAL;
97+
/// The file is a snapshot file.
98+
#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
99+
SF_SNAPSHOT;
100+
#[cfg(any(target_os = "dragonfly"))]
101+
SF_XLINK;
102+
/// The file may only be appended to.
103+
UF_APPEND;
104+
/// The file needs to be archived.
105+
#[cfg(any(target_os = "freebsd"))]
106+
UF_ARCHIVE;
107+
#[cfg(any(target_os = "dragonfly"))]
108+
UF_CACHE;
109+
/// File is compressed at the file system level.
110+
#[cfg(any(target_os = "macos", target_os = "ios"))]
111+
UF_COMPRESSED;
112+
/// The file may be hidden from directory listings at the application's
113+
/// discretion.
114+
#[cfg(any(
115+
target_os = "freebsd",
116+
target_os = "macos",
117+
target_os = "ios",
118+
))]
119+
UF_HIDDEN;
120+
/// The file may not be changed.
121+
UF_IMMUTABLE;
122+
/// Do not dump the file.
123+
UF_NODUMP;
124+
#[cfg(any(target_os = "dragonfly"))]
125+
UF_NOHISTORY;
126+
/// The file may not be renamed or deleted.
127+
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
128+
UF_NOUNLINK;
129+
/// The file is offline, or has the Windows and CIFS
130+
/// `FILE_ATTRIBUTE_OFFLINE` attribute.
131+
#[cfg(any(target_os = "freebsd"))]
132+
UF_OFFLINE;
133+
/// The directory is opaque when viewed through a union stack.
134+
UF_OPAQUE;
135+
/// The file is read only, and may not be written or appended.
136+
#[cfg(any(target_os = "freebsd"))]
137+
UF_READONLY;
138+
/// The file contains a Windows reparse point.
139+
#[cfg(any(target_os = "freebsd"))]
140+
UF_REPARSE;
141+
/// Mask of owner changeable flags.
142+
UF_SETTABLE;
143+
/// The file has the Windows `FILE_ATTRIBUTE_SPARSE_FILE` attribute.
144+
#[cfg(any(target_os = "freebsd"))]
145+
UF_SPARSE;
146+
/// The file has the DOS, Windows and CIFS `FILE_ATTRIBUTE_SYSTEM`
147+
/// attribute.
148+
#[cfg(any(target_os = "freebsd"))]
149+
UF_SYSTEM;
150+
/// File renames and deletes are tracked.
151+
#[cfg(any(target_os = "macos", target_os = "ios"))]
152+
UF_TRACKED;
153+
#[cfg(any(target_os = "dragonfly"))]
154+
UF_XLINK;
155+
}
156+
}
157+
46158
/// Create a special or ordinary file, by pathname.
47159
pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
48160
let res = path.with_nix_path(|cstr| unsafe {

src/unistd.rs

+35
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ use crate::errno::{self, Errno};
66
use crate::fcntl::{at_rawfd, AtFlags};
77
#[cfg(feature = "fs")]
88
use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag};
9+
#[cfg(all(
10+
feature = "fs",
11+
any(
12+
target_os = "openbsd",
13+
target_os = "netbsd",
14+
target_os = "freebsd",
15+
target_os = "dragonfly",
16+
target_os = "macos",
17+
target_os = "ios"
18+
)
19+
))]
20+
use crate::sys::stat::FileFlag;
921
#[cfg(feature = "fs")]
1022
use crate::sys::stat::Mode;
1123
use crate::{Error, NixPath, Result};
@@ -3288,3 +3300,26 @@ pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
32883300
Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
32893301
}
32903302
}
3303+
3304+
feature! {
3305+
#![all(feature = "fs")]
3306+
3307+
/// Set the file flags.
3308+
///
3309+
/// See also [chflags(2)](https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2)
3310+
#[cfg(any(
3311+
target_os = "openbsd",
3312+
target_os = "netbsd",
3313+
target_os = "freebsd",
3314+
target_os = "dragonfly",
3315+
target_os = "macos",
3316+
target_os = "ios"
3317+
))]
3318+
pub fn chflags<P: ?Sized + NixPath>(path: &P, flags: FileFlag) -> Result<()> {
3319+
let res = path.with_nix_path(|cstr| unsafe {
3320+
libc::chflags(cstr.as_ptr(), flags.bits())
3321+
})?;
3322+
3323+
Errno::result(res).map(drop)
3324+
}
3325+
}

test/sys/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod test_signalfd;
2929
mod test_socket;
3030
#[cfg(not(any(target_os = "redox")))]
3131
mod test_sockopt;
32+
mod test_stat;
3233
#[cfg(any(target_os = "android", target_os = "linux"))]
3334
mod test_sysinfo;
3435
#[cfg(not(any(

test/sys/test_stat.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#[cfg(target_os = "freebsd")]
2+
#[test]
3+
fn test_chflags() {
4+
use nix::{
5+
sys::stat::{fstat, FileFlag},
6+
unistd::chflags,
7+
};
8+
use std::os::unix::io::AsRawFd;
9+
use tempfile::NamedTempFile;
10+
11+
let f = NamedTempFile::new().unwrap();
12+
13+
let initial = FileFlag::from_bits_truncate(
14+
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
15+
);
16+
// UF_OFFLINE is preserved by all FreeBSD file systems, but not interpreted
17+
// in any way, so it's handy for testing.
18+
let commanded = initial ^ FileFlag::UF_OFFLINE;
19+
20+
chflags(f.path(), commanded).unwrap();
21+
22+
let changed = FileFlag::from_bits_truncate(
23+
fstat(f.as_raw_fd()).unwrap().st_flags.into(),
24+
);
25+
26+
assert_eq!(commanded, changed);
27+
}

0 commit comments

Comments
 (0)