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::collections::HashSet;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use std::fs::Metadata;
|
||||||
use std::io::{stderr, ErrorKind, Result, Write};
|
use std::io::{stderr, ErrorKind, Result, Write};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
|
@ -92,7 +94,7 @@ struct Stat {
|
||||||
size: u64,
|
size: u64,
|
||||||
blocks: u64,
|
blocks: u64,
|
||||||
inode: Option<FileInfo>,
|
inode: Option<FileInfo>,
|
||||||
created: u64,
|
created: Option<u64>,
|
||||||
accessed: u64,
|
accessed: u64,
|
||||||
modified: u64,
|
modified: u64,
|
||||||
}
|
}
|
||||||
|
@ -113,7 +115,7 @@ impl Stat {
|
||||||
size: metadata.len(),
|
size: metadata.len(),
|
||||||
blocks: metadata.blocks() as u64,
|
blocks: metadata.blocks() as u64,
|
||||||
inode: Some(file_info),
|
inode: Some(file_info),
|
||||||
created: metadata.mtime() as u64,
|
created: birth_u64(&metadata),
|
||||||
accessed: metadata.atime() as u64,
|
accessed: metadata.atime() as u64,
|
||||||
modified: metadata.mtime() as u64,
|
modified: metadata.mtime() as u64,
|
||||||
});
|
});
|
||||||
|
@ -129,7 +131,7 @@ impl Stat {
|
||||||
size: metadata.len(),
|
size: metadata.len(),
|
||||||
blocks: size_on_disk / 1024 * 2,
|
blocks: size_on_disk / 1024 * 2,
|
||||||
inode: file_info,
|
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()),
|
accessed: windows_time_to_unix_time(metadata.last_access_time()),
|
||||||
modified: windows_time_to_unix_time(metadata.last_write_time()),
|
modified: windows_time_to_unix_time(metadata.last_write_time()),
|
||||||
})
|
})
|
||||||
|
@ -137,10 +139,24 @@ impl Stat {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[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)."
|
// "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 {
|
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)]
|
#[cfg(windows)]
|
||||||
|
@ -539,10 +555,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
.value_name("WORD")
|
.value_name("WORD")
|
||||||
.require_equals(true)
|
.require_equals(true)
|
||||||
.min_values(0)
|
.min_values(0)
|
||||||
|
.possible_values(&["atime", "access", "use", "ctime", "status", "birth", "creation"])
|
||||||
.help(
|
.help(
|
||||||
"show time of the last modification of any file in the \
|
"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 \
|
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(
|
.arg(
|
||||||
|
@ -667,19 +684,22 @@ Try '{} --help' for more information.",
|
||||||
let secs = {
|
let secs = {
|
||||||
match matches.value_of(options::TIME) {
|
match matches.value_of(options::TIME) {
|
||||||
Some(s) => match s {
|
Some(s) => match s {
|
||||||
"accessed" => stat.accessed,
|
"ctime" | "status" => stat.modified,
|
||||||
"created" => stat.created,
|
"access" | "atime" | "use" => stat.accessed,
|
||||||
"modified" => stat.modified,
|
"birth" | "creation" => {
|
||||||
_ => {
|
if let Some(time) = stat.created {
|
||||||
show_error!(
|
time
|
||||||
"invalid argument 'modified' for '--time'
|
} else {
|
||||||
Valid arguments are:
|
show_error!(
|
||||||
- 'accessed', 'created', 'modified'
|
"Invalid argument ‘{}‘ for --time.
|
||||||
Try '{} --help' for more information.",
|
‘birth‘ and ‘creation‘ arguments are not supported on this platform.",
|
||||||
NAME
|
s
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// below should never happen as clap already restricts the values.
|
||||||
|
_ => unreachable!("Invalid field for --time"),
|
||||||
},
|
},
|
||||||
None => stat.modified,
|
None => stat.modified,
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,18 +240,37 @@ fn test_du_time() {
|
||||||
scene
|
scene
|
||||||
.ccmd("touch")
|
.ccmd("touch")
|
||||||
.arg("-a")
|
.arg("-a")
|
||||||
.arg("-m")
|
|
||||||
.arg("-t")
|
.arg("-t")
|
||||||
.arg("201505150000")
|
.arg("201505150000")
|
||||||
.arg("date_test")
|
.arg("date_test")
|
||||||
.succeeds();
|
.succeeds();
|
||||||
|
|
||||||
scene
|
scene
|
||||||
.ucmd()
|
.ccmd("touch")
|
||||||
.arg("--time")
|
.arg("-m")
|
||||||
|
.arg("-t")
|
||||||
|
.arg("201606160000")
|
||||||
.arg("date_test")
|
.arg("date_test")
|
||||||
.succeeds()
|
.succeeds();
|
||||||
.stdout_only("0\t2015-05-15 00:00\tdate_test\n");
|
|
||||||
|
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"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue