Finish (probably) port to new spec and add more tests

This commit is contained in:
Nathan Fisher 2023-07-16 01:15:15 -04:00
parent 1bf8fd416a
commit 3b46b11153
11 changed files with 135 additions and 43 deletions

Binary file not shown.

View File

@ -87,3 +87,57 @@ impl Checksum {
Ok(()) Ok(())
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File;
const MD5BUF: [u8; 16] = [
102, 95, 170, 95, 1, 29, 157, 44, 184, 244, 181, 209, 47, 30, 223, 21,
];
const SHA1BUF: [u8; 20] = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
];
#[test]
fn load_store_md5() {
{
let mut fd = File::options()
.create(true)
.truncate(true)
.write(true)
.open("test/md5")
.unwrap();
let cksum = Checksum::Md5(MD5BUF);
cksum.write(&mut fd).unwrap();
}
let mut fd = File::open("test/md5").unwrap();
let cksum = Checksum::read(&mut fd).unwrap();
match cksum {
Checksum::Md5(sum) => assert_eq!(sum, MD5BUF),
_ => unreachable!(),
}
}
#[test]
fn load_store_sha1() {
{
let mut fd = File::options()
.create(true)
.truncate(true)
.write(true)
.open("test/sha1")
.unwrap();
let cksum = Checksum::Sha1(SHA1BUF);
cksum.write(&mut fd).unwrap();
}
let mut fd = File::open("test/sha1").unwrap();
let cksum = Checksum::read(&mut fd).unwrap();
match cksum {
Checksum::Sha1(sum) => assert_eq!(sum, SHA1BUF),
_ => unreachable!(),
}
}
}

View File

@ -84,3 +84,35 @@ impl File {
Ok(()) Ok(())
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File as Fd;
const SHA1BUF: [u8; 20] = [
155, 243, 229, 181, 239, 210, 47, 147, 46, 16, 11, 134, 200, 52, 130, 120, 126, 130, 166,
130,
];
#[test]
fn load_store() {
let file = File {
len: 1005,
checksum: Checksum::Sha1(SHA1BUF),
data: include_bytes!("../test/li.txt").to_vec(),
};
{
let mut fd = Fd::create("test/file").unwrap();
file.write(&mut fd).unwrap();
}
let mut fd = Fd::open("test/file").unwrap();
let res = File::read(&mut fd).unwrap();
assert_eq!(file.len, res.len);
assert_eq!(&file.data, &res.data);
match res.checksum {
Checksum::Sha1(sum) => assert_eq!(sum, SHA1BUF),
_ => unreachable!(),
}
}
}

View File

@ -4,6 +4,7 @@ use {
}; };
#[repr(u8)] #[repr(u8)]
#[derive(Clone, Copy)]
pub(crate) enum Flag { pub(crate) enum Flag {
Normal = 0, Normal = 0,
HardLink = 1, HardLink = 1,
@ -28,7 +29,7 @@ impl TryFrom<u8> for Flag {
5 => Ok(Self::Block), 5 => Ok(Self::Block),
6 => Ok(Self::Fifo), 6 => Ok(Self::Fifo),
7 => Ok(Self::Eof), 7 => Ok(Self::Eof),
8 => Err(Error::UnknownFileType), _ => Err(Error::UnknownFileType),
} }
} }
} }
@ -119,33 +120,14 @@ impl FileType {
pub(crate) fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> { pub(crate) fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
match self { match self {
Self::Normal(f) => { Self::Normal(f) => f.write(writer)?,
writer.write_all(&[0])?; Self::HardLink(s) | Self::SoftLink(s) => {
f.write(writer)?;
}
Self::HardLink(s) => {
writer.write_all(&[1])?;
let len = s.len() as u64; let len = s.len() as u64;
writer.write_all(&len.to_le_bytes())?; writer.write_all(&len.to_le_bytes())?;
writer.write_all(s.as_bytes())?; writer.write_all(s.as_bytes())?;
} }
Self::SoftLink(s) => { Self::Character(s) | Self::Block(s) => s.write(writer)?,
writer.write_all(&[2])?; _ => {}
let len = s.len() as u64;
writer.write_all(&len.to_le_bytes())?;
writer.write_all(s.as_bytes())?;
}
Self::Directory => writer.write_all(&[3])?,
Self::Character(s) => {
writer.write_all(&[4])?;
s.write(writer)?;
}
Self::Block(s) => {
writer.write_all(&[5])?;
s.write(writer)?;
}
Self::Fifo => writer.write_all(&[6])?,
Self::Eof => {}
} }
Ok(()) Ok(())
} }

View File

