Skip to content

Commit 5362be0

Browse files
Pr0metheanmass10
andauthored
fix: Restore original file timestamp when unzipping with chrono (#46)
* Set filetime * Add chrono * fix: Duplicate "chrono" entry in Cargo.toml Signed-off-by: Chris Hennick <[email protected]> * fix: typo in read.rs Signed-off-by: Chris Hennick <[email protected]> * fix: missing feature gate Signed-off-by: Chris Hennick <[email protected]> * Set filetime * Add chrono * fix: Duplicate "chrono" entry in Cargo.toml Signed-off-by: Chris Hennick <[email protected]> * fix: typo in read.rs Signed-off-by: Chris Hennick <[email protected]> * fix: Errors due to missing chrono feature gate * fix: bad merge * style: cargo fmt --all * fix: chrono has renamed method to from_utc * Revert "fix: chrono has renamed method to from_utc" This reverts commit 38cc3ca. * fix: from_utc is deprecated, but from_naive_utc_and_offset doesn't exist before 0.4.27 --------- Signed-off-by: Chris Hennick <[email protected]> Co-authored-by: mass10 <[email protected]>
1 parent 4802b87 commit 5362be0

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ time = { version = "0.3.37", default-features = false }
2929
[dependencies]
3030
aes = { version = "0.8", optional = true }
3131
bzip2 = { version = "0.6.0", optional = true }
32-
chrono = { version = "0.4", optional = true }
32+
chrono = { version = "^0.4.27", optional = true }
3333
constant_time_eq = { version = "0.3.1", optional = true }
3434
crc32fast = "1.4"
3535
flate2 = { version = "1.1.1", default-features = false, optional = true }

src/read.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,7 @@ impl<R: Read + Seek> ZipArchive<R> {
910910
}
911911
let mut file = self.by_index(i)?;
912912
let mut outfile = fs::File::create(&outpath)?;
913+
913914
io::copy(&mut file, &mut outfile)?;
914915
#[cfg(unix)]
915916
{
@@ -918,6 +919,15 @@ impl<R: Read + Seek> ZipArchive<R> {
918919
files_by_unix_mode.push((outpath.clone(), mode));
919920
}
920921
}
922+
#[cfg(feature = "chrono")]
923+
{
924+
// Set original timestamp.
925+
if let Some(last_modified) = file.last_modified() {
926+
if let Some(t) = datetime_to_systemtime(&last_modified) {
927+
outfile.set_modified(t)?;
928+
}
929+
}
930+
}
921931
}
922932
#[cfg(unix)]
923933
{
@@ -2024,6 +2034,35 @@ pub fn root_dir_common_filter(path: &Path) -> bool {
20242034
true
20252035
}
20262036

2037+
#[cfg(feature = "chrono")]
2038+
/// Generate a `SystemTime` from a `DateTime`.
2039+
fn datetime_to_systemtime(datetime: &DateTime) -> Option<std::time::SystemTime> {
2040+
if let Some(t) = generate_chrono_datetime(datetime) {
2041+
let time = chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(t, chrono::Utc);
2042+
return Some(time.into());
2043+
}
2044+
None
2045+
}
2046+
2047+
#[cfg(feature = "chrono")]
2048+
/// Generate a `NaiveDateTime` from a `DateTime`.
2049+
fn generate_chrono_datetime(datetime: &DateTime) -> Option<chrono::NaiveDateTime> {
2050+
if let Some(d) = chrono::NaiveDate::from_ymd_opt(
2051+
datetime.year().into(),
2052+
datetime.month().into(),
2053+
datetime.day().into(),
2054+
) {
2055+
if let Some(d) = d.and_hms_opt(
2056+
datetime.hour().into(),
2057+
datetime.minute().into(),
2058+
datetime.second().into(),
2059+
) {
2060+
return Some(d);
2061+
}
2062+
}
2063+
None
2064+
}
2065+
20272066
#[cfg(test)]
20282067
mod test {
20292068
use crate::result::ZipResult;

0 commit comments

Comments
 (0)