summaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/tar.rs18
-rw-r--r--src/util/unix.rs (renamed from src/util/uid.rs)25
2 files changed, 33 insertions, 10 deletions
diff --git a/src/util/tar.rs b/src/util/tar.rs
index 885663e..1014abc 100644
--- a/src/util/tar.rs
+++ b/src/util/tar.rs
@@ -1,33 +1,35 @@
use std::{
ffi::CString,
fs::DirBuilder,
- io::{self, Read, Write},
+ io::{self, Read, Result, Write},
os::unix::ffi::OsStrExt,
path::Path,
};
+use walkdir::WalkDir;
+
+use super::unix;
pub fn pack<W: Write, P: AsRef<Path>, E: AsRef<Path>, I: Iterator<Item = E>>(
archive: W,
source: P,
entries: I,
-) -> io::Result<W> {
+) -> Result<W> {
+ let _chdir = unix::chdir(source)?;
+
let mut ar = tar::Builder::new(archive);
ar.mode(tar::HeaderMode::Deterministic);
ar.follow_symlinks(false);
for entry in entries {
- let path = source.as_ref().join(entry.as_ref());
- if path.is_dir() {
- ar.append_dir_all(entry.as_ref(), path)?;
- } else {
- ar.append_path_with_name(path, entry.as_ref())?;
+ for dir_entry in WalkDir::new(entry).sort_by_file_name() {
+ ar.append_path(dir_entry?.path())?;
}
}
ar.into_inner()
}
-pub fn unpack<R: Read, P: AsRef<Path>>(archive: R, dest: P) -> io::Result<()> {
+pub fn unpack<R: Read, P: AsRef<Path>>(archive: R, dest: P) -> Result<()> {
let dest_path = dest.as_ref();
DirBuilder::new().recursive(true).create(dest_path)?;
diff --git a/src/util/uid.rs b/src/util/unix.rs
index ee1e16b..ee0507c 100644
--- a/src/util/uid.rs
+++ b/src/util/unix.rs
@@ -1,6 +1,6 @@
-use std::{fs::File, io::Result, path::Path};
+use std::{fs::File, io::Result, os::unix::prelude::AsRawFd, path::Path};
-use nix::unistd;
+use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode, unistd};
use super::ToIOResult;
@@ -42,3 +42,24 @@ pub fn create_as<P: AsRef<Path>>(
File::create(path)
}
+
+pub struct Chdir(Dir);
+
+impl Drop for Chdir {
+ fn drop(&mut self) {
+ unistd::fchdir(self.0.as_raw_fd()).expect("failed to revert directory change");
+ }
+}
+
+pub fn chdir<P: AsRef<Path>>(path: P) -> Result<Chdir> {
+ let dir = Dir::open(
+ ".",
+ OFlag::O_PATH | OFlag::O_CLOEXEC | OFlag::O_NOFOLLOW,
+ Mode::empty(),
+ )
+ .to_io_result()?;
+
+ unistd::chdir(path.as_ref()).to_io_result()?;
+
+ Ok(Chdir(dir))
+}