Skip to content

Commit a636d08

Browse files
committed
Fix handling of potentially unsupported time metadata
- Checking on a directory doesn’t tell us if supported elsewhere (some filesystems, like tmpfs, don’t support created time) - We want to be able to display a column even if some subfiles or subdirectories don’t support it So now if unsupported a time of zero is used, and displayed as `-`
1 parent 89c861f commit a636d08

File tree

5 files changed

+22
-75
lines changed

5 files changed

+22
-75
lines changed

src/fs/file.rs

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,10 @@ impl<'dir> File<'dir> {
328328

329329
/// This file’s last modified timestamp.
330330
pub fn modified_time(&self) -> Duration {
331-
self.metadata.modified().unwrap().duration_since(UNIX_EPOCH).unwrap()
331+
match self.metadata.modified() {
332+
Ok(system_time) => system_time.duration_since(UNIX_EPOCH).unwrap(),
333+
Err(_) => Duration::new(0, 0),
334+
}
332335
}
333336

334337
/// This file’s last changed timestamp.
@@ -338,12 +341,18 @@ impl<'dir> File<'dir> {
338341

339342
/// This file’s last accessed timestamp.
340343
pub fn accessed_time(&self) -> Duration {
341-
self.metadata.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap()
344+
match self.metadata.accessed() {
345+
Ok(system_time) => system_time.duration_since(UNIX_EPOCH).unwrap(),
346+
Err(_) => Duration::new(0, 0),
347+
}
342348
}
343349

344350
/// This file’s created timestamp.
345351
pub fn created_time(&self) -> Duration {
346-
self.metadata.created().unwrap().duration_since(UNIX_EPOCH).unwrap()
352+
match self.metadata.created() {
353+
Ok(system_time) => system_time.duration_since(UNIX_EPOCH).unwrap(),
354+
Err(_) => Duration::new(0, 0),
355+
}
347356
}
348357

349358
/// This file’s ‘type’.
@@ -460,41 +469,6 @@ impl<'dir> FileTarget<'dir> {
460469
}
461470

462471

463-
pub enum PlatformMetadata {
464-
ModifiedTime,
465-
ChangedTime,
466-
AccessedTime,
467-
CreatedTime,
468-
}
469-
470-
impl PlatformMetadata {
471-
pub fn check_supported(&self) -> Result<(), Misfire> {
472-
use std::env::temp_dir;
473-
let result = match self {
474-
// Call the functions that return a Result to see if it works
475-
PlatformMetadata::AccessedTime => metadata(temp_dir()).unwrap().accessed(),
476-
PlatformMetadata::ModifiedTime => metadata(temp_dir()).unwrap().modified(),
477-
PlatformMetadata::CreatedTime => metadata(temp_dir()).unwrap().created(),
478-
// We use the Unix API so we know it’s not available elsewhere
479-
PlatformMetadata::ChangedTime => {
480-
if cfg!(target_family = "unix") {
481-
return Ok(())
482-
} else {
483-
return Err(Misfire::Unsupported(
484-
// for consistency, this error message similar to the one Rust
485-
// use when created time is not available
486-
"status modified time is not available on this platform currently".to_string()));
487-
}
488-
},
489-
};
490-
match result {
491-
Ok(_) => Ok(()),
492-
Err(err) => Err(Misfire::Unsupported(err.to_string()))
493-
}
494-
}
495-
}
496-
497-
498472
/// More readable aliases for the permission bits exposed by libc.
499473
#[allow(trivial_numeric_casts)]
500474
mod modes {

src/fs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ mod dir;
22
pub use self::dir::{Dir, DotFilter};
33

44
mod file;
5-
pub use self::file::{File, FileTarget, PlatformMetadata};
5+
pub use self::file::{File, FileTarget};
66

77
pub mod feature;
88
pub mod fields;

src/options/filter.rs

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Parsing the options for `FileFilter`.
22
3-
use fs::{DotFilter, PlatformMetadata};
3+
use fs::DotFilter;
44
use fs::filter::{FileFilter, SortField, SortCase, IgnorePatterns, GitIgnore};
55

66
use options::{flags, Misfire};
@@ -67,23 +67,7 @@ impl SortField {
6767
_ => return Err(Misfire::BadArgument(&flags::SORT, word.into()))
6868
};
6969

70-
match SortField::to_platform_metadata(field) {
71-
Some(m) => match m.check_supported() {
72-
Ok(_) => Ok(field),
73-
Err(misfire) => Err(misfire),
74-
},
75-
None => Ok(field),
76-
}
77-
}
78-
79-
fn to_platform_metadata(field: Self) -> Option<PlatformMetadata> {
80-
match field {
81-
SortField::ModifiedDate => Some(PlatformMetadata::ModifiedTime),
82-
SortField::ChangedDate => Some(PlatformMetadata::ChangedTime),
83-
SortField::AccessedDate => Some(PlatformMetadata::AccessedTime),
84-
SortField::CreatedDate => Some(PlatformMetadata::CreatedTime),
85-
_ => None
86-
}
70+
Ok(field)
8771
}
8872
}
8973

src/options/view.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use output::time::TimeFormat;
66
use options::{flags, Misfire, Vars};
77
use options::parser::MatchedFlags;
88

9-
use fs::PlatformMetadata;
109
use fs::feature::xattr;
1110

1211

@@ -344,17 +343,6 @@ impl TimeTypes {
344343
TimeTypes::default()
345344
};
346345

347-
let mut fields = vec![];
348-
if time_types.modified { fields.push(PlatformMetadata::ModifiedTime); }
349-
if time_types.changed { fields.push(PlatformMetadata::ChangedTime); }
350-
if time_types.accessed { fields.push(PlatformMetadata::AccessedTime); }
351-
if time_types.created { fields.push(PlatformMetadata::CreatedTime); }
352-
353-
for field in fields {
354-
if let Err(misfire) = field.check_supported() {
355-
return Err(misfire);
356-
}
357-
}
358346
Ok(time_types)
359347
}
360348
}
@@ -542,15 +530,9 @@ mod test {
542530
test!(time_a: TimeTypes <- ["-t", "acc"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: true, created: false }));
543531

