Finish from_path for Node

This commit is contained in:
Nathan Fisher 2023-07-03 23:37:57 -04:00
parent 2c8d05b9f8
commit 162e027365

View File

@ -4,12 +4,13 @@ use {
sha2::Sha256, sha2::Sha256,
std::{ std::{
array::TryFromSliceError, array::TryFromSliceError,
collections::HashMap,
fmt, fs, fmt, fs,
io::{self, BufRead, BufReader, Read, Write}, io::{self, BufReader, Read, Write},
num::TryFromIntError, num::TryFromIntError,
os::unix::fs::MetadataExt, os::unix::fs::MetadataExt,
path::PathBuf,
string::FromUtf8Error, string::FromUtf8Error,
sync::Mutex,
}, },
}; };
@ -100,6 +101,13 @@ impl Special {
writer.write_all(&self.minor.to_le_bytes())?; writer.write_all(&self.minor.to_le_bytes())?;
Ok(()) Ok(())
} }
fn from_rdev(rdev: u32) -> Self {
Self {
major: rdev >> 8,
minor: rdev & 0xff,
}
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -249,7 +257,7 @@ impl FileType {
0 => { 0 => {
let file = File::read(reader)?; let file = File::read(reader)?;
Ok(Self::Normal(file)) Ok(Self::Normal(file))
}, }
1 => { 1 => {
let mut len = [0; 8]; let mut len = [0; 8];
reader.read_exact(&mut len)?; reader.read_exact(&mut len)?;
@ -289,7 +297,7 @@ impl FileType {
Self::Normal(f) => { Self::Normal(f) => {
writer.write_all(&[0])?; writer.write_all(&[0])?;
f.write(writer)?; f.write(writer)?;
}, }
Self::HardLink(s) => { Self::HardLink(s) => {
writer.write_all(&[1])?; writer.write_all(&[1])?;
let len = s.len() as u64; let len = s.len() as u64;
@ -317,7 +325,7 @@ impl FileType {
} }
} }
#[derive(Debug)] #[derive(Debug, PartialEq)]
enum Kind { enum Kind {
Normal, Normal,
Dir, Dir,
@ -391,31 +399,92 @@ impl Node {
Ok(()) Ok(())
} }
/*pub fn from_path(path: &str) -> Result<Self, Error> { pub fn from_path(
path: &str,
checksum: Checksum,
links: Mutex<HashMap<u64, String>>,
) -> Result<Self, Error> {
let name = String::from(path); let name = String::from(path);
let mut fd = fs::File::open(path)?; let fd = fs::File::open(path)?;
let meta = fd.metadata()?; let meta = fd.metadata()?;
let mode = meta.mode(); let mode = meta.mode();
let uid = meta.uid(); let uid = meta.uid();
let gid = meta.gid(); let gid = meta.gid();
let mtime = meta.mtime(); let mtime = meta.mtime().try_into()?;
let mut reader = BufReader::new(fd); let mut reader = BufReader::new(fd);
let ft = meta.file_type(); let ft = meta.file_type();
let filetype = if ft.is_dir() { let filetype = 'blk: {
FileType::Directory if ft.is_dir() {
} else if ft.is_symlink() { FileType::Directory
let target = fs::read_link(path)?; } else if ft.is_symlink() {
let target = target let target = fs::read_link(path)?;
.to_str() let target = target
.ok_or(Error::Other("bad path".to_string()))? .to_str()
.to_string(); .ok_or(Error::Other("bad path".to_string()))?
FileType::SoftLink(target) .to_string();
} else if mode & 0o20000 != 0 { FileType::SoftLink(target)
let rdev = meta.rdev(); } else {
if rdev != 0 { if meta.nlink() > 1 {
if let Ok(mut list) = links.lock() {
let inode = meta.ino();
if let Some(target) = list.get(&inode).cloned() {
break 'blk FileType::HardLink(target);
} else {
list.insert(inode, name.clone());
}
}
}
let kind = Kind::from(mode);
if kind == Kind::Char {
let device = Special::from_rdev(meta.rdev().try_into()?);
break 'blk FileType::Character(device);
} else if kind == Kind::Block {
let device = Special::from_rdev(meta.rdev().try_into()?);
break 'blk FileType::Block(device);
} else if kind == Kind::Pipe {
break 'blk FileType::Fifo;
} else if kind == Kind::Normal {
let mut len = meta.len();
let mut data = Vec::with_capacity(len.try_into()?);
len = reader.read_to_end(&mut data)?.try_into()?;
let checksum = match checksum {
Checksum::Md5(mut cs) => {
let mut hasher = Md5::new();
hasher.update(&data);
cs = hasher.finalize().into();
Checksum::Md5(cs)
}
Checksum::Sha1(mut cs) => {
let mut hasher = Sha1::new();
hasher.update(&data);
cs = hasher.finalize().into();
Checksum::Sha1(cs)
}
Checksum::Sha256(mut cs) => {
let mut hasher = Sha256::new();
hasher.update(&data);
cs = hasher.finalize().into();
Checksum::Sha256(cs)
}
Checksum::Skip => checksum,
};
break 'blk FileType::Normal(File {
len,
checksum,
data,
});
} else {
return Err(Error::UnknownFileType);
}
} }
todo!()
}; };
todo!() Ok(Self {
}*/ name,
mode,
uid,
gid,
mtime,
filetype,
})
}
} }