GithubHelp home page GithubHelp logo

filetime's Introduction

filetime

Documentation

A helper library for inspecting and setting the various timestamps of files in Rust. This library takes into account cross-platform differences in terms of where the timestamps are located, what they are called, and how to convert them into a platform-independent representation.

# Cargo.toml
[dependencies]
filetime = "0.2"

Advantages over using std::fs::Metadata

This library includes the ability to set this data, which std does not.

This library, when built with RUSTFLAGS=--cfg emulate_second_only_system set, will return all times rounded down to the second. This emulates the behavior of some file systems, mostly HFS, allowing debugging on other hardware.

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Filetime by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

filetime's People

Contributors

4ldo2 avatar alexcrichton avatar antonok-edm avatar bgermann avatar bzeq avatar dependabot-preview[bot] avatar eh2406 avatar fogti avatar frnky avatar griff avatar ids1024 avatar jackpot51 avatar jtracey avatar link2xt avatar mark4o avatar mathstuf avatar messense avatar mpizenberg avatar nickelc avatar nielx avatar ortham avatar pfmooney avatar plauche avatar protocall7 avatar rbtcollins avatar semarie avatar silwol avatar tomaka avatar wesleywiser avatar xzfc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

filetime's Issues

Accuracy of setting times only to microsecond, not nanosecond (unix)

I don't know if this really matters for much, but utimes only allows microsecond precision. The newer utimensat function would allow nanosecond precision; it's part of the latest Posix standard, but I don't know how widely available it is (or what the best method is to use it only where available, if it isn't essentially universal).

filetime 0.1.14 issue on Solaris

I have tried to build Cargo 0.23 with filetime 0.1.14 (since the default version 0.1.12 expects lutimes() which is not available on Solaris). But I'm still getting following error (on Solaris). Note that with version 0.1.10 builds.

error[E0425]: cannot find value utimensat in module libc
--> /scratch/userland-rust-s11.3/components/rust/cargo/build/.cargo/registry/src/github.com-eae4ba8cbf2ce1c7/filetime-0.1.14/src/unix/utimensat.rs:8:45
|
8 | super::utimensat(p, atime, mtime, libc::utimensat, 0)
| ^^^^^^^^^ did you mean utimes?
|
help: possible candidate is found in another module, you can import it into scope
|
1 | use imp::utimensat;
|

error[E0425]: cannot find value utimensat in module libc
--> /scratch/userland-rust-s11.3/components/rust/cargo/build/.cargo/registry/src/github.com-eae4ba8cbf2ce1c7/filetime-0.1.14/src/unix/utimensat.rs:12:45
|
12 | super::utimensat(p, atime, mtime, libc::utimensat, libc::AT_SYMLINK_NOFOLLOW)
| ^^^^^^^^^ did you mean utimes?
|
help: possible candidate is found in another module, you can import it into scope
|
1 | use imp::utimensat;
|

error[E0425]: cannot find value AT_SYMLINK_NOFOLLOW in module libc
--> /scratch/userland-rust-s11.3/components/rust/cargo/build/.cargo/registry/src/github.com-eae4ba8cbf2ce1c7/filetime-0.1.14/src/unix/utimensat.rs:12:62
|
12 | super::utimensat(p, atime, mtime, libc::utimensat, libc::AT_SYMLINK_NOFOLLOW)
| ^^^^^^^^^^^^^^^^^^^ not found in libc

error[E0425]: cannot find value AT_FDCWD in module libc
--> /scratch/userland-rust-s11.3/components/rust/cargo/build/.cargo/registry/src/github.com-eae4ba8cbf2ce1c7/filetime-0.1.14/src/unix/mod.rs:64:17
|
64 | f(libc::AT_FDCWD, p.as_ptr() as *const _, times.as_ptr(), flags)
| ^^^^^^^^ not found in libc

error: aborting due to 4 previous errors

--

Any idea what could be possibly wrong?

Parsing fails due to new "Edition" field

Hello,

Looks like the following commit prevents us from compiling cargo-watch on stable, since it adds a new field, that cannot be parsed on stable.

38857bb

Here's a screenshot.

image

Any suggestions on how to fix this issue without us having to go over to nightly?

