Skip to content
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

Enable setting file times for any writable files #105

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

BenWiederhake
Copy link

@BenWiederhake BenWiederhake commented Mar 24, 2024

This PR enables calling (f)utime(n)s(at) in a special way that was not possible before.

In particular, POSIX specifies that when times is a nullptr, then utimensat only requires that the caller has write access to the file. This cannot be emulated by any other function of this crate, as they always pass a userspace-provided times struct, which requires the caller to be the owner of the file.

This PR adds two new functions to the API: set_file_times_now(p: &Path, follow_symlink: bool) and set_file_handle_times_now(f: &fs::File).

  • On linux/utimens/utimes, it uses the appropriate (f)utime(n)s(at) variant to pull off the trick.
    • I checked each of the three variants with both Linux 4.9 and Linux 6.6.
    • I don't have a way to check that this works as intended on aix, solaris, illumos, emscripten, freebsd, netbsd, openbsd, haiku. How do I check this?
  • Android and MacOS should be posix-y enough to allow for this to work, too, but I don't feel adventurous enough to try it out. I implemented it using trivial wrappers, and included a TODO for the next person who cares to look into it.
  • Redox, android, Windows use trivial wrappers, as the feature does not apply here.
  • wasm lacks even the basic functionality, so I copy-pasted the "Wasm not implemented" error.

Fun fact: I'm trying to work on the Rust coreutils, and this feature is required to implement touch in a way that passes the touch/now-owned-by-other test.

@BenWiederhake
Copy link
Author

Changes since last push:

  • Don't test on Android and MacOS (obviously the times=nullptr thing won't work there because I didn't implement it!)
  • Run cargo fmt

@BenWiederhake BenWiederhake marked this pull request as draft March 24, 2024 23:21
@BenWiederhake
Copy link
Author

I ignored AT_SYMLINK_NOFOLLOW – turns out, that was a bad idea.

I'll change a few lines, but the bulk will remain identical.

@BenWiederhake BenWiederhake marked this pull request as ready for review March 25, 2024 22:02
I verified that this works on Linux 4.9 and Linux 6.6.
This is a POSIX-feature according to
https://pubs.opengroup.org/onlinepubs/9699919799/

By changing mod.rs, I verified that this works on Linux 4.9 and Linux 6.6.
This is a POSIX-feature according to
https://pubs.opengroup.org/onlinepubs/9699919799/

By changing mod.rs, I verified that this works on Linux 4.9 and Linux 6.6.
@BenWiederhake
Copy link
Author

Changes since initial version:

  • Added the parameter follow_symlink: bool
  • Re-ran all tests on Linux 4.9 and Linux 6.6
  • Fixed a rustfmt issue
  • Fixed a typo in the documentation

@BenWiederhake
Copy link
Author

@alexcrichton Hi! Can I ask you to look into this, and perhaps merge it? This feature would be really useful.

@@ -486,6 +517,62 @@ mod tests {
Ok(())
}

#[test]
#[cfg(unix)]
// TODO: Do Android and MacOS implement this feature of utimensat?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I guess it's safest to implement it just the way that this PR already does: Defer to the non-NULL variant, and improve it in a later PR if/when more is known about what Darwin accepts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants