diff --git a/src/node.rs b/src/node.rs index 90f7c12..ab120c4 100644 --- a/src/node.rs +++ b/src/node.rs @@ -247,19 +247,38 @@ impl Node { match self.filetype { FileType::Eof => {} FileType::Fifo => { - nix::mkfifo(&path, self.mode.into())?; + if n_path.exists() { + fs::remove_file(&n_path)?; + } + nix::mkfifo(&n_path.to_str().ok_or(Error::BadPath)?, self.mode.into())?; if euid == 0 { - nix::chown(&path, self.uid, self.gid)?; + nix::chown(&n_path.to_str().ok_or(Error::BadPath)?, self.uid, self.gid)?; } } FileType::Block(ref b) => { if euid == 0 { - nix::mknod(&path, self.mode.into(), b.major, b.minor)?; + if n_path.exists() { + fs::remove_file(&n_path)?; + } + nix::mknod( + &n_path.to_str().ok_or(Error::BadPath)?, + self.mode.into(), + b.major, + b.minor, + )?; } } FileType::Character(ref c) => { if euid == 0 { - nix::mknod(&path, self.mode.into(), c.major, c.minor)?; + if n_path.exists() { + fs::remove_file(&n_path)?; + } + nix::mknod( + &n_path.to_str().ok_or(Error::BadPath)?, + self.mode.into(), + c.major, + c.minor, + )?; } } FileType::Normal(ref n) => { @@ -273,9 +292,9 @@ impl Node { writer.write_all(&n.data)?; } if euid == 0 { - nix::chown(&path, self.uid, self.gid)?; + nix::chown(&n_path.to_str().ok_or(Error::BadPath)?, self.uid, self.gid)?; } - nix::chmod(&path, self.mode.into())?; + nix::chmod(&n_path.to_str().ok_or(Error::BadPath)?, self.mode.into())?; } FileType::HardLink(ref t) => { let target = if let Some(prefix) = prefix { @@ -283,7 +302,13 @@ impl Node { } else { t.to_string() }; - fs::hard_link(target, &path)?; + if !PathBuf::from(&target).exists() { + let _f = fs::File::create(&target)?; + } + if PathBuf::from(&n_path).exists() { + fs::remove_file(&n_path)?; + } + fs::hard_link(target, &n_path)?; } FileType::SoftLink(ref t) => { if n_path.exists() { @@ -292,7 +317,7 @@ impl Node { symlink(t, &n_path)?; } FileType::Directory => { - self.mkdir(&PathBuf::from(&path))?; + self.mkdir(&n_path)?; } } Ok(()) @@ -542,4 +567,25 @@ mod tests { let tgt = fs::read_link("test/output/test/lilnk.txt").unwrap(); assert_eq!(tgt, PathBuf::from("li.txt")); } + + #[test] + fn extract_hardlink() { + let links = Mutex::new(HashMap::new()); + if !PathBuf::from("test/lihlnk.txt").exists() { + fs::hard_link("test/li.txt", "test/lihlnk.txt").unwrap(); + } + let node0 = Node::from_path("test/li.txt", Algorithm::Sha256, &links).unwrap(); + let FileType::Normal(_) = node0.filetype else { + eprintln!("Created wrong filetype for node0: {:?}", node0.filetype); + panic!(); + }; + let node1 = Node::from_path("test/lihlnk.txt", Algorithm::Sha256, &links).unwrap(); + let FileType::HardLink(ref tgt) = node1.filetype else { + eprintln!("Created wrong filetype for node1: {:?}", node1.filetype); + panic!(); + }; + assert_eq!(tgt, "test/li.txt"); + node1.extract(Some("test/output")).unwrap(); + node0.extract(Some("test/output")).unwrap(); + } }