squashfs_async/inodes/
directory.rs

1use serde::Deserialize;
2
3use super::super::deser::{self, from_reader};
4use super::super::error::InodeTableError;
5
6/// Location in the directory table.
7#[derive(Default, Debug, Clone)]
8pub struct DirectoryTableLocation {
9    pub start: u64,
10    pub offset: u64,
11    pub file_size: u64,
12}
13/// Trait to encompass `BasicDirectory` and `ExtendedDirectory`
14pub trait DirectoryInode: std::fmt::Debug {
15    fn hard_link_count(&self) -> u32;
16    fn parent_inode_number(&self) -> u32;
17    fn table_location(&self) -> DirectoryTableLocation;
18}
19#[derive(Debug, Default, Deserialize)]
20pub struct BasicDirectory {
21    dir_block_start: u32,
22    hard_link_count: u32,
23    file_size: u16,
24    block_offset: u16,
25    parent_inode_number: u32,
26}
27from_reader!(BasicDirectory, 16);
28impl DirectoryInode for BasicDirectory {
29    fn hard_link_count(&self) -> u32 {
30        self.hard_link_count
31    }
32    fn parent_inode_number(&self) -> u32 {
33        self.parent_inode_number
34    }
35    fn table_location(&self) -> DirectoryTableLocation {
36        DirectoryTableLocation {
37            start: self.dir_block_start as u64,
38            offset: self.block_offset as u64,
39            file_size: self.file_size as u64,
40        }
41    }
42}
43
44#[derive(Debug, Default, Deserialize)]
45struct DirectoryIndex {
46    _index: u32,
47    _start: u32,
48    name_size: u32,
49    #[serde(skip)]
50    name: String,
51}
52impl DirectoryIndex {
53    pub async fn from_reader(mut r: impl crate::AsyncRead) -> Result<Self, InodeTableError> {
54        let mut index: Self = deser::bincode_deser_from(&mut r, 12)
55            .await
56            .map_err(|_| InodeTableError::InvalidEntry)?;
57        index.name = deser::bincode_deser_string_from(r, index.name_size as usize + 1)
58            .await
59            .map_err(|_| InodeTableError::InvalidEntry)?;
60        Ok(index)
61    }
62}
63
64#[derive(Debug, Default, Deserialize)]
65pub struct ExtendedDirectory {
66    hard_link_count: u32,
67    file_size: u32,
68    dir_block_start: u32,
69    parent_inode_number: u32,
70    index_count: u16,
71    block_offset: u16,
72    _xattr_idx: u32,
73    #[serde(skip)]
74    index: Vec<DirectoryIndex>,
75}
76impl DirectoryInode for ExtendedDirectory {
77    fn hard_link_count(&self) -> u32 {
78        self.hard_link_count
79    }
80    fn parent_inode_number(&self) -> u32 {
81        self.parent_inode_number
82    }
83    fn table_location(&self) -> DirectoryTableLocation {
84        DirectoryTableLocation {
85            start: self.dir_block_start as u64,
86            offset: self.block_offset as u64,
87            file_size: self.file_size as u64,
88        }
89    }
90}
91impl ExtendedDirectory {
92    pub async fn from_reader(mut r: impl crate::AsyncRead) -> Result<Self, InodeTableError> {
93        let mut dir: Self = deser::bincode_deser_from(&mut r, 24)
94            .await
95            .map_err(|_| InodeTableError::InvalidEntry)?;
96        for _ in 0..dir.index_count {
97            dir.index.push(DirectoryIndex::from_reader(&mut r).await?);
98        }
99        Ok(dir)
100    }
101}