mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
Merge pull request #2288 from syukronrm/du-time
du: fix `--time` behavior
This commit is contained in:
commit
963a0da0b4
2 changed files with 62 additions and 23 deletions
|
@ -14,6 +14,8 @@ use clap::{App, Arg};
|
|||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
#[cfg(not(windows))]
|
||||
use std::fs::Metadata;
|
||||
use std::io::{stderr, ErrorKind, Result, Write};
|
||||
use std::iter;
|
||||
#[cfg(not(windows))]
|
||||
|
@ -92,7 +94,7 @@ struct Stat {
|
|||
size: u64,
|
||||
blocks: u64,
|
||||
inode: Option<FileInfo>,
|
||||
created: u64,
|
||||
created: Option<u64>,
|
||||
accessed: u64,
|
||||
modified: u64,
|
||||
}
|
||||
|
@ -113,7 +115,7 @@ impl Stat {
|
|||
size: metadata.len(),
|
||||
blocks: metadata.blocks() as u64,
|
||||
inode: Some(file_info),
|
||||
created: metadata.mtime() as u64,
|
||||
created: birth_u64(&metadata),
|
||||
accessed: metadata.atime() as u64,
|
||||
modified: metadata.mtime() as u64,
|
||||
});
|
||||
|
@ -129,7 +131,7 @@ impl Stat {
|
|||
size: metadata.len(),
|
||||
blocks: size_on_disk / 1024 * 2,
|
||||
inode: file_info,
|
||||
created: windows_time_to_unix_time(metadata.creation_time()),
|
||||
created: windows_creation_time_to_unix_time(metadata.creation_time()),
|
||||
accessed: windows_time_to_unix_time(metadata.last_access_time()),
|
||||
modified: windows_time_to_unix_time(metadata.last_write_time()),
|
||||
})
|
||||
|
@ -137,10 +139,24 @@ impl Stat {
|
|||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
// https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html#tymethod.creation_time
|
||||
// https://doc.rust-lang.org/std/os/windows/fs/trait.MetadataExt.html#tymethod.last_access_time
|
||||
// "The returned 64-bit value [...] which represents the number of 100-nanosecond intervals since January 1, 1601 (UTC)."
|
||||
// "If the underlying filesystem does not support last access time, the returned value is 0."
|
||||
fn windows_time_to_unix_time(win_time: u64) -> u64 {
|
||||
win_time / 10_000_000 - 11_644_473_600
|
||||
(win_time / 10_000_000).saturating_sub(11_644_473_600)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn windows_creation_time_to_unix_time(win_time: u64) -> Option<u64> {
|
||||
(win_time / 10_000_000).checked_sub(11_644_473_600)
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn birth_u64(meta: &Metadata) -> Option<u64> {
|
||||
meta.created()
|
||||
.ok()
|
||||
.and_then(|t| t.duration_since(UNIX_EPOCH).ok())
|
||||
.map(|e| e.as_secs() as u64)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
@ -539,10 +555,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.value_name("WORD")
|
||||
.require_equals(true)
|
||||
.min_values(0)
|
||||
.possible_values(&["atime", "access", "use", "ctime", "status", "birth", "creation"])
|
||||
.help(
|
||||
"show time of the last modification of any file in the \
|
||||
directory, or any of its subdirectories. If WORD is given, show time as WORD instead \
|
||||
of modification time: atime, access, use, ctime or status"
|
||||
of modification time: atime, access, use, ctime, status, birth or creation"
|
||||
)
|
||||
)
|
||||
.arg(
|
||||
|
@ -667,19 +684,22 @@ Try '{} --help' for more information.",
|
|||
let secs = {
|
||||
match matches.value_of(options::TIME) {
|
||||
Some(s) => match s {
|
||||
"accessed" => stat.accessed,
|
||||
"created" => stat.created,
|
||||
"modified" => stat.modified,
|
||||
_ => {
|
||||
show_error!(
|
||||
"invalid argument 'modified' for '--time'
|
||||
Valid arguments are:
|
||||
- 'accessed', 'created', 'modified'
|
||||
Try '{} --help' for more information.",
|
||||
NAME
|
||||
);
|
||||
return 1;
|
||||
"ctime" | "status" => stat.modified,
|
||||
"access" | "atime" | "use" => stat.accessed,
|
||||
"birth" | "creation" => {
|
||||
if let Some(time) = stat.created {
|
||||
time
|
||||
} else {
|
||||
show_error!(
|
||||
"Invalid argument ‘{}‘ for --time.
|
||||
‘birth‘ and ‘creation‘ arguments are not supported on this platform.",
|
||||
s
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// below should never happen as clap already restricts the values.
|
||||
_ => unreachable!("Invalid field for --time"),
|
||||
},
|
||||
None => stat.modified,
|
||||
}
|
||||
|
|
|
@ -240,18 +240,37 @@ fn test_du_time() {
|
|||
scene
|
||||
.ccmd("touch")
|
||||
.arg("-a")
|
||||
.arg("-m")
|
||||
.arg("-t")
|
||||
.arg("201505150000")
|
||||
.arg("date_test")
|
||||
.succeeds();
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--time")
|
||||
.ccmd("touch")
|
||||
.arg("-m")
|
||||
.arg("-t")
|
||||
.arg("201606160000")
|
||||
.arg("date_test")
|
||||
.succeeds()
|
||||
.stdout_only("0\t2015-05-15 00:00\tdate_test\n");
|
||||
.succeeds();
|
||||
|
||||
let result = scene.ucmd().arg("--time").arg("date_test").succeeds();
|
||||
result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");
|
||||
|
||||
let result = scene.ucmd().arg("--time=atime").arg("date_test").succeeds();
|
||||
result.stdout_only("0\t2015-05-15 00:00\tdate_test\n");
|
||||
|
||||
let result = scene.ucmd().arg("--time=ctime").arg("date_test").succeeds();
|
||||
result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");
|
||||
|
||||
#[cfg(not(target_env = "musl"))]
|
||||
{
|
||||
use regex::Regex;
|
||||
|
||||
let re_birth =
|
||||
Regex::new(r"0\t[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}\tdate_test").unwrap();
|
||||
let result = scene.ucmd().arg("--time=birth").arg("date_test").succeeds();
|
||||
result.stdout_matches(&re_birth);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue