Skip to content

Commit 6eb75f2

Browse files
committed
stat: Stop relying on fsext::Birth
We can rely on other fsext/time functions, and stay a bit more consistent.
1 parent 9c13e3f commit 6eb75f2

File tree

5 files changed

+26
-41
lines changed

5 files changed

+26
-41
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/uu/stat/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ uucore = { workspace = true, features = [
2626
"fsext",
2727
"time",
2828
] }
29-
chrono = { workspace = true }
3029
thiserror = { workspace = true }
3130

3231
[features]

src/uu/stat/src/stat.rs

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ use clap::builder::ValueParser;
1010
use uucore::display::Quotable;
1111
use uucore::fs::display_permissions;
1212
use uucore::fsext::{
13-
BirthTime, FsMeta, MetadataTimeField, StatFs, metadata_get_time, pretty_filetype,
14-
pretty_fstype, read_fs_list, statfs,
13+
FsMeta, MetadataTimeField, StatFs, metadata_get_time, pretty_filetype, pretty_fstype,
14+
read_fs_list, statfs,
1515
};
1616
use uucore::libc::mode_t;
1717
use uucore::{entries, format_usage, show_error, show_warning};
1818

19-
use chrono::{DateTime, Local};
2019
use clap::{Arg, ArgAction, ArgMatches, Command};
2120
use std::borrow::Cow;
2221
use std::ffi::{OsStr, OsString};
@@ -29,6 +28,7 @@ use std::{env, fs};
2928
use std::collections::HashMap;
3029
use thiserror::Error;
3130
use uucore::locale::{get_message, get_message_with_args};
31+
use uucore::time::{format_system_time, system_time_to_sec};
3232

3333
#[derive(Debug, Error)]
3434
enum StatError {
@@ -1030,7 +1030,10 @@ impl Stater {
10301030
'w' => OutputType::Str(pretty_time(meta, MetadataTimeField::Birth)),
10311031

10321032
// time of file birth, seconds since Epoch; 0 if unknown
1033-
'W' => OutputType::Unsigned(meta.birth().unwrap_or_default().0),
1033+
'W' => OutputType::Integer(
1034+
metadata_get_time(meta, MetadataTimeField::Birth)
1035+
.map_or(0, |x| system_time_to_sec(x).0),
1036+
),
10341037

10351038
// time of last access, human-readable
10361039
'x' => OutputType::Str(pretty_time(meta, MetadataTimeField::Access)),
@@ -1040,21 +1043,9 @@ impl Stater {
10401043
'y' => OutputType::Str(pretty_time(meta, MetadataTimeField::Modification)),
10411044
// time of last data modification, seconds since Epoch
10421045
'Y' => {
1043-
let sec = meta.mtime();
1044-
let nsec = meta.mtime_nsec();
1045-
let tm = DateTime::from_timestamp(sec, nsec as u32).unwrap_or_default();
1046-
let tm: DateTime<Local> = tm.into();
1047-
match tm.timestamp_nanos_opt() {
1048-
None => {
1049-
let micros = tm.timestamp_micros();
1050-
let secs = micros as f64 / 1_000_000.0;
1051-
OutputType::Float(secs)
1052-
}
1053-
Some(ns) => {
1054-
let secs = ns as f64 / 1_000_000_000.0;
1055-
OutputType::Float(secs)
1056-
}
1057-
}
1046+
let (sec, nsec) = metadata_get_time(meta, MetadataTimeField::Modification)
1047+
.map_or((0, 0), system_time_to_sec);
1048+
OutputType::Float(sec as f64 + nsec as f64 / 1_000_000_000.0)
10581049
}
10591050
// time of last status change, human-readable
10601051
'z' => OutputType::Str(pretty_time(meta, MetadataTimeField::Change)),
@@ -1297,7 +1288,7 @@ const PRETTY_DATETIME_FORMAT: &str = "%Y-%m-%d %H:%M:%S.%N %z";
12971288
fn pretty_time(meta: &Metadata, md_time_field: MetadataTimeField) -> String {
12981289
if let Some(time) = metadata_get_time(meta, md_time_field) {
12991290
let mut tmp = Vec::new();
1300-
if uucore::time::format_system_time(&mut tmp, time, PRETTY_DATETIME_FORMAT, false).is_ok() {
1291+
if format_system_time(&mut tmp, time, PRETTY_DATETIME_FORMAT, false).is_ok() {
13011292
return String::from_utf8(tmp).unwrap();
13021293
}
13031294
}

src/uucore/src/lib/features/fsext.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ use std::io::Error as IOError;
6969
use std::mem;
7070
#[cfg(windows)]
7171
use std::path::Path;
72-
use std::time::{SystemTime, UNIX_EPOCH};
72+
use std::time::SystemTime;
73+
#[cfg(not(windows))]
74+
use std::time::UNIX_EPOCH;
7375
use std::{borrow::Cow, ffi::OsString};
7476

7577
use std::fs::Metadata;
@@ -114,19 +116,6 @@ pub use libc::statfs as statfs_fn;
114116
))]
115117
pub use libc::statvfs as statfs_fn;
116118

117-
pub trait BirthTime {
118-
fn birth(&self) -> Option<(u64, u32)>;
119-
}
120-
121-
impl BirthTime for Metadata {
122-
fn birth(&self) -> Option<(u64, u32)> {
123-
self.created()
124-
.ok()
125-
.and_then(|t| t.duration_since(UNIX_EPOCH).ok())
126-
.map(|e| (e.as_secs(), e.subsec_nanos()))
127-
}
128-
}
129-
130119
#[derive(Debug, Copy, Clone)]
131120
pub enum MetadataTimeField {
132121
Modification,

src/uucore/src/lib/features/time.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ fn format_zoned<W: Write>(out: &mut W, zoned: Zoned, fmt: &str) -> UResult<()> {
2525
.map_err(|x| USimpleError::new(1, x.to_string()))
2626
}
2727

28+
/// Convert a SystemTime` to a number of seconds since UNIX_EPOCH
29+
pub fn system_time_to_sec(time: SystemTime) -> (i64, u32) {
30+
if time > UNIX_EPOCH {
31+
let d = time.duration_since(UNIX_EPOCH).unwrap();
32+
(d.as_secs() as i64, d.subsec_nanos())
33+
} else {
34+
let d = UNIX_EPOCH.duration_since(time).unwrap();
35+
(-(d.as_secs() as i64), d.subsec_nanos())
36+
}
37+
}
38+
2839
/// Format a `SystemTime` according to given fmt, and append to vector out.
2940
pub fn format_system_time<W: Write>(
3041
out: &mut W,
@@ -42,11 +53,7 @@ pub fn format_system_time<W: Write>(
4253
// but it still far enough in the future/past to be unlikely to matter:
4354
// jiff: Year between -9999 to 9999 (UTC) [-377705023201..=253402207200]
4455
// GNU: Year fits in signed 32 bits (timezone dependent)
45-
let ts: i64 = if time > UNIX_EPOCH {
46-
time.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64
47-
} else {
48-
-(UNIX_EPOCH.duration_since(time).unwrap().as_secs() as i64)
49-
};
56+
let ts: i64 = system_time_to_sec(time).0;
5057
let str = ts.to_string();
5158
if show_error {
5259
show_error!("time '{str}' is out of range");

0 commit comments

Comments
 (0)