Skip to content

Commit 56f6eb5

Browse files
committed
add support for chmod/fchmod/fchmodat
1 parent f378c74 commit 56f6eb5

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

src/sys/stat.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,35 @@ pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: AtFlags) -> R
147147
Ok(dst)
148148
}
149149

150+
/// Change permissions of a file
151+
/// ([see chmod(2)](http://man7.org/linux/man-pages/man2/chmod.2.html)).
152+
pub fn chmod<P: ?Sized + NixPath>(pathname: &P, mode: Mode) -> Result<()> {
153+
let res = try!(pathname.with_nix_path(|cstr| {
154+
unsafe { libc::chmod(cstr.as_ptr(), mode.bits()) }
155+
}));
156+
157+
Errno::result(res).map(drop)
158+
}
159+
160+
/// Change permissions of a file
161+
/// ([see fchmod(2)](http://man7.org/linux/man-pages/man2/fchmod.2.html)).
162+
pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
163+
let res = unsafe { libc::fchmod(fd, mode.bits()) };
164+
165+
Errno::result(res).map(drop)
166+
}
167+
168+
/// Change permissions of a file
169+
/// ([see fchmodat(2)](http://man7.org/linux/man-pages/man2/fchmodat.2.html)).
170+
pub fn fchmodat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, mode: Mode, flags: AtFlags) -> Result<()> {
171+
let res = try!(pathname.with_nix_path(|cstr| {
172+
unsafe {
173+
libc::fchmodat(dirfd,
174+
cstr.as_ptr(),
175+
mode.bits(),
176+
flags.bits())
177+
}
178+
}));
179+
180+
Errno::result(res).map(drop)
181+
}

test/test_stat.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use std::fs::File;
2-
use std::os::unix::fs::symlink;
2+
use std::os::unix::fs::{symlink, PermissionsExt};
33
use std::os::unix::prelude::AsRawFd;
4+
use tempfile::NamedTempFile;
45

56
use libc::{S_IFMT, S_IFLNK};
67

78
use nix::fcntl;
8-
use nix::sys::stat::{self, stat, fstat, lstat};
9-
use nix::sys::stat::FileStat;
9+
use nix::sys::stat::*;
1010
use nix::Result;
1111
use tempdir::TempDir;
1212

@@ -81,11 +81,11 @@ fn test_fstatat() {
8181
File::create(&filename).unwrap();
8282
let dirfd = fcntl::open(tempdir.path(),
8383
fcntl::OFlag::empty(),
84-
stat::Mode::empty());
84+
Mode::empty());
8585

86-
let result = stat::fstatat(dirfd.unwrap(),
87-
&filename,
88-
fcntl::AtFlags::empty());
86+
let result = fstatat(dirfd.unwrap(),
87+
&filename,
88+
fcntl::AtFlags::empty());
8989
assert_stat_results(result);
9090
}
9191

@@ -110,3 +110,30 @@ fn test_stat_fstat_lstat() {
110110
let fstat_result = fstat(link.as_raw_fd());
111111
assert_stat_results(fstat_result);
112112
}
113+
114+
fn assert_mode(f: &NamedTempFile, mode: u32) {
115+
assert_eq!(f.metadata().unwrap().permissions().mode(),
116+
mode);
117+
}
118+
119+
#[test]
120+
fn test_chmod() {
121+
let tempfile = NamedTempFile::new().unwrap();
122+
chmod(tempfile.path(),
123+
Mode::from_bits(0o755).unwrap()).unwrap();
124+
assert_mode(&tempfile, 0o755);
125+
126+
fchmod(tempfile.as_raw_fd(),
127+
Mode::from_bits(0o644).unwrap()).unwrap();
128+
assert_mode(&tempfile, 0o644);
129+
130+
let parent_dir = tempfile.path().parent().unwrap();
131+
let dirfd = fcntl::open(parent_dir,
132+
fcntl::OFlag::empty(),
133+
Mode::empty()).unwrap();
134+
fchmodat(dirfd,
135+
tempfile.path().file_name().unwrap(),
136+
Mode::from_bits(0o600).unwrap(),
137+
fcntl::AtFlags::empty()).unwrap();
138+
assert_mode(&tempfile, 0o600);
139+
}

0 commit comments

Comments
 (0)