Skip to content

Commit 05cde3b

Browse files
committed
Preserve file timestamps (#16)
1 parent 3cf990e commit 05cde3b

File tree

5 files changed

+62
-19
lines changed

5 files changed

+62
-19
lines changed

CHANGELOG.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## [0.9.0] - 2020-03-03
4+
### Added
5+
- Preserve file timestamps following compression/decompression ([#16])
6+
37
## [0.8.0] - 2020-02-29
48
### Added
59
- Excluded directories now get skipped entirely ([#8])
@@ -20,9 +24,10 @@
2024

2125
[0.7.1]: https://github.com/Freaky/Compactor/releases/tag/v0.7.1
2226
[0.8.0]: https://github.com/Freaky/Compactor/releases/tag/v0.8.0
23-
24-
[#11]: https://github.com/Freaky/Compactor/pull/11
25-
[#10]: https://github.com/Freaky/Compactor/pull/10
26-
[#9]: https://github.com/Freaky/Compactor/pull/9
27-
[#8]: https://github.com/Freaky/Compactor/issues/8
27+
[0.9.0]: https://github.com/Freaky/Compactor/releases/tag/v0.9.0
2828
[#6]: https://github.com/Freaky/Compactor/issues/6
29+
[#8]: https://github.com/Freaky/Compactor/issues/8
30+
[#9]: https://github.com/Freaky/Compactor/pull/9
31+
[#10]: https://github.com/Freaky/Compactor/pull/10
32+
[#11]: https://github.com/Freaky/Compactor/pull/11
33+
[#16]: https://github.com/Freaky/Compactor/issues/16

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "compactor"
3-
version = "0.8.0"
3+
version = "0.9.0"
44
authors = ["Thomas Hurst <[email protected]>"]
55
homepage = "https://github.com/Freaky/Compactor"
66
description = "An interface to Windows 10 filesystem compression"
@@ -29,6 +29,7 @@ siphasher = "0.3.0"
2929
walkdir = "2.2.8"
3030
web-view = "0.6.0"
3131
winapi = { version = "0.3.7", features = [ "combaseapi", "ioapiset", "knownfolders", "shellscalingapi", "shlobj", "shtypes", "winbase", "winerror", "winioctl", "winver"] }
32+
filetime = "0.2.8"
3233

3334
[[bin]]
3435
name = "Compactor"

src/compact.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,10 @@ unsafe fn as_byte_slice<T: Sized + Copy>(p: &T) -> &[u8] {
271271

272272
pub fn compress_file<P: AsRef<Path>>(path: P, compression: Compression) -> std::io::Result<bool> {
273273
let file = std::fs::File::open(path)?;
274+
compress_file_handle(&file, compression)
275+
}
274276

277+
pub fn compress_file_handle(file: &std::fs::File, compression: Compression) -> std::io::Result<bool> {
275278
const LEN: usize = std::mem::size_of::<_WOF_EXTERNAL_INFO>()
276279
+ std::mem::size_of::<_FILE_PROVIDER_EXTERNAL_INFO_V1>();
277280

@@ -315,7 +318,10 @@ pub fn compress_file<P: AsRef<Path>>(path: P, compression: Compression) -> std::
315318

316319
pub fn uncompress_file<P: AsRef<Path>>(path: P) -> std::io::Result<()> {
317320
let file = std::fs::File::open(path)?;
321+
uncompress_file_handle(&file)
322+
}
318323

324+
pub fn uncompress_file_handle(file: &std::fs::File) -> std::io::Result<()> {
319325
let mut bytes_returned: DWORD = 0;
320326

321327
let ret = unsafe {

src/compression.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use std::io;
22
use std::path::PathBuf;
3+
use std::os::windows::fs::OpenOptionsExt;
34

45
use compresstimator::Compresstimator;
56
use crossbeam_channel::{Receiver, Sender};
7+
use filetime::FileTime;
8+
use winapi::um::winnt::{FILE_WRITE_ATTRIBUTES, FILE_READ_DATA};
69

710
use crate::background::Background;
811
use crate::background::ControlToken;
@@ -29,29 +32,44 @@ impl BackgroundCompactor {
2932
}
3033
}
3134

35+
fn handle_file(file: &PathBuf, compression: Option<Compression>) -> io::Result<bool> {
36+
let est = Compresstimator::with_block_size(8192);
37+
let meta = std::fs::metadata(&file)?;
38+
let handle = std::fs::OpenOptions::new()
39+
.access_mode(FILE_WRITE_ATTRIBUTES | FILE_READ_DATA)
40+
.open(&file)?;
41+
42+
let ret = match compression {
43+
Some(compression) => match est.compresstimate(&handle, meta.len()) {
44+
Ok(ratio) if ratio < 0.95 => compact::compress_file_handle(&handle, compression),
45+
Ok(_) => Ok(false),
46+
Err(e) => Err(e),
47+
},
48+
None => compact::uncompress_file_handle(&handle).map(|_| true),
49+
};
50+
51+
let _ = filetime::set_file_handle_times(
52+
&handle,
53+
Some(FileTime::from_last_access_time(&meta)),
54+
Some(FileTime::from_last_modification_time(&meta))
55+
);
56+
57+
ret
58+
}
59+
3260
impl Background for BackgroundCompactor {
3361
type Output = ();
3462
type Status = ();
3563

3664
fn run(&self, control: &ControlToken<Self::Status>) -> Self::Output {
37-
let est = Compresstimator::with_block_size(8192);
38-
3965
for file in &self.files_in {
4066
if control.is_cancelled_with_pause() {
4167
break;
4268
}
4369

4470
match file {
45-
Some((file, len)) => {
46-
let ret = match self.compression {
47-
Some(compression) => match est.compresstimate_file_len(&file, len) {
48-
Ok(ratio) if ratio < 0.95 => compact::compress_file(&file, compression),
49-
Ok(_) => Ok(false),
50-
Err(e) => Err(e),
51-
},
52-
None => compact::uncompress_file(&file).map(|_| true),
53-
};
54-
71+
Some((file, _len)) => {
72+
let ret = handle_file(&file, self.compression);
5573
if self.files_out.send((file, ret)).is_err() {
5674
break;
5775
}

0 commit comments

Comments
 (0)