Skip to content

Commit 153e09d

Browse files
saidsay-soasomers
authored andcommitted
Add chflags
1 parent caebe66 commit 153e09d

File tree

5 files changed

+174
-7
lines changed

5 files changed

+174
-7
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+
(#[1757](https://github.com/nix-rust/nix/pull/1757))
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: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22
33
use crate::errno::{self, Errno};
44
#[cfg(not(target_os = "redox"))]
5-
#[cfg(feature = "fs")]
6-
use crate::fcntl::{at_rawfd, AtFlags};
7-
#[cfg(feature = "fs")]
8-
use crate::fcntl::{fcntl, FcntlArg::F_SETFD, FdFlag, OFlag};
9-
#[cfg(feature = "fs")]
10-
use crate::sys::stat::Mode;
5+
use crate::{
6+
fcntl::{at_rawfd, AtFlags, fcntl, FcntlArg::F_SETFD, FdFlag, OFlag},
7+
sys::stat::{FileFlag, Mode}
8+
};
119
use crate::{Error, NixPath, Result};
1210
#[cfg(not(target_os = "redox"))]
1311
use cfg_if::cfg_if;
@@ -3275,3 +3273,26 @@ pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
32753273
Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
32763274
}
32773275
}
3276+
3277+
feature! {
3278+
#![all(feature = "fs")]
3279+
3280+
/// Set the file flags.
3281+
///
3282+
/// See also [chflags(2)](https://www.freebsd.org/cgi/man.cgi?query=chflags&sektion=2)
3283+
#[cfg(any(
3284+
target_os = "openbsd",
3285+
target_os = "netbsd",
3286+
target_os = "freebsd",
3287+
target_os = "dragonfly",
3288+
target_os = "macos",
3289+
target_os = "ios"
3290+
))]
3291+
pub fn chflags<P: ?Sized + NixPath>(path: &P, flags: FileFlag) -> Result<()> {
3292+
let res = path.with_nix_path(|cstr| unsafe {
3293+
libc::chflags(cstr.as_ptr(), flags.bits())
3294+
})?;
3295+
3296+
Errno::result(res).map(drop)
3297+
}
3298+
}

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

0 commit comments

Comments
 (0)