orbis_pfs/directory/
dirent.rs1use std::io::Read;
2
3use snafu::{Snafu, ensure};
4use zerocopy::{FromBytes, Immutable, KnownLayout, little_endian::U32};
5
6#[derive(Debug, Snafu)]
8#[non_exhaustive]
9pub enum ReadError {
10 #[snafu(display("i/o failed"))]
11 IoFailed { source: std::io::Error },
12
13 #[snafu(display("data too small"))]
14 TooSmall,
15
16 #[snafu(display("end of entry"))]
17 EndOfEntry,
18}
19
20impl From<std::io::Error> for ReadError {
21 fn from(v: std::io::Error) -> Self {
22 if v.kind() == std::io::ErrorKind::UnexpectedEof {
23 ReadError::TooSmall
24 } else {
25 ReadError::IoFailed { source: v }
26 }
27 }
28}
29
30#[derive(FromBytes, KnownLayout, Immutable)]
34#[repr(C)]
35struct DirentRaw {
36 ino: U32,
37 ty: U32,
38 namelen: U32,
39 entsize: U32,
40}
41
42pub(crate) struct Dirent {
43 raw: DirentRaw,
44 name: Vec<u8>,
45}
46
47impl Dirent {
48 pub const FILE: u32 = 2;
49 pub const DIRECTORY: u32 = 3;
50 pub const SELF: u32 = 4;
51 pub const PARENT: u32 = 5;
52
53 pub fn read<F: Read>(from: &mut F) -> Result<Self, ReadError> {
54 let mut header_buf = [0u8; size_of::<DirentRaw>()];
56 from.read_exact(&mut header_buf)?;
57
58 let raw =
59 DirentRaw::read_from_bytes(&header_buf).expect("header buffer is correctly sized");
60
61 ensure!(raw.entsize.get() != 0, EndOfEntrySnafu);
62
63 let mut name = vec![0u8; raw.namelen.get() as usize];
65 from.read_exact(&mut name)?;
66
67 Ok(Self { raw, name })
68 }
69
70 pub const fn inode(&self) -> usize {
71 self.raw.ino.get() as usize
72 }
73
74 pub const fn ty(&self) -> u32 {
75 self.raw.ty.get()
76 }
77
78 pub const fn name(&self) -> &[u8] {
79 self.name.as_slice()
80 }
81
82 pub fn padding_size(&self) -> usize {
84 self.raw.entsize.get() as usize - size_of::<DirentRaw>() - self.name.len()
85 }
86}