use bitflags::bitflags;
use ext4_lwext4_sys;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum FsType {
Ext2,
Ext3,
#[default]
Ext4,
}
impl FsType {
pub(crate) fn to_raw(self) -> i32 {
match self {
FsType::Ext2 => ext4_lwext4_sys::F_SET_EXT2,
FsType::Ext3 => ext4_lwext4_sys::F_SET_EXT3,
FsType::Ext4 => ext4_lwext4_sys::F_SET_EXT4,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileType {
RegularFile,
Directory,
Symlink,
BlockDevice,
CharDevice,
Fifo,
Socket,
Unknown,
}
impl FileType {
pub(crate) fn from_raw(raw: u8) -> Self {
match raw {
ext4_lwext4_sys::EXT4_DE_REG_FILE => FileType::RegularFile,
ext4_lwext4_sys::EXT4_DE_DIR => FileType::Directory,
ext4_lwext4_sys::EXT4_DE_SYMLINK => FileType::Symlink,
ext4_lwext4_sys::EXT4_DE_BLKDEV => FileType::BlockDevice,
ext4_lwext4_sys::EXT4_DE_CHRDEV => FileType::CharDevice,
ext4_lwext4_sys::EXT4_DE_FIFO => FileType::Fifo,
ext4_lwext4_sys::EXT4_DE_SOCK => FileType::Socket,
_ => FileType::Unknown,
}
}
pub(crate) fn to_raw(self) -> u8 {
match self {
FileType::RegularFile => ext4_lwext4_sys::EXT4_DE_REG_FILE,
FileType::Directory => ext4_lwext4_sys::EXT4_DE_DIR,
FileType::Symlink => ext4_lwext4_sys::EXT4_DE_SYMLINK,
FileType::BlockDevice => ext4_lwext4_sys::EXT4_DE_BLKDEV,
FileType::CharDevice => ext4_lwext4_sys::EXT4_DE_CHRDEV,
FileType::Fifo => ext4_lwext4_sys::EXT4_DE_FIFO,
FileType::Socket => ext4_lwext4_sys::EXT4_DE_SOCK,
FileType::Unknown => ext4_lwext4_sys::EXT4_DE_UNKNOWN,
}
}
pub fn is_file(&self) -> bool {
matches!(self, FileType::RegularFile)
}
pub fn is_dir(&self) -> bool {
matches!(self, FileType::Directory)
}
pub fn is_symlink(&self) -> bool {
matches!(self, FileType::Symlink)
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OpenFlags: u32 {
const READ = 0b0000_0001;
const WRITE = 0b0000_0010;
const CREATE = 0b0000_0100;
const TRUNCATE = 0b0000_1000;
const APPEND = 0b0001_0000;
const EXCLUSIVE = 0b0010_0000;
}
}
impl OpenFlags {
pub(crate) fn to_raw(self) -> i32 {
let mut flags = 0i32;
if self.contains(OpenFlags::READ) && self.contains(OpenFlags::WRITE) {
flags |= ext4_lwext4_sys::O_RDWR;
} else if self.contains(OpenFlags::WRITE) {
flags |= ext4_lwext4_sys::O_WRONLY;
} else {
flags |= ext4_lwext4_sys::O_RDONLY;
}
if self.contains(OpenFlags::CREATE) {
flags |= ext4_lwext4_sys::O_CREAT;
}
if self.contains(OpenFlags::TRUNCATE) {
flags |= ext4_lwext4_sys::O_TRUNC;
}
if self.contains(OpenFlags::APPEND) {
flags |= ext4_lwext4_sys::O_APPEND;
}
if self.contains(OpenFlags::EXCLUSIVE) {
flags |= ext4_lwext4_sys::O_EXCL;
}
flags
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
}
impl SeekFrom {
pub(crate) fn to_raw(self) -> (i64, u32) {
match self {
SeekFrom::Start(pos) => (pos as i64, ext4_lwext4_sys::SEEK_SET),
SeekFrom::End(pos) => (pos, ext4_lwext4_sys::SEEK_END),
SeekFrom::Current(pos) => (pos, ext4_lwext4_sys::SEEK_CUR),
}
}
}
#[derive(Debug, Clone)]
pub struct Metadata {
pub file_type: FileType,
pub size: u64,
pub blocks: u64,
pub mode: u32,
pub uid: u32,
pub gid: u32,
pub atime: u64,
pub mtime: u64,
pub ctime: u64,
pub nlink: u32,
}
impl Metadata {
pub fn is_file(&self) -> bool {
self.file_type.is_file()
}
pub fn is_dir(&self) -> bool {
self.file_type.is_dir()
}
pub fn is_symlink(&self) -> bool {
self.file_type.is_symlink()
}
pub fn len(&self) -> u64 {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
}
#[derive(Debug, Clone)]
pub struct FsStats {
pub block_size: u32,
pub total_blocks: u64,
pub free_blocks: u64,
pub total_inodes: u64,
pub free_inodes: u64,
pub block_group_count: u32,
pub blocks_per_group: u32,
pub inodes_per_group: u32,
pub volume_name: String,
}
impl FsStats {
pub fn total_size(&self) -> u64 {
self.total_blocks * self.block_size as u64
}
pub fn free_size(&self) -> u64 {
self.free_blocks * self.block_size as u64
}
pub fn used_size(&self) -> u64 {
(self.total_blocks - self.free_blocks) * self.block_size as u64
}
}