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 error;
|
||||||
mod file;
|
mod file;
|
||||||
mod filetype;
|
mod filetype;
|
||||||
|
mod listing;
|
||||||
pub(crate) mod nix;
|
pub(crate) mod nix;
|
||||||
mod node;
|
mod node;
|
||||||
mod special;
|
mod special;
|
||||||
@ -26,6 +27,7 @@ pub use {
|
|||||||
error::Error,
|
error::Error,
|
||||||
file::File,
|
file::File,
|
||||||
filetype::FileType,
|
filetype::FileType,
|
||||||
|
listing::Listing,
|
||||||
node::Node,
|
node::Node,
|
||||||
special::Special,
|
special::Special,
|
||||||
stream::Stream,
|
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() {
|
if n_path.exists() {
|
||||||
fs::remove_file(&n_path)?;
|
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 {
|
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) => {
|
FileType::Block(ref b) => {
|
||||||
@ -261,7 +261,7 @@ impl Node {
|
|||||||
fs::remove_file(&n_path)?;
|
fs::remove_file(&n_path)?;
|
||||||
}
|
}
|
||||||
nix::mknod(
|
nix::mknod(
|
||||||
&n_path.to_str().ok_or(Error::BadPath)?,
|
n_path.to_str().ok_or(Error::BadPath)?,
|
||||||
self.mode.into(),
|
self.mode.into(),
|
||||||
b.major,
|
b.major,
|
||||||
b.minor,
|
b.minor,
|
||||||
@ -274,7 +274,7 @@ impl Node {
|
|||||||
fs::remove_file(&n_path)?;
|
fs::remove_file(&n_path)?;
|
||||||
}
|
}
|
||||||
nix::mknod(
|
nix::mknod(
|
||||||
&n_path.to_str().ok_or(Error::BadPath)?,
|
n_path.to_str().ok_or(Error::BadPath)?,
|
||||||
self.mode.into(),
|
self.mode.into(),
|
||||||
c.major,
|
c.major,
|
||||||
c.minor,
|
c.minor,
|
||||||
@ -292,9 +292,9 @@ impl Node {
|
|||||||
writer.write_all(&n.data)?;
|
writer.write_all(&n.data)?;
|
||||||
}
|
}
|
||||||
if euid == 0 {
|
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) => {
|
FileType::HardLink(ref t) => {
|
||||||
let target = if let Some(prefix) = prefix {
|
let target = if let Some(prefix) = prefix {
|
||||||
|
Loading…
Reference in New Issue
Block a user