libc::lutimes is not defined when building with --target=wasm32-unknown-emscripten

I'm building a wasm project that depends on filetime and it looks like libc::lutimes is not defined for wasm32-unknown-emscripten targets.

Build log:

$ cargo web build --target=wasm32-unknown-emscripten
   Compiling filetime v0.1.15
error[E0425]: cannot find value `lutimes` in module `libc`
  --> /home/justas/.cargo/registry/src/github.com-1ecc6299db9ec823/filetime-0.1.15/src/unix/utimes.rs:12:42
   |
12 |     super::utimes(p, atime, mtime, libc::lutimes)
   |                                          ^^^^^^^ did you mean `utimes`?
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.
error: Could not compile `filetime`.
error: build failed

This might just be an issue with libc so feel free to close it and I'll reopen it in the libc repo.

docs: "portable" values are always in UTC, right?

When I was hacking up some code to print the actual date/time for a timestamp reported by this library, I was briefly flummoxed when it didn't match the results I saw from ls.

Then I eventually realized that ls was giving me times in my current locale, while this library always produces times relative to UTC.

This is unsurprising; this crate is after all just a thin veneer over utimes (at least on Unix), so the time zone handling is just going to be inherited from whatever the implementation of utimes does.

But: maybe the docs should explicitly note this, at least for fn seconds_relative_to_1970 and fn from_seconds_since_1970.

Just adding "(UTC)" to the description of the epoch would suffice, probably.

  • Looking at the docs now, it doesn't even say "00:00:00" (aka midnight); it just says January 1, 1970. Heh.
  • So maybe the full string "(more specifically, the Epoch: 1970-01-01 00:00:00 +0000 (UTC))" should be written after the occurrences of "January 1, 1970" in the docs.

#![feature(metadata_ext)] unstable

This project is used in iron/staticfile,
but wasn't able to compile the examples sucessfully.

git clone https://github.com/iron/staticfile
cargo run --release --example router
filetime-0.1.2/src/lib.rs:1 #![feature(metadata_ext)]
                                                                                                                ^~~~~~~~~~~~~~~~~~~~~~~~~

$rustc -V
rustc 1.1.0-beta (cd7d89af9 2015-05-16) (built 2015-05-16)

ARM build fails on stable 1.5

Using stable rust 1.5 it's the usual:

Compiling filetime v0.1.8
/home/odroid/.cargo-1.5/registry/src/github.com-48ad6e4054423464/filetime-0.1.8/src/lib.rs:222:19: 222:29 error: mismatched types:
 expected `*const u8`,
    found `*const i8`
(expected u8,
    found i8) [E0308]
