Proposal
Problem statement
I need to set file attributes on Windows, and I found it's exactly what std::fs::set_permissions does. However, struct std::fs::Permissions only exposes attribute readonly. I would also need to set other attributes, such as FILE_ATTRIBUTE_SYSTEM or FILE_ATTRIBUTE_TEMPORARY.
On Linux, there is extension trait std::os::unix::fs::PermissionsExt, but it seems Windows has no such thing.
The attributes given to OpenOptions are only applied to existing files if the files are open with .create(true).truncate(true), which truncates the files. I need to get and set the attributes of an existing file, without changing its contents.
Solution sketch
An extension trait could be added on Windows to expose other attributes. This trait could also provide methods to convert Permissions from and to u32.
In std::sys::pal::windows::fs, extend impl FilePermissions:
impl FilePermissions {
pub fn readonly(&self) -> bool {
self.attrs & c::FILE_ATTRIBUTE_READONLY != 0
}
pub fn set_readonly(&mut self, readonly: bool) {
if readonly {
self.attrs |= c::FILE_ATTRIBUTE_READONLY;
} else {
self.attrs &= !c::FILE_ATTRIBUTE_READONLY;
}
}
pub fn system(&self) -> bool {
self.attrs & c::FILE_ATTRIBUTE_SYSTEM != 0
}
pub fn set_system(&mut self, system: bool) {
if readonly {
self.attrs |= c::FILE_ATTRIBUTE_SYSTEM;
} else {
self.attrs &= !c::FILE_ATTRIBUTE_SYSTEM;
}
}
// ...
// A macro could be used since all the functions will have the same structure
pub fn to_u32(&self) -> u32 {
self.attrs
}
fn from_u32(mask: u32) -> Self {
// You may want to check the mask is correct and return an `Option` here, although `SetFileAttributes` seems to ignore invalid attributes.
Self { attrs: mask }
}
}
In std::os::windows::fs:
pub trait PermissionsExt {
#[must_use]
fn system(&self) -> bool;
fn set_system(&mut self);
#[must_use]
fn temporary(&self) -> bool;
fn set_temporary(&mut self);
// Same for other attributes
fn to_u32(&self) -> u32;
fn from_u32(mask: u32) -> Self;
}
impl PermissionsExt for Permissions {
// Delegates all to `as_inner` or `from_inner`, just like `PermissionsExt` is implemented on Unix.
}
Alternatives
Currently, I'm calling system API SetFileAttributesW directly, but this forces me to resort to unsafe code and to re-implement conversion from Path to Vec<u16> (with verbatim support for long paths), in a way that's probably less efficient than the standard library.
Another possibility would be to compute the mask manually and to transmute the result to Permissions (which is basically a u32), but I don't like this solution because there is no guarantee that Permissions will remain equivalent to a u32 in the future.
Links and related work
Initial discussion:
https://internals.rust-lang.org/t/extend-std-permissions-on-windows/20943
Proposal
Problem statement
I need to set file attributes on Windows, and I found it's exactly what
std::fs::set_permissionsdoes. However, structstd::fs::Permissionsonly exposes attributereadonly. I would also need to set other attributes, such asFILE_ATTRIBUTE_SYSTEMorFILE_ATTRIBUTE_TEMPORARY.On Linux, there is extension trait
std::os::unix::fs::PermissionsExt, but it seems Windows has no such thing.The attributes given to
OpenOptionsare only applied to existing files if the files are open with.create(true).truncate(true), which truncates the files. I need to get and set the attributes of an existing file, without changing its contents.Solution sketch
An extension trait could be added on Windows to expose other attributes. This trait could also provide methods to convert
Permissionsfrom and tou32.In
std::sys::pal::windows::fs, extendimpl FilePermissions:In
std::os::windows::fs:Alternatives
Currently, I'm calling system API
SetFileAttributesWdirectly, but this forces me to resort to unsafe code and to re-implement conversion fromPathtoVec<u16>(with verbatim support for long paths), in a way that's probably less efficient than the standard library.Another possibility would be to compute the mask manually and to transmute the result to Permissions (which is basically a u32), but I don't like this solution because there is no guarantee that Permissions will remain equivalent to a u32 in the future.
Links and related work
Initial discussion:
https://internals.rust-lang.org/t/extend-std-permissions-on-windows/20943