Skip to content

Document surprising and dangerous fs::Permissions behaviour on Unix #101644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 24, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 64 additions & 3 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,34 @@ impl FileTimes {
impl Permissions {
/// Returns `true` if these permissions describe a readonly (unwritable) file.
///
/// # Note
///
/// This function does not take Access Control Lists (ACLs) or Unix group
/// membership into account.
///
/// # Windows
///
/// On Windows this returns [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
/// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
/// but the user may still have permission to change this flag. If
/// `FILE_ATTRIBUTE_READONLY` is *not* set then writes may still fail due
/// to lack of write permission.
/// The behavior of this attribute for directories depends on the Windows
/// version.
///
/// # Unix (including macOS)
///
/// On Unix-based platforms this checks if *any* of the owner, group or others
/// write permission bits are set. It does not check if the current
/// user is in the file's assigned group. It also does not check ACLs.
/// Therefore even if this returns true you may not be able to write to the
/// file, and vice versa. The [`PermissionsExt`] trait gives direct access
/// to the permission bits but also does not read ACLs. If you need to
/// accurately know whether or not a file is writable use the `access()`
/// function from libc.
///
/// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
///
/// # Examples
///
/// ```no_run
Expand All @@ -1390,8 +1418,40 @@ impl Permissions {
/// using the resulting `Permission` will update file permissions to allow
/// writing.
///
/// This operation does **not** modify the filesystem. To modify the
/// filesystem use the [`set_permissions`] function.
/// This operation does **not** modify the files attributes. This only
/// changes the in-memory value of these attributes for this `Permissions`
/// instance. To modify the files attributes use the [`set_permissions`]
/// function which commits these attribute changes to the file.
///
/// # Note
///
/// `set_readonly(false)` makes the file *world-writable* on Unix.
/// You can use the [`PermissionsExt`] trait on Unix to avoid this issue.
///
/// It also does not take Access Control Lists (ACLs) or Unix group
/// membership into account.
///
/// # Windows
///
/// On Windows this sets or clears [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
/// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
/// but the user may still have permission to change this flag. If
/// `FILE_ATTRIBUTE_READONLY` is *not* set then the write may still fail if
/// the user does not have permission to write to the file.
///
/// In Windows 7 and earlier this attribute prevents deleting empty
/// directories. It does not prevent modifying the directory contents.
/// On later versions of Windows this attribute is ignored for directories.
///
/// # Unix (including macOS)
///
/// On Unix-based platforms this sets or clears the write access bit for
/// the owner, group *and* others, equivalent to `chmod a+w <file>`
/// or `chmod a-w <file>` respectively. The latter will grant write access
/// to all users! You can use the [`PermissionsExt`] trait on Unix
/// to avoid this issue.
///
/// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
///
/// # Examples
///
Expand All @@ -1405,7 +1465,8 @@ impl Permissions {
///
/// permissions.set_readonly(true);
///
/// // filesystem doesn't change
/// // filesystem doesn't change, only the in memory state of the
/// // readonly permission
/// assert_eq!(false, metadata.permissions().readonly());
///
/// // just this particular `permissions`.
Expand Down