diff --git a/rslib/io/src/error.rs b/rslib/io/src/error.rs index 6df493940..c66a29a41 100644 --- a/rslib/io/src/error.rs +++ b/rslib/io/src/error.rs @@ -35,6 +35,7 @@ pub enum FileOp { Sync, Metadata, DecodeUtf8Filename, + SetFileTimes, /// For legacy errors without any context. Unknown, } @@ -61,6 +62,7 @@ impl FileIoError { FileOp::Sync => "sync".into(), FileOp::Metadata => "get metadata".into(), FileOp::DecodeUtf8Filename => "decode utf8 filename".into(), + FileOp::SetFileTimes => "set file times".into(), }, self.path.to_string_lossy(), self.source diff --git a/rslib/io/src/lib.rs b/rslib/io/src/lib.rs index 7420da3cb..f9ee9758a 100644 --- a/rslib/io/src/lib.rs +++ b/rslib/io/src/lib.rs @@ -4,6 +4,8 @@ mod error; use std::fs::File; +use std::fs::FileTimes; +use std::fs::OpenOptions; use std::io::Read; use std::io::Seek; use std::path::Component; @@ -37,6 +39,13 @@ pub fn open_file(path: impl AsRef) -> Result { }) } +pub fn open_file_ext(path: impl AsRef, options: OpenOptions) -> Result { + options.open(&path).context(FileIoSnafu { + path: path.as_ref(), + op: FileOp::Open, + }) +} + /// See [std::fs::write]. pub fn write_file(path: impl AsRef, contents: impl AsRef<[u8]>) -> Result<()> { std::fs::write(&path, contents).context(FileIoSnafu { @@ -44,6 +53,14 @@ pub fn write_file(path: impl AsRef, contents: impl AsRef<[u8]>) -> Result< op: FileOp::Write, }) } +/// See [File::set_times]. Note that this won't work on folders. +pub fn set_file_times(path: impl AsRef, times: FileTimes) -> Result<()> { + let file = open_file_ext(&path, OpenOptions::new().write(true).to_owned())?; + file.set_times(times).context(FileIoSnafu { + path: path.as_ref(), + op: FileOp::SetFileTimes, + }) +} /// See [std::fs::remove_file]. #[allow(dead_code)] diff --git a/rslib/src/media/files.rs b/rslib/src/media/files.rs index 2cbef1a89..9fd3bc85f 100644 --- a/rslib/src/media/files.rs +++ b/rslib/src/media/files.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use std::fs; +use std::fs::FileTimes; use std::io; use std::io::Read; use std::path::Path; @@ -12,6 +13,7 @@ use std::time; use anki_io::create_dir; use anki_io::open_file; +use anki_io::set_file_times; use anki_io::write_file; use anki_io::FileIoError; use anki_io::FileIoSnafu; @@ -345,11 +347,9 @@ where fs::rename(&src_path, &dst_path)?; // mark it as modified, so we can expire it in the future - let secs = time::SystemTime::now() - .duration_since(time::UNIX_EPOCH) - .unwrap() - .as_secs() as i64; - if let Err(err) = utime::set_file_times(&dst_path, secs, secs) { + let secs = time::SystemTime::now(); + let times = FileTimes::new().set_accessed(secs).set_modified(secs); + if let Err(err) = set_file_times(&dst_path, times) { // The libc utimes() call fails on (some? all?) Android devices. Since we don't // do automatic expiry yet, we can safely ignore the error. if !cfg!(target_os = "android") {