Add Listing type for generating a listing of files in an archive
This commit is contained in:
parent
c2e377d09e
commit
ae7c9b08b3
@ -16,6 +16,7 @@ mod checksum;
|
||||
mod error;
|
||||
mod file;
|
||||
mod filetype;
|
||||
mod listing;
|
||||
pub(crate) mod nix;
|
||||
mod node;
|
||||
mod special;
|
||||
@ -26,6 +27,7 @@ pub use {
|
||||
error::Error,
|
||||
file::File,
|
||||
filetype::FileType,
|
||||
listing::Listing,
|
||||
node::Node,
|
||||
special::Special,
|
||||
stream::Stream,
|
||||
|
131
src/listing.rs
Normal file
131
src/listing.rs
Normal file
@ -0,0 +1,131 @@
|
||||
use {
|
||||
crate::{filetype::Flag, Error, Special},
|
||||
std::io::{Read, Seek, SeekFrom},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Kind {
|
||||
Normal(u64),
|
||||
HardLink(String),
|
||||
SoftLink(String),
|
||||
Directory,
|
||||
Character(Special),
|
||||
Block(Special),
|
||||
Fifo,
|
||||
Eof,
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
fn read<R: Read + Seek>(reader: &mut R, flag: Flag) -> Result<Self, Error> {
|
||||
match flag {
|
||||
Flag::Normal => {
|
||||
let mut len = [0; 8];
|
||||
reader.read_exact(&mut len)?;
|
||||
let len = u64::from_le_bytes(len);
|
||||
let mut buf = [0; 1];
|
||||
reader.read_exact(&mut buf)?;
|
||||
match buf[0] {
|
||||
0 => {
|
||||
let bytes = reader.seek(SeekFrom::Current(len as i64 + 16))?;
|
||||
if bytes - 16 != len {
|
||||
return Err(Error::MissingData);
|
||||
}
|
||||
}
|
||||
1 => {
|
||||
let bytes = reader.seek(SeekFrom::Current(len as i64 + 20))?;
|
||||
if bytes - 20 != len {
|
||||
return Err(Error::MissingData);
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
let bytes = reader.seek(SeekFrom::Current(len as i64 + 32))?;
|
||||
if bytes - 32 != len {
|
||||
return Err(Error::MissingData);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(Self::Normal(len))
|
||||
}
|
||||
Flag::HardLink => {
|
||||
let mut len = [0; 2];
|
||||
reader.read_exact(&mut len)?;
|
||||
let len = u16::from_le_bytes(len);
|
||||
let mut buf = Vec::with_capacity(len.into());
|
||||
let mut handle = reader.take(len.into());
|
||||
handle.read_to_end(&mut buf)?;
|
||||
let s = String::from_utf8(buf)?;
|
||||
Ok(Self::HardLink(s))
|
||||
}
|
||||
Flag::SoftLink => {
|
||||
let mut len = [0; 2];
|
||||
reader.read_exact(&mut len)?;
|
||||
let len = u16::from_le_bytes(len);
|
||||
let mut buf = Vec::with_capacity(len.into());
|
||||
let mut handle = reader.take(len.into());
|
||||
handle.read_to_end(&mut buf)?;
|
||||
let s = String::from_utf8(buf)?;
|
||||
Ok(Self::SoftLink(s))
|
||||
}
|
||||
Flag::Directory => Ok(Self::Directory),
|
||||
Flag::Character => {
|
||||
let sp = Special::read(reader)?;
|
||||
Ok(Self::Character(sp))
|
||||
}
|
||||
Flag::Block => {
|
||||
let sp = Special::read(reader)?;
|
||||
Ok(Self::Block(sp))
|
||||
}
|
||||
Flag::Fifo => Ok(Self::Fifo),
|
||||
Flag::Eof => Ok(Self::Eof),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Listing {
|
||||
pub name: String,
|
||||
pub uid: u32,
|
||||
pub gid: u32,
|
||||
pub mtime: u64,
|
||||
pub mode: u16,
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
impl Listing {
|
||||
pub fn read<R: Read + Seek>(reader: &mut R) -> Result<Self, Error> {
|
||||
let mut len = [0; 2];
|
||||
reader.read_exact(&mut len)?;
|
||||
let len = u16::from_le_bytes(len);
|
||||
if len == 0 {
|
||||
return Ok(Self {
|
||||
name: String::new(),
|
||||
mode: 0,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
mtime: 0,
|
||||
kind: Kind::Eof,
|
||||
});
|
||||
}
|
||||
let mut name = Vec::with_capacity(len.into());
|
||||
let mut handle = reader.take(len.into());
|
||||
handle.read_to_end(&mut name)?;
|
||||
let mut buf = [0; 18];
|
||||
reader.read_exact(&mut buf)?;
|
||||
let uid: [u8; 4] = buf[0..4].try_into()?;
|
||||
let gid: [u8; 4] = buf[4..8].try_into()?;
|
||||
let mtime: [u8; 8] = buf[8..16].try_into()?;
|
||||
let raw_mode: [u8; 2] = buf[16..18].try_into()?;
|
||||
let raw_mode = u16::from_le_bytes(raw_mode);
|
||||
let (flag, mode) = Flag::extract_from_raw(raw_mode)?;
|
||||
let kind = Kind::read(reader, flag)?;
|
||||
Ok(Self {
|
||||
name: String::from_utf8(name)?,
|
||||
uid: u32::from_le_bytes(uid),
|
||||
gid: u32::from_le_bytes(gid),
|
||||
mtime: u64::from_le_bytes(mtime),
|
||||
mode,
|
||||
kind,
|
||||
})
|
||||
}
|
||||
}
|
12
src/node.rs
12
src/node.rs
@ -250,9 +250,9 @@ impl Node {
|
||||
if n_path.exists() {
|
||||
fs::remove_file(&n_path)?;
|
||||
}
|
||||
nix::mkfifo(&n_path.to_str().ok_or(Error::BadPath)?, self.mode.into())?;
|
||||
nix::mkfifo(n_path.to_str().ok_or(Error::BadPath)?, self.mode.into())?;
|
||||
if euid == 0 {
|
||||
nix::chown(&n_path.to_str().ok_or(Error::BadPath)?, self.uid, self.gid)?;
|
||||
nix::chown(n_path.to_str().ok_or(Error::BadPath)?, self.uid, self.gid)?;
|
||||
}
|
||||
}
|
||||
FileType::Block(ref b) => {
|
||||
@ -261,7 +261,7 @@ impl Node {
|
||||
fs::remove_file(&n_path)?;
|
||||
}
|
||||
nix::mknod(
|
||||
&n_path.to_str().ok_or(Error::BadPath)?,
|
||||
n_path.to_str().ok_or(Error::BadPath)?,
|
||||
self.mode.into(),
|
||||
b.major,
|
||||
b.minor,
|
||||
@ -274,7 +274,7 @@ impl Node {
|
||||
fs::remove_file(&n_path)?;
|
||||
}
|
||||
nix::mknod(
|
||||
&n_path.to_str().ok_or(Error::BadPath)?,
|
||||
n_path.to_str().ok_or(Error::BadPath)?,
|
||||
self.mode.into(),
|
||||
c.major,
|
||||
c.minor,
|
||||
@ -292,9 +292,9 @@ impl Node {
|
||||
writer.write_all(&n.data)?;
|
||||
}
|
||||
if euid == 0 {
|
||||
nix::chown(&n_path.to_str().ok_or(Error::BadPath)?, self.uid, self.gid)?;
|
||||
nix::chown(n_path.to_str().ok_or(Error::BadPath)?, self.uid, self.gid)?;
|
||||
}
|
||||
nix::chmod(&n_path.to_str().ok_or(Error::BadPath)?, 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user