Finish Node::extract method

This commit is contained in:
Nathan Fisher 2023-07-05 13:07:46 -04:00
parent 5fd1d09e77
commit e5cbf16064
3 changed files with 98 additions and 12 deletions

View File

@ -17,6 +17,37 @@ pub fn chown(path: &str, uid: u32, gid: u32) -> Result<(), Error> {
}
}
#[cfg(target_os = "linux")]
pub fn chmod(path: &str, mode: u32) -> Result<(), Error> {
let ret = unsafe { libc::chmod(CString::new(path)?.as_ptr(), mode) };
if ret == 0 {
Ok(())
} else {
Err(Error::Io(io::Error::last_os_error()))
}
}
#[cfg(target_os = "freebsd")]
pub fn chmod(path: &str, mode: u32) -> Result<(), Error> {
let ret = unsafe { libc::chmod(CString::new(path)?.as_ptr(), mode.try_into()?) };
if ret == 0 {
Ok(())
} else {
Err(Error::Io(io::Error::last_os_error()))
}
}
#[cfg(target_os = "linux")]
pub fn mkfifo(path: &str, mode: u32) -> Result<(), Error> {
let ret = unsafe { libc::mkfifo(CString::new(path)?.as_ptr(), mode) };
if ret == 0 {
Ok(())
} else {
Err(Error::Io(io::Error::last_os_error()))
}
}
#[cfg(target_os = "freebsd")]
pub fn mkfifo(path: &str, mode: u32) -> Result<(), Error> {
let ret = unsafe { libc::mkfifo(CString::new(path)?.as_ptr(), mode.try_into()?) };
if ret == 0 {
@ -26,6 +57,18 @@ pub fn mkfifo(path: &str, mode: u32) -> Result<(), Error> {
}
}
#[cfg(target_os = "linux")]
pub fn mknod(path: &str, mode: u32, major: u32, minor: u32) -> Result<(), Error> {
let dev = libc::makedev(major, minor);
let res = unsafe { libc::mknod(CString::new(path)?.as_ptr(), mode, dev) };
if res == 0 {
Ok(())
} else {
Err(Error::Io(io::Error::last_os_error()))
}
}
#[cfg(target_os = "freebsd")]
pub fn mknod(path: &str, mode: u32, major: u32, minor: u32) -> Result<(), Error> {
let dev = libc::makedev(major, minor);
let res = unsafe { libc::mknod(CString::new(path)?.as_ptr(), mode.try_into()?, dev) };

View File

@ -6,7 +6,7 @@ use {
std::{
collections::HashMap,
fs,
io::{BufReader, Read, Write},
io::{BufReader, BufWriter, Read, Write},
os::unix::fs::{symlink, DirBuilderExt, MetadataExt},
path::{Path, PathBuf},
sync::Mutex,
@ -156,10 +156,10 @@ impl Node {
}
let kind = Kind::from(mode);
if kind == Kind::Char {
let device = Special::from_rdev(meta.rdev().try_into()?);
let device = Special::from_rdev(meta.rdev());
break 'blk FileType::Character(device);
} else if kind == Kind::Block {
let device = Special::from_rdev(meta.rdev().try_into()?);
let device = Special::from_rdev(meta.rdev());
break 'blk FileType::Block(device);
} else if kind == Kind::Pipe {
break 'blk FileType::Fifo;
@ -225,10 +225,38 @@ impl Node {
if euid == 0 {
nix::chown(&path, self.uid, self.gid)?;
}
},
FileType::Block(ref b) => todo!(),
FileType::Character(ref c) => todo!(),
FileType::Normal(ref n) => todo!(),
}
FileType::Block(ref b) => {
if euid == 0 {
nix::mknod(&path, self.mode, b.major, b.minor)?;
}
}
FileType::Character(ref c) => {
if euid == 0 {
nix::mknod(&path, self.mode, c.major, c.minor)?;
}
}
FileType::Normal(ref n) => {
let n_path = PathBuf::from(&path);
if let Some(p) = n_path.parent() {
if !p.exists() {
self.mkdir(&p)?;
}
}
{
let fd = fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&n_path)?;
let mut writer = BufWriter::new(fd);
writer.write_all(&n.data)?;
}
if euid == 0 {
nix::chown(&path, self.uid, self.gid)?;
}
nix::chmod(&path, self.mode)?;
}
FileType::HardLink(ref t) => {
let target = if let Some(prefix) = prefix {
format!("{prefix}/{t}")
@ -236,7 +264,7 @@ impl Node {
t.to_string()
};
fs::hard_link(&target, &path)?;
},
}
FileType::SoftLink(ref t) => {
symlink(&self.name, t)?;
}
@ -253,7 +281,7 @@ impl Node {
self.mkdir(&p)?;
}
}
if !dir.exists () {
if !dir.exists() {
fs::DirBuilder::new().mode(self.mode).create(dir)?;
}
if nix::geteuid() == 0 {

View File

@ -27,10 +27,25 @@ impl Special {
Ok(())
}
pub(super) fn from_rdev(rdev: u32) -> Self {
#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
pub(super) fn from_rdev(rdev: u64) -> Self {
Self {
major: rdev >> 8,
minor: rdev & 0xff,
major: ((rdev >> 8) & 0xff) as u32,
minor: (rdev & 0xffff00ff) as u32,
}
}
#[cfg(target_os = "linux")]
pub(super) fn from_rdev(rdev: u64) -> Self {
let mut major = 0;
major |= (rdev & 0x00000000000fff00) >> 8;
major |= (rdev & 0xfffff00000000000) >> 32;
let mut minor = 0;
minor |= (rdev & 0x00000000000000ff) >> 0;
minor |= (rdev & 0x00000ffffff00000) >> 12;
Self {
major: major as u32,
minor: minor as u32,
}
}
}