Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions Cargo.lock

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

1 change: 0 additions & 1 deletion cpio-archive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ readme = "README.md"

[dependencies]
chrono = "0.4.43"
is_executable = "1.0.5"
simple-file-manifest = "0.11.0"
thiserror = "2.0.18"
71 changes: 50 additions & 21 deletions cpio-archive/src/odc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
use {
crate::{CpioHeader, CpioReader, CpioResult, Error},
chrono::{DateTime, Utc},
is_executable::IsExecutable,
simple_file_manifest::{
FileManifest, S_IFDIR, S_IRGRP, S_IROTH, S_IRUSR, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR,
},
std::{
collections::HashSet,
ffi::CStr,
fs,
io::{Read, Take, Write},
path::Path,
},
Expand Down Expand Up @@ -70,6 +70,33 @@ fn write_octal(value: u64, writer: &mut impl Write, size: usize) -> CpioResult<(
Ok(())
}

/// permissions_to_u32 converts fs::Permissions objects to chmod integers.
pub fn permissions_to_u32(permissions: fs::Permissions) -> u32 {
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
permissions.mode()
}
#[cfg(windows)]
{
if permissions.readonly() {
0o444u32
} else {
0o666u32
}
}
}

/// GENERIC_DIRECTORY_MODE applies to auto generated directories.
const GENERIC_DIRECTORY_MODE: u32 = S_IFDIR
| S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH;

/// Parsed portable ASCII format header.
#[derive(Clone, Debug)]
pub struct OdcHeader {
Expand Down Expand Up @@ -297,8 +324,8 @@ pub struct OdcBuilder<W: Write + Sized> {
default_uid: u32,
default_gid: u32,
default_mtime: DateTime<Utc>,
default_mode_file: u32,
default_mode_dir: u32,
default_mode_file: Option<u32>,
default_mode_dir: Option<u32>,
auto_write_dirs: bool,
seen_dirs: HashSet<String>,
entry_count: u32,
Expand All @@ -313,15 +340,8 @@ impl<W: Write + Sized> OdcBuilder<W> {
default_uid: 0,
default_gid: 0,
default_mtime: Utc::now(),
default_mode_file: S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
default_mode_dir: S_IFDIR
| S_IRUSR
| S_IWUSR
| S_IXUSR
| S_IRGRP
| S_IXGRP
| S_IROTH
| S_IXOTH,
default_mode_file: None,
default_mode_dir: None,
auto_write_dirs: true,
seen_dirs: HashSet::new(),
entry_count: 0,
Expand All @@ -330,12 +350,12 @@ impl<W: Write + Sized> OdcBuilder<W> {
}

/// Set the default file mode to use for files.
pub fn default_mode_file(&mut self, mode: u32) {
pub fn default_mode_file(&mut self, mode: Option<u32>) {
self.default_mode_file = mode;
}

/// Set the default file mode to use for directories.
pub fn default_mode_directory(&mut self, mode: u32) {
pub fn default_mode_directory(&mut self, mode: Option<u32>) {
self.default_mode_dir = mode;
}

Expand Down Expand Up @@ -372,7 +392,7 @@ impl<W: Write + Sized> OdcBuilder<W> {
OdcHeader {
dev: 0,
inode,
mode: self.default_mode_file,
mode: 0u32,
uid: self.default_uid,
gid: self.default_gid,
nlink: 0,
Expand Down Expand Up @@ -407,7 +427,7 @@ impl<W: Write + Sized> OdcBuilder<W> {

if !self.seen_dirs.contains(&dir) {
let mut header = self.next_header();
header.mode = self.default_mode_dir;
header.mode = self.default_mode_file.unwrap_or(GENERIC_DIRECTORY_MODE);
header.name = dir.clone();

bytes_written += header.write(&mut self.writer)?;
Expand Down Expand Up @@ -516,10 +536,7 @@ impl<W: Write + Sized> OdcBuilder<W> {
let mut header = self.next_header();
header.name = archive_path;
header.file_size = metadata.len();

if path.is_executable() {
header.mode |= S_IXUSR | S_IXGRP | S_IXOTH;
}
header.mode = self.default_mode_file.unwrap_or(permissions_to_u32(metadata.permissions()));

bytes_written += header.write(&mut self.writer)?;
bytes_written += std::io::copy(&mut fh, &mut self.writer)?;
Expand All @@ -532,7 +549,19 @@ impl<W: Write + Sized> OdcBuilder<W> {
let mut bytes_written = 0;

for (path, entry) in manifest.iter_entries() {
let mode = if entry.is_executable() { 0o755 } else { 0o644 };
let metadata = path.metadata()?;
let mut mode = permissions_to_u32(metadata.permissions());

if metadata.is_file() {
if let Some(m) = self.default_mode_file {
mode = m;
}
} else if metadata.is_dir() {
if let Some(m) = self.default_mode_dir {
mode = m;
}
}

let data = entry.resolve_content()?;

bytes_written += self.append_file_from_data(path.display().to_string(), data, mode)?;
Expand Down