Merge pull request #271 from figsoda/zip-permissions

fix: respect file permissions when compressing zip files
This commit is contained in:
João Marcos Bezerra 2022-09-16 18:46:57 -03:00 committed by GitHub
commit 398a619018
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 13 deletions

View File

@ -142,6 +142,7 @@ Categories Used:
- CI: Rewrite [\#135](https://github.com/ouch-org/ouch/pull/135) ([figsoda](https://github.com/figsoda)) - CI: Rewrite [\#135](https://github.com/ouch-org/ouch/pull/135) ([figsoda](https://github.com/figsoda))
- Improving error messages and removing dead error treatment code [\#140](https://github.com/ouch-org/ouch/pull/140) ([marcospb19](https://github.com/marcospb19)) - Improving error messages and removing dead error treatment code [\#140](https://github.com/ouch-org/ouch/pull/140) ([marcospb19](https://github.com/marcospb19))
- Apply clippy lints and simplify smart_unpack [\#267](https://github.com/ouch-org/ouch/pull/267) ([figsoda](https://github.com/figsoda)) - Apply clippy lints and simplify smart_unpack [\#267](https://github.com/ouch-org/ouch/pull/267) ([figsoda](https://github.com/figsoda))
- Respect file permissions when compressing zip files [\#271](https://github.com/ouch-org/ouch/pull/271) ([figsoda](https://github.com/figsoda))
### Tweaks ### Tweaks

10
Cargo.lock generated
View File

@ -384,6 +384,15 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "is_executable"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.3" version = "0.10.3"
@ -525,6 +534,7 @@ dependencies = [
"ignore", "ignore",
"indicatif", "indicatif",
"infer", "infer",
"is_executable",
"libc", "libc",
"linked-hash-map", "linked-hash-map",
"lzzzz", "lzzzz",

View File

@ -34,6 +34,9 @@ indicatif = "0.16.2"
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
time = { version = "0.3.9", default-features = false } time = { version = "0.3.9", default-features = false }
[target.'cfg(not(unix))'.dependencies]
is_executable = "1.0.1"
[build-dependencies] [build-dependencies]
clap = { version = "3.1.18", features = ["derive", "env"] } clap = { version = "3.1.18", features = ["derive", "env"] }
clap_complete = "3.1.4" clap_complete = "3.1.4"

View File

@ -1,5 +1,7 @@
//! Contains Zip-specific building and unpacking functions //! Contains Zip-specific building and unpacking functions
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::{ use std::{
env, env,
io::{self, prelude::*}, io::{self, prelude::*},
@ -138,6 +140,9 @@ where
let mut writer = zip::ZipWriter::new(writer); let mut writer = zip::ZipWriter::new(writer);
let options = zip::write::FileOptions::default(); let options = zip::write::FileOptions::default();
#[cfg(not(unix))]
let executable = options.unix_permissions(0o755);
// Vec of any filename that failed the UTF-8 check // Vec of any filename that failed the UTF-8 check
let invalid_unicode_filenames = get_invalid_utf8_paths(input_filenames); let invalid_unicode_filenames = get_invalid_utf8_paths(input_filenames);
@ -168,21 +173,33 @@ where
// and so on // and so on
info!(@display_handle, inaccessible, "Compressing '{}'.", to_utf(path)); info!(@display_handle, inaccessible, "Compressing '{}'.", to_utf(path));
if path.is_dir() { let metadata = match path.metadata() {
Ok(metadata) => metadata,
Err(e) => {
if e.kind() == std::io::ErrorKind::NotFound && utils::is_symlink(path) {
// This path is for a broken symlink
// We just ignore it
continue;
}
return Err(e.into());
}
};
#[cfg(unix)]
let options = options.unix_permissions(metadata.permissions().mode());
if metadata.is_dir() {
writer.add_directory(path.to_str().unwrap().to_owned(), options)?; writer.add_directory(path.to_str().unwrap().to_owned(), options)?;
} else { } else {
writer.start_file(path.to_str().unwrap().to_owned(), options)?; #[cfg(not(unix))]
let file_bytes = match fs::read(entry.path()) { let options = if is_executable::is_executable(path) {
Ok(b) => b, executable
Err(e) => { } else {
if e.kind() == std::io::ErrorKind::NotFound && utils::is_symlink(path) { options
// This path is for a broken symlink
// We just ignore it
continue;
}
return Err(e.into());
}
}; };
writer.start_file(path.to_str().unwrap().to_owned(), options)?;
let file_bytes = fs::read(entry.path())?;
writer.write_all(&file_bytes)?; writer.write_all(&file_bytes)?;
} }
} }
@ -260,7 +277,7 @@ fn set_last_modified_time(file: &fs::File, zip_file: &ZipFile) -> crate::Result<
#[cfg(unix)] #[cfg(unix)]
fn __unix_set_permissions(file_path: &Path, file: &ZipFile) -> crate::Result<()> { fn __unix_set_permissions(file_path: &Path, file: &ZipFile) -> crate::Result<()> {
use std::{fs::Permissions, os::unix::fs::PermissionsExt}; use std::fs::Permissions;
if let Some(mode) = file.unix_mode() { if let Some(mode) = file.unix_mode() {
fs::set_permissions(file_path, Permissions::from_mode(mode))?; fs::set_permissions(file_path, Permissions::from_mode(mode))?;