2023-07-04 00:51:47 -04:00
|
|
|
use {
|
|
|
|
crate::{Error, File, Special},
|
|
|
|
std::io::{Read, Write},
|
|
|
|
};
|
|
|
|
|
2023-07-15 12:05:24 -04:00
|
|
|
#[repr(u8)]
|
2023-07-15 11:36:21 -04:00
|
|
|
pub(crate) enum Flag {
|
2023-07-15 12:05:24 -04:00
|
|
|
Normal = 0,
|
|
|
|
HardLink = 1,
|
|
|
|
SoftLink = 2,
|
|
|
|
Directory = 3,
|
|
|
|
Character = 4,
|
|
|
|
Block = 5,
|
|
|
|
Fifo = 6,
|
|
|
|
Eof = 7,
|
2023-07-15 11:36:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TryFrom<u8> for Flag {
|
|
|
|
type Error = Error;
|
|
|
|
|
|
|
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
|
|
|
match value {
|
|
|
|
0 => Ok(Self::Normal),
|
|
|
|
1 => Ok(Self::HardLink),
|
|
|
|
2 => Ok(Self::SoftLink),
|
|
|
|
3 => Ok(Self::Directory),
|
|
|
|
4 => Ok(Self::Character),
|
|
|
|
5 => Ok(Self::Block),
|
|
|
|
6 => Ok(Self::Fifo),
|
|
|
|
7 => Ok(Self::Eof),
|
|
|
|
8 => Err(Error::UnknownFileType),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-15 12:05:24 -04:00
|
|
|
impl From<&FileType> for Flag {
|
|
|
|
fn from(value: &FileType) -> Self {
|
|
|
|
match value {
|
|
|
|
FileType::Normal(_) => Self::Normal,
|
|
|
|
FileType::HardLink(_) => Self::HardLink,
|
|
|
|
FileType::SoftLink(_) => Self::SoftLink,
|
|
|
|
FileType::Directory => Self::Directory,
|
|
|
|
FileType::Character(_) => Self::Character,
|
|
|
|
FileType::Block(_) => Self::Block,
|
|
|
|
FileType::Fifo => Self::Fifo,
|
|
|
|
FileType::Eof => Self::Eof,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Flag {
|
|
|
|
pub(crate) fn append_mode(&self, mode: u16) -> u16 {
|
|
|
|
let mask: u16 = u16::from(*self as u8) << 13;
|
|
|
|
mode & mask
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-04 20:13:38 -04:00
|
|
|
/// An enum representing the type of file of an archive member
|
2023-07-04 00:51:47 -04:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum FileType {
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A normal file and it's contained data
|
2023-07-04 00:51:47 -04:00
|
|
|
Normal(File),
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A hard link to another file in this archive
|
2023-07-04 00:51:47 -04:00
|
|
|
HardLink(String),
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A soft link to another file
|
2023-07-04 00:51:47 -04:00
|
|
|
SoftLink(String),
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A directory inode
|
2023-07-04 00:51:47 -04:00
|
|
|
Directory,
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A character (buffered) device
|
2023-07-04 00:51:47 -04:00
|
|
|
Character(Special),
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A block device
|
2023-07-04 00:51:47 -04:00
|
|
|
Block(Special),
|
2023-07-04 20:13:38 -04:00
|
|
|
/// A Unix named pipe (fifo)
|
2023-07-04 00:51:47 -04:00
|
|
|
Fifo,
|
2023-07-05 00:25:31 -04:00
|
|
|
/// End of archive
|
|
|
|
Eof,
|
2023-07-04 00:51:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FileType {
|
2023-07-15 11:36:21 -04:00
|
|
|
pub(crate) fn read<T: Read>(reader: &mut T, flag: Flag) -> Result<Self, Error> {
|
|
|
|
match flag {
|
|
|
|
Flag::Normal => {
|
2023-07-04 00:51:47 -04:00
|
|
|
let file = File::read(reader)?;
|
|
|
|
Ok(Self::Normal(file))
|
|
|
|
}
|
2023-07-15 11:36:21 -04:00
|
|
|
Flag::HardLink => {
|
|
|
|
let mut len = [0; 2];
|
2023-07-04 00:51:47 -04:00
|
|
|
reader.read_exact(&mut len)?;
|
2023-07-15 11:36:21 -04:00
|
|
|
let len = u16::from_le_bytes(len);
|
|
|
|
let mut buf = Vec::with_capacity(len.into());
|
|
|
|
let mut handle = reader.take(len.into());
|
2023-07-04 00:51:47 -04:00
|
|
|
handle.read_exact(&mut buf)?;
|
|
|
|
let s = String::from_utf8(buf)?;
|
|
|
|
Ok(Self::HardLink(s))
|
|
|
|
}
|
2023-07-15 11:36:21 -04:00
|
|
|
Flag::SoftLink => {
|
|
|
|
let mut len = [0; 2];
|
2023-07-04 00:51:47 -04:00
|
|
|
reader.read_exact(&mut len)?;
|
2023-07-15 11:36:21 -04:00
|
|
|
let len = u16::from_le_bytes(len);
|
|
|
|
let mut buf = Vec::with_capacity(len.into());
|
|
|
|
let mut handle = reader.take(len.into());
|
2023-07-04 00:51:47 -04:00
|
|
|
handle.read_exact(&mut buf)?;
|
|
|
|
let s = String::from_utf8(buf)?;
|
|
|
|
Ok(Self::SoftLink(s))
|
|
|
|
}
|
2023-07-15 11:36:21 -04:00
|
|
|
Flag::Directory => Ok(Self::Directory),
|
|
|
|
Flag::Character => {
|
2023-07-04 00:51:47 -04:00
|
|
|
let sp = Special::read(reader)?;
|
|
|
|
Ok(Self::Character(sp))
|
|
|
|
}
|
2023-07-15 11:36:21 -04:00
|
|
|
Flag::Block => {
|
2023-07-04 00:51:47 -04:00
|
|
|
let sp = Special::read(reader)?;
|
|
|
|
Ok(Self::Block(sp))
|
|
|
|
}
|
2023-07-15 11:36:21 -04:00
|
|
|
Flag::Fifo => Ok(Self::Fifo),
|
|
|
|
Flag::Eof => Ok(Self::Eof),
|
2023-07-04 00:51:47 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-05 13:35:37 -04:00
|
|
|
pub(crate) fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
|
2023-07-04 00:51:47 -04:00
|
|
|
match self {
|
|
|
|
Self::Normal(f) => {
|
|
|
|
writer.write_all(&[0])?;
|
|
|
|
f.write(writer)?;
|
|
|
|
}
|
|
|
|
Self::HardLink(s) => {
|
|
|
|
writer.write_all(&[1])?;
|
|
|
|
let len = s.len() as u64;
|
|
|
|
writer.write_all(&len.to_le_bytes())?;
|
|
|
|
writer.write_all(s.as_bytes())?;
|
|
|
|
}
|
|
|
|
Self::SoftLink(s) => {
|
|
|
|
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])?,
|
2023-07-05 00:25:31 -04:00
|
|
|
Self::Eof => {}
|
2023-07-04 00:51:47 -04:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|