mod edge_cases;
mod glob_pattern;
mod keep_solid;
mod missing_file;
mod multiple_clauses;
mod numeric;
mod password;
mod password_file;
mod symbolic_all;
mod symbolic_combined;
mod symbolic_group;
mod symbolic_other;
mod symbolic_user;
mod unsolid;
use crate::utils::{archive, archive::FileEntryDef, setup};
use clap::Parser;
#[allow(deprecated)]
use pna::Permission;
use pna::{Archive, EntryBuilder, EntryName, WriteOptions};
use portable_network_archive::cli;
use std::fs::File;
use std::io::Write;
const ENTRY_PATH: &str = "test.txt";
const ENTRY_CONTENT: &[u8] = b"test content";
#[test]
fn archive_chmod() {
setup();
archive::create_archive_with_permissions(
"chmod.pna",
&[FileEntryDef {
path: ENTRY_PATH,
content: ENTRY_CONTENT,
permission: 0o777,
}],
)
.unwrap();
cli::Cli::try_parse_from([
"pna",
"--quiet",
"experimental",
"chmod",
"-f",
"chmod.pna",
"--",
"-x",
ENTRY_PATH,
])
.unwrap()
.execute()
.unwrap();
archive::for_each_entry("chmod.pna", |entry| {
if entry.header().path() == ENTRY_PATH {
let mode = entry
.metadata()
.permission_mode()
.expect("entry should have permission mode metadata")
.get();
assert_eq!(mode & 0o777, 0o666, "-x on 0o777 should yield 0o666");
}
})
.unwrap();
}
#[test]
#[allow(deprecated)]
fn archive_chmod_drops_legacy_fprm() {
setup();
let path = "chmod_legacy_fprm.pna";
{
let mut archive = Archive::write_header(File::create(path).unwrap()).unwrap();
let mut builder = EntryBuilder::new_file(
EntryName::from_utf8_preserve_root(ENTRY_PATH),
WriteOptions::store(),
)
.unwrap();
builder.permission(Permission::new(
1000,
"user".to_string(),
1000,
"group".to_string(),
0o777,
));
builder.write_all(ENTRY_CONTENT).unwrap();
archive.add_entry(builder.build().unwrap()).unwrap();
archive.finalize().unwrap();
}
cli::Cli::try_parse_from([
"pna",
"--quiet",
"experimental",
"chmod",
"-f",
path,
"644",
ENTRY_PATH,
])
.unwrap()
.execute()
.unwrap();
archive::for_each_entry(path, |entry| {
assert!(
entry.metadata().permission().is_none(),
"legacy fPRM must be removed after chmod"
);
assert_eq!(entry.metadata().permission_mode().unwrap().get(), 0o644);
})
.unwrap();
}
#[test]
#[allow(deprecated)]
fn archive_chmod_numeric_sets_missing_permission_mode() {
setup();
let path = "chmod_missing_mode_numeric.pna";
{
let mut archive = Archive::write_header(File::create(path).unwrap()).unwrap();
let mut builder = EntryBuilder::new_file(
EntryName::from_utf8_preserve_root(ENTRY_PATH),
WriteOptions::store(),
)
.unwrap();
builder.write_all(ENTRY_CONTENT).unwrap();
archive.add_entry(builder.build().unwrap()).unwrap();
archive.finalize().unwrap();
}
cli::Cli::try_parse_from([
"pna",
"--quiet",
"experimental",
"chmod",
"-f",
path,
"600",
ENTRY_PATH,
])
.unwrap()
.execute()
.unwrap();
archive::for_each_entry(path, |entry| {
assert!(
entry.metadata().permission().is_none(),
"legacy fPRM must not be generated by chmod"
);
assert_eq!(entry.metadata().permission_mode().unwrap().get(), 0o600);
})
.unwrap();
}
#[test]
fn archive_chmod_symbolic_uses_default_mode_for_missing_permission() {
setup();
let path = "chmod_missing_mode_symbolic.pna";
{
let mut archive = Archive::write_header(File::create(path).unwrap()).unwrap();
let mut file = EntryBuilder::new_file("file.txt".into(), WriteOptions::store()).unwrap();
file.write_all(b"file").unwrap();
archive.add_entry(file.build().unwrap()).unwrap();
archive
.add_entry(EntryBuilder::new_dir("dir".into()).build().unwrap())
.unwrap();
archive
.add_entry(
EntryBuilder::new_symlink("link.txt".into(), "file.txt".into())
.unwrap()
.build()
.unwrap(),
)
.unwrap();
archive
.add_entry(
EntryBuilder::new_hard_link("hard.txt".into(), "file.txt".into())
.unwrap()
.build()
.unwrap(),
)
.unwrap();
archive.finalize().unwrap();
}
cli::Cli::try_parse_from([
"pna",
"--quiet",
"experimental",
"chmod",
"-f",
path,
"a-r",
"file.txt",
"dir",
"link.txt",
"hard.txt",
])
.unwrap()
.execute()
.unwrap();
archive::for_each_entry(path, |entry| {
let expected = match entry.header().path().as_str() {
"dir" => 0o311,
"file.txt" | "link.txt" | "hard.txt" => 0o200,
other => panic!("unexpected entry: {other}"),
};
assert_eq!(
entry.metadata().permission_mode().unwrap().get() & 0o777,
expected
);
})
.unwrap();
}