Skip to content

Commit 6fb19d9

Browse files
saidsay-soasomers
authored andcommitted
Add chflags
1 parent caebe66 commit 6fb19d9

File tree

5 files changed

+179
-1
lines changed

5 files changed

+179
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
66
## [Unreleased] - ReleaseDate
77
### Added
88

9+
- Added `chflags`.
10+
(#[1758](https://github.com/nix-rust/nix/pull/1758))
911
- Added `aio_writev` and `aio_readv`.
1012
(#[1713](https://github.com/nix-rust/nix/pull/1713))
11-
1213
- impl `From<uid_t>` for `Uid` and `From<gid_t>` for `Gid`
1314
(#[1727](https://github.com/nix-rust/nix/pull/1727))
1415
- impl From<SockaddrIn> for std::net::SocketAddrV4 and

src/sys/stat.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
pub use libc::{dev_t, mode_t};
2+
#[cfg(any(target_os = "macos", target_os = "ios"))]
3+
pub use libc::c_uint;
4+
#[cfg(any(
5+
target_os = "openbsd",
6+
target_os = "netbsd",
7+
target_os = "freebsd",
8+
target_os = "dragonfly"
9+
))]
10+
pub use libc::c_ulong;
211
pub use libc::stat as FileStat;
312

413
use crate::{Result, NixPath, errno::Errno};
@@ -43,6 +52,111 @@ libc_bitflags! {
4352
}
4453
}
4554

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

src/unistd.rs

Lines changed: 35 additions & 0 deletions
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};
@@ -3275,3 +3287,26 @@ pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
32753287
Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
32763288
}
32773289
}
3290+
3291+
feature! {
3292+
#![all(feature = "fs")]
3293+
3294+
/// Set the file flags.
3295+
///
3296+
/// See also [chflags(2)](https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2)
3297+
#[cfg(any(
3298+
target_os = "openbsd",
3299+
target_os = "netbsd",
3300+
target_os = "freebsd",
3301+
target_os = "dragonfly",
3302+
target_os = "macos",
3303+
target_os = "ios"
3304+
))]
3305+
pub fn chflags<P: ?Sized + NixPath>(path: &P, flags: FileFlag) -> Result<()> {
3306+
let res = path.with_nix_path(|cstr| unsafe {
3307+
libc::chflags(cstr.as_ptr(), flags.bits())
3308+
})?;
3309+
3310+
Errno::result(res).map(drop)
3311+
}
3312+
}

test/sys/mod.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 27 additions & 0 deletions
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)