/home/odroid/.cargo-1.5/registry/src/github.com-48ad6e4054423464/filetime-0.1.8/src/lib.rs:222         if utimes(p.as_ptr(), times.as_ptr()) == 0 {
                                                                                                                 ^~~~~~~~~~
/home/odroid/.cargo-1.5/registry/src/github.com-48ad6e4054423464/filetime-0.1.8/src/lib.rs:222:19: 222

Windows ctime should be set to `mtime` if `mtime < ctime`

The code passes null pointer for the creation time, so it is not changed. (see documentation of SetFileTime)

filetime/src/windows.rs

Lines 34 to 54 in 1df0704

pub fn set_file_handle_times(
f: &File,
atime: Option<FileTime>,
mtime: Option<FileTime>,
) -> io::Result<()> {
let atime = atime.map(to_filetime);
let mtime = mtime.map(to_filetime);
return unsafe {
let ret = SetFileTime(
f.as_raw_handle() as HANDLE,
ptr::null(),
atime
.as_ref()
.map(|p| p as *const FILETIME)
.unwrap_or(ptr::null()),
mtime
.as_ref()
.map(|p| p as *const FILETIME)
.unwrap_or(ptr::null()),
);
if ret != 0 {

With this, it is possible to change modified time to a time earlier than the created time, which does not make sense:

//# filetime = "*"

use std::fs;
use std::io;
use std::path::Path;
use std::time::Duration;

use filetime::FileTime;

fn run() -> io::Result<()> {
    let filepath = Path::new("test.abc123");

    // create the example file if it does not exist:
    fs::write(filepath, "hello world")?;

    // query the metadata:
    let metadata = fs::metadata(filepath)?;

    let ctime = FileTime::from(metadata.created()?);
    let mtime = FileTime::from(metadata.modified()?);
    let atime = FileTime::from(metadata.accessed()?);

    println!("ctime: {}, mtime: {}, atime: {}", ctime, mtime, atime,);

    // note: as expected the created time will be the same or
    //       earlier than the last modification time:
    assert_eq!(ctime <= mtime, true);

    let new_time = FileTime::from(metadata.modified()? - Duration::from_secs(60 * 60 * 24));

    filetime::set_file_times(filepath, new_time, new_time)?;

    let metadata = fs::metadata(filepath)?;

    let ctime = FileTime::from(metadata.created()?);
    let mtime = FileTime::from(metadata.modified()?);
    let atime = FileTime::from(metadata.accessed()?);

    println!("ctime: {}, mtime: {}, atime: {}", ctime, mtime, atime,);

    // note: the modified time is now earlier than the created
    //       time, which should not be possible:
    assert_eq!(mtime < ctime, true);

    fs::remove_file(filepath)?;

    Ok(())
}

fn main() {
    run().expect("failed to execute");
}

Proposal: ability to set btime

Some OS/filesystem combos support file birth/creation times as a user-modifiable attribute. Windows and macOS, at least, are in this boat, and possibly also FreeBSD and NetBSD.

Although Linux added support for reading btimes with statx in 4.11, they seem to have decided that it is only for internal filesystem use, and thus should not be settable by normal means. There was a proposal to come up with a standard xattr for logical file creation time, but I haven't been able to find any info on whether that ever happened.

If this is acceptable, what should the API look like? I could just add a btime parameter to all of the set_file_times/set_file_handle_times methods, and then return an io::Error or panic for unimplemented platforms.

Support setting filetimes on open files

Hi,

I realise this is a potentially difficult thing to get right across multiple platforms, but it'd be super-nice if the filetime crate supported setting the file times on open files. In code I am writing now, I have had to wrapper up futimens() for myself because I need to be able to re-stamp an open file from time to time to fit with the semantics of what is being worked with.

I ended up with:

mod platform {
    use libc::{futimens, timespec};
    use std::fs::File;
    use std::io::{Error, Result};
    use std::os::unix::io::AsRawFd;

    pub fn set_utime_now(fh: &File) -> Result<()> {
        let fd = fh.as_raw_fd();
        let rc = unsafe { futimens(fd, 0 as *const timespec) };
        if rc == 0 {
            Ok(())
        } else {
            Err(Error::last_os_error())
        }
    }
}

While this is pretty platform-specific and quite task-specific to myself, I would love to see a function (or trait I guess) in the filetime crate which was something along the lines of fn set_file_times(&File,Option<&FileTime>)

Is there any chance of this, or should I continue to use my hack for now?

Thanks,

Daniel.

Separate setting atime and mtime for symlinks

Right now the only available function that allows you to set any type of time on a symlink is set_symlink_file_times which forces you to set both the atime and the mtime.

It would be useful to have, say, either two separate set_symlink_file_atime and set_symlink_file_mtime or making so that (like set_file_handle_times) the function set_symlink_file_times takes two Options for the atime and the mtime allowing you to set either one of those.

Is this something that is possible to add?

Can not set times before 1970

FileTime uses u64 for the seconds field, rendering it unable to represent timestamps before 1970.
I believe time_t is signed on most systems, so using an i64 would be a better match.

build broken for android

evgeniy@15inch ~/bigdisk1/projects/rust-infra/filetime $ cargo check --target=armv7-linux-androideabi --release
    Updating crates.io index
    Checking filetime v0.2.11 (/home/evgeniy/bigdisk1/projects/rust-infra/filetime)
error[E0425]: cannot find function `futimes` in crate `libc`
    --> src/unix/utimes.rs:35:29
     |
35   |     let rc = unsafe { libc::futimes(f.as_raw_fd(), times.as_ptr()) };
     |                             ^^^^^^^ help: a function with a similar name exists: `futimens`
     | 
    ::: /home/evgeniy/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.74/src/unix/linux_like/mod.rs:1324:5
     |
1324 |     pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int;
     |     ------------------------------------------------------------------ similarly named function `futimens` defined here

error[E0425]: cannot find function `lutimes` in crate `libc`
    --> src/unix/utimes.rs:102:19
     |
102  |               libc::lutimes(p.as_ptr(), times.as_ptr())
     |                     ^^^^^^^ help: a function with a similar name exists: `utimes`
     | 
    ::: /home/evgeniy/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.74/src/unix/mod.rs:1224:5
     |
1224 | /     pub fn utimes(
1225 | |         filename: *const ::c_char,
1226 | |         times: *const ::timeval,
1227 | |     ) -> ::c_int;
     | |_________________- similarly named function `utimes` defined here

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0425`.
error: could not compile `filetime`.

To learn more, run the command again with --verbose.

Creation time on Linux is None

Is this a bug? Or am I missing some configuration features?

use std::fs;
use filetime::FileTime;

fn main() {
    let metadata = fs::metadata("foo.txt").unwrap();
    let ctime = FileTime::from_creation_time(&metadata).unwrap();
    println!("{}", ctime);
}

This code panics as from_creation_time returns None.

Enables this crate to modify the file creation time on Windows.

Hi, I wrote this crate: https://crates.io/crates/filetime_creation
It extends the functionality of "filetime" to modify the file creation time on Windows.
Initially my idea was to make changes directly on "filetime" and submit a pull request for the changes to be fed back upstream. But take into account the following factors:

  • This change requires modifying the signature of the existing function, I'm not sure how this will affect SemVer.
  • Does a feature that only works on Windows affect the cross-platform nature of this crate.
  • Is it appropriate for other platforms to simply ignore the "ctime" parameter? If inappropriate, do other platforms have suitable means of modifying the file creation time.
  • Is "ctime" an appropriate name.

So I decided to implement this feature first as a standalone crate to meet my (and potentially others') needs. But in the long run I think this feature should be merged into this crate to avoid community splits.
So what do you think? Should this feature be merged into this crate or should it remain separate? If you can think of a good way to implement this functionality into this crate, I don't mind deprecating my crate and archive the corresponding repository.

Add option to create FileTime from custom date

I'd like to have an option to create a FileTime struct for a specific date. Since FileTime can only be constructed from a SystemTime instance there is no way to initialize it with a specific date (unless I miss something).

API could look like that of chrono:

FileTime::ymd(2021, 11, 18).and_hms_milli(17, 00, 12, 123);

Use utimensat on FreeBSD

Every supported version of FreeBSD includes utimensat(2). Filetimes should use that instead of utimes, to get nanosecond precision.

error: unresolved import `std::os::macos::fs::MetadataExt`. Could not find `macos` in `std::os

Hello!
I'm trying Iron Framework and have such error during compiling it's https://github.com/iron/staticfile.git middleware. There is filetime 0.1.2 dependence and as I see, main reason is in this library.

Os: Mac Os X 10.10.3

Error log from cargo:

/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/filetime-0.1.2/src/lib.rs:83:29: 83:57 error: unresolved import std::os::macos::fs::MetadataExt. Could not find macos in std::os
/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/filetime-0.1.2/src/lib.rs:83 use std::os::$i::fs::MetadataExt;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/filetime-0.1.2/src/lib.rs:77:9: 96:10 note: in expansion of birthtim!
/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/filetime-0.1.2/src/lib.rs:98:9: 104:10 note: expansion site
error: aborting due to previous error

Thank you!

Was migration to 2018 edition a backwards breaking change needing 0.3 release?

In the commit 38857bb project is migrated to Rust 2018 edition.

This causes breakage for projects using older Rust, for example rouille with Rust 1.24.1:

error: non-ident macro paths are experimental (see issue #35896)
  --> /Users/oherrala/.cargo/registry/src/github.com-1ecc6299db9ec823/filetime-0.2.6/src/lib.rs:43:1
   |
43 | cfg_if::cfg_if! {
   | ^^^^^^^^^^^^^^

error: aborting due to previous error

I know this is semver 0.x.y version, but I think this breakage would be avoided by releasing this change as 0.3.0 and keeping 0.2 as is.

Build failure on OpenBSD 6.4 due to missing libc::lutimes

Hi, I was trying to build https://github.com/jwilm/alacritty on OpenBSD 6.4-current and I've ran into the failure bellow.

It seems related to the latest version of https://github.com/rust-lang/libc (v2.4.3) and triggered by db5cc8d . If I try to take out this commit out of filetime then it builds correctly. But I'm quite new to Rust so I can't say what is the best course of action.

Build failure on HEAD:

user ~/ALACRITTY/filetime $ sysctl kern.version
kern.version=OpenBSD 6.4-current (GENERIC.MP) #433: Sun Nov 11 10:08:54 MST 2018
    [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP

user ~/ALACRITTY/filetime $ rustc -Vv
rustc 1.30.1
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-openbsd
release: 1.30.1
LLVM version: 6.0

user ~/ALACRITTY/filetime $ cargo test
    Updating crates.io index
 Downloading tempdir v0.3.7
   Compiling libc v0.2.43
   Compiling cfg-if v0.1.6
   Compiling remove_dir_all v0.5.1
   Compiling rand v0.4.3
   Compiling filetime v0.2.2 (/home/user/ALACRITTY/filetime)
error[E0425]: cannot find value `lutimes` in module `libc`
  --> src/unix/utimes.rs:12:42
   |
12 |     super::utimes(p, atime, mtime, libc::lutimes)
   |                                          ^^^^^^^ did you mean `futimes`?

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.
error: Could not compile `filetime`.
warning: build failed, waiting for other jobs to finish...
error: build failed

Build successful on df8da97:

user ~/ALACRITTY/filetime $ git checkout df8da97ee26e9262246630ddca73561d823e0cc7
Note: checking out 'df8da97ee26e9262246630ddca73561d823e0cc7'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at df8da97 Bump to 0.2.2

user ~/ALACRITTY/filetime $ cargo clean

user ~/ALACRITTY/filetime $ cargo test
   Compiling libc v0.2.43
   Compiling cfg-if v0.1.6
   Compiling remove_dir_all v0.5.1
   Compiling rand v0.4.3
   Compiling filetime v0.2.2 (/home/user/ALACRITTY/filetime)
   Compiling tempdir v0.3.7
    Finished dev [unoptimized + debuginfo] target(s) in 5.69s
     Running target/debug/deps/filetime-f76c9a59801532b5

running 5 tests
test tests::from_unix_time_test ... ok
test tests::from_system_time_test ... ok
test tests::set_file_times_pre_unix_epoch_test ... ok
test tests::set_symlink_file_times_test ... ok
test tests::set_file_times_test ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests filetime

running 1 test
test src/lib.rs -  (line 17) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

user ~/ALACRITTY/filetime $ cargo build --release
   Compiling libc v0.2.43
   Compiling cfg-if v0.1.6
   Compiling filetime v0.2.2 (/home/user/ALACRITTY/filetime)
    Finished release [optimized] target(s) in 2.13s

Make `set_times` public

Hi! I have a use case1 where both the atime and mtime are optional and where following the symlink is optional. While looking through the source code of this crate, I found this function in the unix-specific part of the library, which fits my use case perfectly, but it's not public:

fn set_times(
p: &Path,
atime: Option<FileTime>,
mtime: Option<FileTime>,
symlink: bool,
) -> io::Result<()> {

Similar functions do not yet exist for the Windows and Redox implementations, but I think those could be added with relatively little effort.

If you decide to expose this, I'd recommend a name like set_path_times, mirroring the set_file_handle_times name, which is very similar in functionality. I would be happy to open a PR for this.

This would also partially fix #83, albeit not in the most elegant way.

Footnotes

  1. The touch utility of uutils, which basically acts as a wrapper around the utimensat syscall and therefore requires the same flexibility.

libc::futimens is not available on Android

This function is used here:

let rc = unsafe { libc::futimens(f.as_raw_fd(), times.as_ptr()) };

But it is not available on Android: https://stackoverflow.com/questions/19374749/how-to-work-around-absence-of-futimes-in-android-ndk

As a result, ndk-make throws an error undefined reference to 'futimens' when trying to build deltachat/deltachat-core-rust#1749 which depends on async-tar which in turn depends on filetime.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.