Skip to content

Commit

Permalink
Preserve file timestamps (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
Freaky committed Mar 3, 2020
1 parent 3cf990e commit 05cde3b
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 19 deletions.
15 changes: 10 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## [0.9.0] - 2020-03-03
### Added
- Preserve file timestamps following compression/decompression ([#16])

## [0.8.0] - 2020-02-29
### Added
- Excluded directories now get skipped entirely ([#8])
Expand All @@ -20,9 +24,10 @@

[0.7.1]: https://github.com/Freaky/Compactor/releases/tag/v0.7.1
[0.8.0]: https://github.com/Freaky/Compactor/releases/tag/v0.8.0

[#11]: https://github.com/Freaky/Compactor/pull/11
[#10]: https://github.com/Freaky/Compactor/pull/10
[#9]: https://github.com/Freaky/Compactor/pull/9
[#8]: https://github.com/Freaky/Compactor/issues/8
[0.9.0]: https://github.com/Freaky/Compactor/releases/tag/v0.9.0
[#6]: https://github.com/Freaky/Compactor/issues/6
[#8]: https://github.com/Freaky/Compactor/issues/8
[#9]: https://github.com/Freaky/Compactor/pull/9
[#10]: https://github.com/Freaky/Compactor/pull/10
[#11]: https://github.com/Freaky/Compactor/pull/11
[#16]: https://github.com/Freaky/Compactor/issues/16
15 changes: 14 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "compactor"
version = "0.8.0"
version = "0.9.0"
authors = ["Thomas Hurst <[email protected]>"]
homepage = "https://github.com/Freaky/Compactor"
description = "An interface to Windows 10 filesystem compression"
Expand Down Expand Up @@ -29,6 +29,7 @@ siphasher = "0.3.0"
walkdir = "2.2.8"
web-view = "0.6.0"
winapi = { version = "0.3.7", features = [ "combaseapi", "ioapiset", "knownfolders", "shellscalingapi", "shlobj", "shtypes", "winbase", "winerror", "winioctl", "winver"] }
filetime = "0.2.8"

[[bin]]
name = "Compactor"
Expand Down
6 changes: 6 additions & 0 deletions src/compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,10 @@ unsafe fn as_byte_slice<T: Sized + Copy>(p: &T) -> &[u8] {

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

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

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

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

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

let ret = unsafe {
Expand Down
42 changes: 30 additions & 12 deletions src/compression.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::io;
use std::path::PathBuf;
use std::os::windows::fs::OpenOptionsExt;

use compresstimator::Compresstimator;
use crossbeam_channel::{Receiver, Sender};
use filetime::FileTime;
use winapi::um::winnt::{FILE_WRITE_ATTRIBUTES, FILE_READ_DATA};

use crate::background::Background;
use crate::background::ControlToken;
Expand All @@ -29,29 +32,44 @@ impl BackgroundCompactor {
}
}

fn handle_file(file: &PathBuf, compression: Option<Compression>) -> io::Result<bool> {
let est = Compresstimator::with_block_size(8192);
let meta = std::fs::metadata(&file)?;
let handle = std::fs::OpenOptions::new()
.access_mode(FILE_WRITE_ATTRIBUTES | FILE_READ_DATA)
.open(&file)?;

let ret = match compression {
Some(compression) => match est.compresstimate(&handle, meta.len()) {
Ok(ratio) if ratio < 0.95 => compact::compress_file_handle(&handle, compression),
Ok(_) => Ok(false),
Err(e) => Err(e),
},
None => compact::uncompress_file_handle(&handle).map(|_| true),
};

let _ = filetime::set_file_handle_times(
&handle,
Some(FileTime::from_last_access_time(&meta)),
Some(FileTime::from_last_modification_time(&meta))
);

ret
}

impl Background for BackgroundCompactor {
type Output = ();
type Status = ();

fn run(&self, control: &ControlToken<Self::Status>) -> Self::Output {
let est = Compresstimator::with_block_size(8192);

for file in &self.files_in {
if control.is_cancelled_with_pause() {
break;
}

match file {
Some((file, len)) => {
let ret = match self.compression {
Some(compression) => match est.compresstimate_file_len(&file, len) {
Ok(ratio) if ratio < 0.95 => compact::compress_file(&file, compression),
Ok(_) => Ok(false),
Err(e) => Err(e),
},
None => compact::uncompress_file(&file).map(|_| true),
};

Some((file, _len)) => {
let ret = handle_file(&file, self.compression);
if self.files_out.send((file, ret)).is_err() {
break;
}
Expand Down

0 comments on commit 05cde3b

Please sign in to comment.