@ -108,9 +108,8 @@ impl Node {
let len: u16 = self.name.len().try_into()?; let len: u16 = self.name.len().try_into()?;
writer.write_all(&len.to_le_bytes())?; writer.write_all(&len.to_le_bytes())?;
writer.write_all(self.name.as_bytes())?; writer.write_all(self.name.as_bytes())?;
[self.uid, self.gid] writer.write_all(&self.uid.to_le_bytes())?;
.iter() writer.write_all(&self.gid.to_le_bytes())?;
.try_for_each(|f| writer.write_all(&f.to_le_bytes()))?;
writer.write_all(&self.mtime.to_le_bytes())?; writer.write_all(&self.mtime.to_le_bytes())?;
let mode = Flag::from(&self.filetype).append_mode(self.mode); let mode = Flag::from(&self.filetype).append_mode(self.mode);
writer.write_all(&mode.to_le_bytes())?; writer.write_all(&mode.to_le_bytes())?;
@ -207,10 +206,10 @@ impl Node {
}; };
Ok(Self { Ok(Self {
name, name,
mode,
uid, uid,
gid, gid,
mtime, mtime,
mode: (mode & !(0o111 << 13)).try_into()?,
filetype, filetype,
}) })
} }
@ -246,19 +245,19 @@ impl Node {
match self.filetype { match self.filetype {
FileType::Eof => {} FileType::Eof => {}
FileType::Fifo => { FileType::Fifo => {
nix::mkfifo(&path, self.mode)?; nix::mkfifo(&path, self.mode.into())?;
if euid == 0 { if euid == 0 {
nix::chown(&path, self.uid, self.gid)?; nix::chown(&path, self.uid, self.gid)?;
} }
} }
FileType::Block(ref b) => { FileType::Block(ref b) => {
if euid == 0 { if euid == 0 {
nix::mknod(&path, self.mode, b.major, b.minor)?; nix::mknod(&path, self.mode.into(), b.major, b.minor)?;
} }
} }
FileType::Character(ref c) => { FileType::Character(ref c) => {
if euid == 0 { if euid == 0 {
nix::mknod(&path, self.mode, c.major, c.minor)?; nix::mknod(&path, self.mode.into(), c.major, c.minor)?;
} }
} }
FileType::Normal(ref n) => { FileType::Normal(ref n) => {
@ -274,7 +273,7 @@ impl Node {
if euid == 0 { if euid == 0 {
nix::chown(&path, self.uid, self.gid)?; nix::chown(&path, self.uid, self.gid)?;
} }
nix::chmod(&path, self.mode)?; nix::chmod(&path, self.mode.into())?;
} }
FileType::HardLink(ref t) => { FileType::HardLink(ref t) => {
let target = if let Some(prefix) = prefix { let target = if let Some(prefix) = prefix {
@ -303,7 +302,7 @@ impl Node {
} }
nix::chmod( nix::chmod(
dir.to_str().ok_or(Error::BadPath)?, dir.to_str().ok_or(Error::BadPath)?,
self.mode & 0o7777 | 0o100, (self.mode & 0o7777 | 0o100).into(),
)?; )?;
Ok(()) Ok(())
} }
@ -334,16 +333,14 @@ mod tests {
} }
#[test] #[test]
fn write() { fn load_store() {
{
let fd = std::fs::File::create("test/li.node").unwrap(); let fd = std::fs::File::create("test/li.node").unwrap();
let mut writer = std::io::BufWriter::new(fd); let mut writer = std::io::BufWriter::new(fd);
let links = Mutex::new(HashMap::new()); let links = Mutex::new(HashMap::new());
let node = Node::from_path("test/li.txt", Algorithm::Sha1, &links).unwrap(); let node = Node::from_path("test/li.txt", Algorithm::Sha1, &links).unwrap();
node.write(&mut writer).unwrap(); node.write(&mut writer).unwrap();
} }
#[test]
fn read() {
let fd = std::fs::File::open("test/li.node").unwrap(); let fd = std::fs::File::open("test/li.node").unwrap();
let mut reader = BufReader::new(fd); let mut reader = BufReader::new(fd);
let node = Node::read(&mut reader).unwrap(); let node = Node::read(&mut reader).unwrap();

View File

@ -49,3 +49,30 @@ impl Special {
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File;
#[test]
fn load_store() {
{
let mut fd = File::options()
.write(true)
.create(true)
.truncate(true)
.open("test/device")
.unwrap();
let dev = Special {
major: 42,
minor: 69,
};
dev.write(&mut fd).unwrap();
}
let mut fd = File::open("test/device").unwrap();
let dev = Special::read(&mut fd).unwrap();
assert_eq!(dev.major, 42);
assert_eq!(dev.minor, 69);
}
}

BIN
test/device Normal file

Binary file not shown.

BIN
test/file Normal file

Binary file not shown.

Binary file not shown.

BIN
test/md5 Normal file

Binary file not shown.

BIN
test/sha1 Normal file

Binary file not shown.