From f4f439ca0cd3a984d2a66fb8e42f6e2307876afd Mon Sep 17 00:00:00 2001 From: John Watson Date: Mon, 4 Apr 2022 07:05:17 -0700 Subject: [PATCH] Preserve symlink mtimes (#289) --- src/entry.rs | 32 ++++++++++++++++++++++---------- tests/all.rs | 4 ++++ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/entry.rs b/src/entry.rs index 30938566..cce39d45 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -464,6 +464,19 @@ impl<'a> EntryFields<'a> { Ok(()) } + fn get_mtime(header: &Header) -> Option { + header.mtime().ok().map(|mtime| { + // For some more information on this see the comments in + // `Header::fill_platform_from`, but the general idea is that + // we're trying to avoid 0-mtime files coming out of archives + // since some tools don't ingest them well. Perhaps one day + // when Cargo stops working with 0-mtime archives we can remove + // this. + let mtime = if mtime == 0 { 1 } else { mtime }; + FileTime::from_unix_time(mtime as i64, 0) + }) + } + let kind = self.header.entry_type(); if kind.is_dir() { @@ -546,7 +559,14 @@ impl<'a> EntryFields<'a> { ), ) })?; - }; + if self.preserve_mtime { + if let Some(mtime) = get_mtime(&self.header) { + filetime::set_symlink_file_times(dst, mtime, mtime).map_err(|e| { + TarError::new(format!("failed to set mtime for `{}`", dst.display()), e) + })?; + } + } + } return Ok(Unpacked::__Nonexhaustive); #[cfg(target_arch = "wasm32")] @@ -646,15 +666,7 @@ impl<'a> EntryFields<'a> { })?; if self.preserve_mtime { - if let Ok(mtime) = self.header.mtime() { - // For some more information on this see the comments in - // `Header::fill_platform_from`, but the general idea is that - // we're trying to avoid 0-mtime files coming out of archives - // since some tools don't ingest them well. Perhaps one day - // when Cargo stops working with 0-mtime archives we can remove - // this. - let mtime = if mtime == 0 { 1 } else { mtime }; - let mtime = FileTime::from_unix_time(mtime as i64, 0); + if let Some(mtime) = get_mtime(&self.header) { filetime::set_file_handle_times(&f, Some(mtime), Some(mtime)).map_err(|e| { TarError::new(format!("failed to set mtime for `{}`", dst.display()), e) })?; diff --git a/tests/all.rs b/tests/all.rs index 76c668f7..fa38ef62 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -792,6 +792,10 @@ fn unpack_links() { let md = t!(fs::symlink_metadata(td.path().join("lnk"))); assert!(md.file_type().is_symlink()); + + let mtime = FileTime::from_last_modification_time(&md); + assert_eq!(mtime.unix_seconds(), 1448291033); + assert_eq!( &*t!(fs::read_link(td.path().join("lnk"))), Path::new("file")