1use bitflags::bitflags;
4use ext4_lwext4_sys;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub enum FsType {
9 Ext2,
11 Ext3,
13 #[default]
15 Ext4,
16}
17
18impl FsType {
19 pub(crate) fn to_raw(self) -> i32 {
21 match self {
22 FsType::Ext2 => ext4_lwext4_sys::F_SET_EXT2,
23 FsType::Ext3 => ext4_lwext4_sys::F_SET_EXT3,
24 FsType::Ext4 => ext4_lwext4_sys::F_SET_EXT4,
25 }
26 }
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum FileType {
32 RegularFile,
34 Directory,
36 Symlink,
38 BlockDevice,
40 CharDevice,
42 Fifo,
44 Socket,
46 Unknown,
48}
49
50impl FileType {
51 pub(crate) fn from_raw(raw: u8) -> Self {
53 match raw {
54 ext4_lwext4_sys::EXT4_DE_REG_FILE => FileType::RegularFile,
55 ext4_lwext4_sys::EXT4_DE_DIR => FileType::Directory,
56 ext4_lwext4_sys::EXT4_DE_SYMLINK => FileType::Symlink,
57 ext4_lwext4_sys::EXT4_DE_BLKDEV => FileType::BlockDevice,
58 ext4_lwext4_sys::EXT4_DE_CHRDEV => FileType::CharDevice,
59 ext4_lwext4_sys::EXT4_DE_FIFO => FileType::Fifo,
60 ext4_lwext4_sys::EXT4_DE_SOCK => FileType::Socket,
61 _ => FileType::Unknown,
62 }
63 }
64
65 pub(crate) fn to_raw(self) -> u8 {
67 match self {
68 FileType::RegularFile => ext4_lwext4_sys::EXT4_DE_REG_FILE,
69 FileType::Directory => ext4_lwext4_sys::EXT4_DE_DIR,
70 FileType::Symlink => ext4_lwext4_sys::EXT4_DE_SYMLINK,
71 FileType::BlockDevice => ext4_lwext4_sys::EXT4_DE_BLKDEV,
72 FileType::CharDevice => ext4_lwext4_sys::EXT4_DE_CHRDEV,
73 FileType::Fifo => ext4_lwext4_sys::EXT4_DE_FIFO,
74 FileType::Socket => ext4_lwext4_sys::EXT4_DE_SOCK,
75 FileType::Unknown => ext4_lwext4_sys::EXT4_DE_UNKNOWN,
76 }
77 }
78
79 pub fn is_file(&self) -> bool {
81 matches!(self, FileType::RegularFile)
82 }
83
84 pub fn is_dir(&self) -> bool {
86 matches!(self, FileType::Directory)
87 }
88
89 pub fn is_symlink(&self) -> bool {
91 matches!(self, FileType::Symlink)
92 }
93}
94
95bitflags! {
96 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
98 pub struct OpenFlags: u32 {
99 const READ = 0b0000_0001;
101 const WRITE = 0b0000_0010;
103 const CREATE = 0b0000_0100;
105 const TRUNCATE = 0b0000_1000;
107 const APPEND = 0b0001_0000;
109 const EXCLUSIVE = 0b0010_0000;
111 }
112}
113
114impl OpenFlags {
115 pub(crate) fn to_raw(self) -> i32 {
117 let mut flags = 0i32;
118
119 if self.contains(OpenFlags::READ) && self.contains(OpenFlags::WRITE) {
120 flags |= ext4_lwext4_sys::O_RDWR;
121 } else if self.contains(OpenFlags::WRITE) {
122 flags |= ext4_lwext4_sys::O_WRONLY;
123 } else {
124 flags |= ext4_lwext4_sys::O_RDONLY;
125 }
126
127 if self.contains(OpenFlags::CREATE) {
128 flags |= ext4_lwext4_sys::O_CREAT;
129 }
130 if self.contains(OpenFlags::TRUNCATE) {
131 flags |= ext4_lwext4_sys::O_TRUNC;
132 }
133 if self.contains(OpenFlags::APPEND) {
134 flags |= ext4_lwext4_sys::O_APPEND;
135 }
136 if self.contains(OpenFlags::EXCLUSIVE) {
137 flags |= ext4_lwext4_sys::O_EXCL;
138 }
139
140 flags
141 }
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq)]
146pub enum SeekFrom {
147 Start(u64),
149 End(i64),
151 Current(i64),
153}
154
155impl SeekFrom {
156 pub(crate) fn to_raw(self) -> (i64, u32) {
158 match self {
159 SeekFrom::Start(pos) => (pos as i64, ext4_lwext4_sys::SEEK_SET),
160 SeekFrom::End(pos) => (pos, ext4_lwext4_sys::SEEK_END),
161 SeekFrom::Current(pos) => (pos, ext4_lwext4_sys::SEEK_CUR),
162 }
163 }
164}
165
166#[derive(Debug, Clone)]
168pub struct Metadata {
169 pub file_type: FileType,
171 pub size: u64,
173 pub blocks: u64,
175 pub mode: u32,
177 pub uid: u32,
179 pub gid: u32,
181 pub atime: u64,
183 pub mtime: u64,
185 pub ctime: u64,
187 pub nlink: u32,
189}
190
191impl Metadata {
192 pub fn is_file(&self) -> bool {
194 self.file_type.is_file()
195 }
196
197 pub fn is_dir(&self) -> bool {
199 self.file_type.is_dir()
200 }
201
202 pub fn is_symlink(&self) -> bool {
204 self.file_type.is_symlink()
205 }
206
207 pub fn len(&self) -> u64 {
209 self.size
210 }
211
212 pub fn is_empty(&self) -> bool {
214 self.size == 0
215 }
216}
217
218#[derive(Debug, Clone)]
220pub struct FsStats {
221 pub block_size: u32,
223 pub total_blocks: u64,
225 pub free_blocks: u64,
227 pub total_inodes: u64,
229 pub free_inodes: u64,
231 pub block_group_count: u32,
233 pub blocks_per_group: u32,
235 pub inodes_per_group: u32,
237 pub volume_name: String,
239}
240
241impl FsStats {
242 pub fn total_size(&self) -> u64 {
244 self.total_blocks * self.block_size as u64
245 }
246
247 pub fn free_size(&self) -> u64 {
249 self.free_blocks * self.block_size as u64
250 }
251
252 pub fn used_size(&self) -> u64 {
254 (self.total_blocks - self.free_blocks) * self.block_size as u64
255 }
256}