Add ability to override uid/gid when creating an archive

This commit is contained in:
Nathan Fisher 2024-01-19 00:26:54 -05:00
parent 1740dcb79c
commit 3269da7fe8
2 changed files with 30 additions and 6 deletions

View File

@ -36,6 +36,6 @@ to see Haggis implemented in other languages.
## Roadmap ## Roadmap
- [x] Create and extract archives - [x] Create and extract archives
- [x] List archive nodes - [x] List archive nodes
- [ ] Override user/group when creating archives - [x] Override user/group when creating archives
- [x] Override user/group when extracting archives - [x] Override user/group when extracting archives
- [ ] Automatically detect zstd compressed archives - [ ] Automatically detect zstd compressed archives

View File

@ -44,13 +44,19 @@ pub static MAGIC: [u8; 7] = [0x89, b'h', b'a', b'g', b'g', b'i', b's'];
/// Creates a haggis archive from a list of files /// Creates a haggis archive from a list of files
/// # Errors /// # Errors
/// Returns `crate::Error` if io fails or several other error conditions /// Returns `crate::Error` if io fails or several other error conditions
pub fn create_archive(path: &str, files: &[String], algorithm: Algorithm) -> Result<(), Error> { pub fn create_archive(
path: &str,
files: &[String],
algorithm: Algorithm,
uid: Option<u32>,
gid: Option<u32>,
) -> Result<(), Error> {
let fd = fs::OpenOptions::new() let fd = fs::OpenOptions::new()
.create(true) .create(true)
.truncate(true) .truncate(true)
.open(path)?; .open(path)?;
let mut writer = BufWriter::new(fd); let mut writer = BufWriter::new(fd);
stream_archive(&mut writer, files, algorithm)?; stream_archive(&mut writer, files, algorithm, uid, gid)?;
Ok(()) Ok(())
} }
@ -61,13 +67,21 @@ pub fn stream_archive<W: Write>(
mut writer: W, mut writer: W,
files: &[String], files: &[String],
algorithm: Algorithm, algorithm: Algorithm,
uid: Option<u32>,
gid: Option<u32>,
) -> Result<(), Error> { ) -> Result<(), Error> {
writer.write_all(&MAGIC)?; writer.write_all(&MAGIC)?;
let len = u32::try_from(files.len())?; let len = u32::try_from(files.len())?;
writer.write_all(&len.to_le_bytes())?; writer.write_all(&len.to_le_bytes())?;
let links = Mutex::new(HashMap::new()); let links = Mutex::new(HashMap::new());
for f in files { for f in files {
let node = Node::from_path(f, algorithm, &links)?; let mut node = Node::from_path(f, algorithm, &links)?;
if let Some(n) = uid {
node.uid = n;
}
if let Some(n) = gid {
node.gid = n;
}
node.write(&mut writer)?; node.write(&mut writer)?;
} }
writer.write_all(&[0; 8])?; writer.write_all(&[0; 8])?;
@ -95,10 +109,12 @@ pub fn par_create_archive(
files: &[String], files: &[String],
algorithm: Algorithm, algorithm: Algorithm,
sender: &Sender<Message>, sender: &Sender<Message>,
uid: Option<u32>,
gid: Option<u32>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let fd = fs::File::create(path)?; let fd = fs::File::create(path)?;
let writer = BufWriter::new(fd); let writer = BufWriter::new(fd);
par_stream_archive(writer, files, algorithm, sender)?; par_stream_archive(writer, files, algorithm, sender, uid, gid)?;
Ok(()) Ok(())
} }
@ -111,6 +127,8 @@ pub fn par_stream_archive<W: Write + Send>(
files: &[String], files: &[String],
algorithm: Algorithm, algorithm: Algorithm,
sender: &Sender<Message>, sender: &Sender<Message>,
uid: Option<u32>,
gid: Option<u32>,
) -> Result<(), Error> { ) -> Result<(), Error> {
writer.write_all(&MAGIC)?; writer.write_all(&MAGIC)?;
let len = u32::try_from(files.len())?; let len = u32::try_from(files.len())?;
@ -119,13 +137,19 @@ pub fn par_stream_archive<W: Write + Send>(
let writer = Mutex::new(writer); let writer = Mutex::new(writer);
let s = sender.clone(); let s = sender.clone();
files.par_iter().try_for_each_with(s, |s, f| { files.par_iter().try_for_each_with(s, |s, f| {
let node = match Node::from_path(f, algorithm, &links) { let mut node = match Node::from_path(f, algorithm, &links) {
Ok(n) => n, Ok(n) => n,
Err(e) => { Err(e) => {
s.send(Message::Err(e)).map_err(|_| Error::SenderError)?; s.send(Message::Err(e)).map_err(|_| Error::SenderError)?;
return Ok(()); return Ok(());
} }
}; };
if let Some(n) = uid {
node.uid = n;
}
if let Some(n) = gid {
node.gid = n;
}
if let Ok(mut writer) = writer.lock() { if let Ok(mut writer) = writer.lock() {
let mut writer = &mut *writer; let mut writer = &mut *writer;
if let Err(e) = node.write(&mut writer) { if let Err(e) = node.write(&mut writer) {