Add a method for setting permissions directly on an open file.
On unix like systems, the underlying file corresponding to any given path may change at any time. This function makes it possible to set the permissions of the a file corresponding to a `File` object even if its path changes.
This commit is contained in:
parent
0f7c75b74f
commit
1aaca5f290
@ -348,6 +348,41 @@ impl File {
|
||||
inner: self.inner.duplicate()?
|
||||
})
|
||||
}
|
||||
|
||||
/// Changes the permissions on the underlying file.
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// This function currently corresponds to the `fchmod` function on Unix and
|
||||
/// the `SetFileInformationByHandle` function on Windows. Note that, this
|
||||
/// [may change in the future][changes].
|
||||
///
|
||||
/// [changes]: ../io/index.html#platform-specific-behavior
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if the user lacks permission change
|
||||
/// attributes on the underlying file. It may also return an error in other
|
||||
/// os-specific unspecified cases.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(set_permissions_atomic)]
|
||||
/// # fn foo() -> std::io::Result<()> {
|
||||
/// use std::fs::File;
|
||||
///
|
||||
/// let file = File::open("foo.txt")?;
|
||||
/// let mut perms = file.metadata()?.permissions();
|
||||
/// perms.set_readonly(true);
|
||||
/// file.set_permissions(perms)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "set_permissions_atomic", issue="37916")]
|
||||
pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
|
||||
self.inner.set_permissions(perm.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<fs_imp::File> for File {
|
||||
@ -2469,6 +2504,24 @@ mod tests {
|
||||
check!(fs::set_permissions(&file, p));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fchmod_works() {
|
||||
let tmpdir = tmpdir();
|
||||
let path = tmpdir.join("in.txt");
|
||||
|
||||
let file = check!(File::create(&path));
|
||||
let attr = check!(fs::metadata(&path));
|
||||
assert!(!attr.permissions().readonly());
|
||||
let mut p = attr.permissions();
|
||||
p.set_readonly(true);
|
||||
check!(file.set_permissions(p.clone()));
|
||||
let attr = check!(fs::metadata(&path));
|
||||
assert!(attr.permissions().readonly());
|
||||
|
||||
p.set_readonly(false);
|
||||
check!(file.set_permissions(p));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_doesnt_kill_anything() {
|
||||
let tmpdir = tmpdir();
|
||||
|
@ -526,6 +526,11 @@ impl File {
|
||||
pub fn fd(&self) -> &FileDesc { &self.0 }
|
||||
|
||||
pub fn into_fd(self) -> FileDesc { self.0 }
|
||||
|
||||
pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
|
||||
cvt_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
|
@ -389,6 +389,15 @@ pub enum FILE_INFO_BY_HANDLE_CLASS {
|
||||
MaximumFileInfoByHandlesClass
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FILE_BASIC_INFO {
|
||||
pub CreationTime: LARGE_INTEGER,
|
||||
pub LastAccessTime: LARGE_INTEGER,
|
||||
pub LastWriteTime: LARGE_INTEGER,
|
||||
pub ChangeTime: LARGE_INTEGER,
|
||||
pub FileAttributes: DWORD,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FILE_END_OF_FILE_INFO {
|
||||
pub EndOfFile: LARGE_INTEGER,
|
||||
|
@ -417,6 +417,24 @@ impl File {
|
||||
Ok(PathBuf::from(OsString::from_wide(subst)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
|
||||
let mut info = c::FILE_BASIC_INFO {
|
||||
CreationTime: 0,
|
||||
LastAccessTime: 0,
|
||||
LastWriteTime: 0,
|
||||
ChangeTime: 0,
|
||||
FileAttributes: perm.attrs,
|
||||
};
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(unsafe {
|
||||
c::SetFileInformationByHandle(self.handle.raw(),
|
||||
c::FileBasicInfo,
|
||||
&mut info as *mut _ as *mut _,
|
||||
size as c::DWORD)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromInner<c::HANDLE> for File {
|
||||
|
Loading…
Reference in New Issue
Block a user