Skip to content

Commit

Permalink
archive: work from leaves up when unpacking directories
Browse files Browse the repository at this point in the history
  • Loading branch information
jeckersb committed Apr 17, 2023
1 parent f4f439c commit 3c384e0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/archive.rs
Expand Up @@ -217,12 +217,17 @@ impl Archive<dyn Read + '_> {
for entry in self._entries(None)? {
let mut file = entry.map_err(|e| TarError::new("failed to iterate over archive", e))?;
if file.header().entry_type() == crate::EntryType::Directory {
directories.push(file);
directories.push((file.path()?.components().count(), file));
} else {
file.unpack_in(dst)?;
}
}
for mut dir in directories {

// Work from leaves up. Otherwise when a parent directory has
// no write permission, any empty subdirectories beneath it
// cannot be created.
directories.sort_by(|a, b| b.0.cmp(&a.0));
for (_, mut dir) in directories {
dir.unpack_in(dst)?;
}

Expand Down
26 changes: 26 additions & 0 deletions tests/all.rs
Expand Up @@ -1317,6 +1317,32 @@ fn read_only_directory_containing_files() {
assert!(ar.unpack(td.path()).is_ok());
}

#[test]
fn read_only_directory_containing_empty_directory() {
let test_dirs_with_modes: Box<dyn Fn(&[(&str, u32)])> = Box::new(|dirs| {
let td = t!(TempBuilder::new().prefix("tar-rs").tempdir());

let mut b = Builder::new(Vec::<u8>::new());

for (path, mode) in dirs {
let mut h = Header::new_gnu();
t!(h.set_path(path));
h.set_size(0);
h.set_entry_type(EntryType::dir());
h.set_mode(*mode);
h.set_cksum();
t!(b.append(&h, "".as_bytes()));
}

let contents = t!(b.into_inner());
let mut ar = Archive::new(&contents[..]);
assert!(ar.unpack(td.path()).is_ok());
});

test_dirs_with_modes(&[("dir/", 0o444), ("dir/subdir", 0o755)]);
test_dirs_with_modes(&[("dir/subdir", 0o755), ("dir/", 0o444)]);
}

// This test was marked linux only due to macOS CI can't handle `set_current_dir` correctly
#[test]
#[cfg(target_os = "linux")]
Expand Down

0 comments on commit 3c384e0

Please sign in to comment.