544532
// Created
545-
#[cfg(not(target_os = "linux"))]
546533
test!(cr: TimeTypes <- ["--created"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
547-
#[cfg(target_os = "linux")]
548-
test!(cr: TimeTypes <- ["--created"]; Both => err Misfire::Unsupported("creation time is not available on this platform currently".to_string()));
549-
#[cfg(not(target_os = "linux"))]
550534
test!(c: TimeTypes <- ["-U"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
551-
#[cfg(not(target_os = "linux"))]
552535
test!(time_cr: TimeTypes <- ["--time=created"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
553-
#[cfg(not(target_os = "linux"))]
554536
test!(t_cr: TimeTypes <- ["-tcr"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
555537

556538
// Multiples

src/output/time.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ impl DefaultFormat {
129129

130130
#[allow(trivial_numeric_casts)]
131131
fn format_local(&self, time: Duration) -> String {
132+
if time.as_nanos() == 0 {
133+
return "-".to_string();
134+
}
132135
let date = LocalDateTime::at(time.as_secs() as i64);
133136

134137
if self.is_recent(date) {
@@ -141,6 +144,10 @@ impl DefaultFormat {
141144

142145
#[allow(trivial_numeric_casts)]
143146
fn format_zoned(&self, time: Duration, zone: &TimeZone) -> String {
147+
if time.as_nanos() == 0 {
148+
return "-".to_string();
149+
}
150+
144151
let date = zone.to_zoned(LocalDateTime::at(time.as_secs() as i64));
145152

146153
if self.is_recent(date) {

0 commit comments

Comments
 (0)