From ae19de8597f41c83983e6e6ca35f31d845f16bd3 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 9 Aug 2026 07:19:49 +0900 Subject: feat(archiver): preserve file permissions in zip archives The shim reported setExternalAttributesName as missing, so ZipArchiver took the branch for libzip below 0.11.2 and every archived entry got the zip crate's default mode. The attributes now travel as arguments to add_file and add_empty_dir, because the crate fixes an entry's external attributes when the entry is started and offers no way to amend one already written. unix_permissions keeps only the low 9 mode bits, on top of which the crate restores S_IFREG and S_IFDIR, so setuid/setgid/sticky bits and other file types are still dropped. Co-Authored-By: Claude Opus 5 --- .../shirabe/src/package/archiver/zip_archiver.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'crates/shirabe') diff --git a/crates/shirabe/src/package/archiver/zip_archiver.rs b/crates/shirabe/src/package/archiver/zip_archiver.rs index e5bb613d..5604c07d 100644 --- a/crates/shirabe/src/package/archiver/zip_archiver.rs +++ b/crates/shirabe/src/package/archiver/zip_archiver.rs @@ -5,9 +5,7 @@ use crate::package::archiver::ArchiverInterface; use crate::util::Filesystem; use crate::util::Platform; use indexmap::IndexMap; -use shirabe_php_shim::{ - PhpMixed, RuntimeException, ZipArchive, class_exists, fileperms, method_exists, realpath, -}; +use shirabe_php_shim::{RuntimeException, ZipArchive, class_exists, fileperms, realpath}; use std::path::PathBuf; #[derive(Debug)] @@ -71,16 +69,18 @@ impl ArchiverInterface for ZipArchiver { )); } + // Ensure to preserve the permission umasks for the filepath in the archive. + let perms = fileperms(&filepath); + if filepath.is_dir() { - zip.add_empty_dir(&relative_path.to_string_lossy()); + zip.add_empty_dir( + &relative_path.to_string_lossy(), + ZipArchive::OPSYS_UNIX, + perms << 16, + ); } else { - zip.add_file(&filepath, &relative_path.to_string_lossy()); - } - - // setExternalAttributesName() is only available with libzip 0.11.2 or above - if method_exists(&PhpMixed::Null, "setExternalAttributesName") { - let perms = fileperms(&filepath); - zip.set_external_attributes_name( + zip.add_file( + &filepath, &relative_path.to_string_lossy(), ZipArchive::OPSYS_UNIX, perms << 16, -- cgit v1.3.1-4-g156e