// SPDX-License-Identifier: MPL-2.0 //! VFS components pub use access_mode::AccessMode; pub use creation_flags::CreationFlags; pub use dirent_visitor::{DirentCounter, DirentVisitor}; pub use direntry_vec::DirEntryVecExt; pub use endpoint::{Endpoint, EndpointState}; pub use falloc_mode::FallocMode; pub use file_creation_mask::{AtomicFileCreationMask, FileCreationMask}; pub use flock::{FlockItem, FlockList, FlockType}; pub use fs::{FileSystem, FsEventSubscriberStats, FsFlags, SuperBlock}; pub use id_bitmap::IdBitmap; pub use inode::{ Extension, Inode, InodeIo, InodeType, Metadata, MknodType, Permission, SymbolicLink, }; pub use inode_mode::InodeMode; pub(crate) use inode_mode::{chmod, mkmod, perms_to_mask, who_and_perms_to_mask, who_to_mask}; pub use open_args::OpenArgs; pub use page_cache::{CachePage, PageCache, PageCacheBackend}; pub use random_test::{generate_random_operation, new_fs_in_memory}; pub use range_lock::{FileRange, RangeLockItem, RangeLockList, RangeLockType, OFFSET_MAX}; pub use status_flags::StatusFlags; pub use xattr::{ XattrName, XattrNamespace, XattrSetFlags, XATTR_LIST_MAX_LEN, XATTR_NAME_MAX_LEN, XATTR_VALUE_MAX_LEN, }; mod access_mode; mod creation_flags; mod dirent_visitor; mod direntry_vec; mod endpoint; mod falloc_mode; mod file_creation_mask; mod flock; mod fs; mod id_bitmap; mod inode; mod inode_mode; mod open_args; mod page_cache; mod random_test; mod range_lock; mod status_flags; pub mod systree_inode; mod xattr; use core::{ borrow::Borrow, hash::{Hash, Hasher}, }; use crate::prelude::*; #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub enum SeekFrom { Start(usize), End(isize), Current(isize), } /// Maximum bytes in a path pub const PATH_MAX: usize = 4096; /// Maximum bytes in a file name pub const NAME_MAX: usize = 255; /// The upper limit for resolving symbolic links pub const SYMLINKS_MAX: usize = 40; pub type CStr256 = FixedCStr<256>; pub type Str16 = FixedStr<16>; pub type Str64 = FixedStr<64>; /// An owned C-compatible string with a fixed capacity of `N`. /// /// The string is terminated with a null byte. #[repr(C)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Pod)] pub struct FixedCStr([u8; N]); impl FixedCStr { pub fn len(&self) -> usize { self.0.iter().position(|&b| b == 0).unwrap() } #[expect(dead_code)] pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn as_str(&self) -> Result<&str> { Ok(alloc::str::from_utf8(self.as_bytes())?) } pub fn as_cstr(&self) -> Result<&CStr> { Ok(CStr::from_bytes_with_nul(self.as_bytes_with_nul())?) } pub fn as_bytes(&self) -> &[u8] { &self.0[0..self.len()] } pub fn as_bytes_with_nul(&self) -> &[u8] { &self.0[0..=self.len()] } } impl<'a, const N: usize> From<&'a [u8]> for FixedCStr { fn from(bytes: &'a [u8]) -> Self { assert!(N > 0); let mut inner = [0u8; N]; let len = { let mut nul_byte_idx = match bytes.iter().position(|&b| b == 0) { Some(idx) => idx, None => bytes.len(), }; if nul_byte_idx >= N { nul_byte_idx = N - 1; } nul_byte_idx }; inner[0..len].copy_from_slice(&bytes[0..len]); Self(inner) } } impl<'a, const N: usize> From<&'a str> for FixedCStr { fn from(string: &'a str) -> Self { let bytes = string.as_bytes(); Self::from(bytes) } } impl<'a, const N: usize> From<&'a CStr> for FixedCStr { fn from(cstr: &'a CStr) -> Self { let bytes = cstr.to_bytes_with_nul(); Self::from(bytes) } } impl Default for FixedCStr { fn default() -> Self { Self([0u8; N]) } } impl Debug for FixedCStr { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match self.as_cstr() { Ok(cstr) => write!(f, "{:?}", cstr), Err(_) => write!(f, "{:?}", self.as_bytes()), } } } /// An owned string with a fixed capacity of `N`. #[repr(C)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Pod)] pub struct FixedStr([u8; N]); impl FixedStr { pub fn len(&self) -> usize { self.0.iter().position(|&b| b == 0).unwrap_or(N) } #[expect(dead_code)] pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn as_str(&self) -> Result<&str> { Ok(alloc::str::from_utf8(self.as_bytes())?) } pub fn as_bytes(&self) -> &[u8] { &self.0[0..self.len()] } } impl<'a, const N: usize> From<&'a [u8]> for FixedStr { fn from(bytes: &'a [u8]) -> Self { let mut inner = [0u8; N]; let len = { let mut nul_byte_idx = match bytes.iter().position(|&b| b == 0) { Some(idx) => idx, None => bytes.len(), }; if nul_byte_idx > N { nul_byte_idx = N; } nul_byte_idx }; inner[0..len].copy_from_slice(&bytes[0..len]); Self(inner) } } impl<'a, const N: usize> From<&'a str> for FixedStr { fn from(string: &'a str) -> Self { let bytes = string.as_bytes(); Self::from(bytes) } } impl Borrow<[u8]> for FixedCStr { fn borrow(&self) -> &[u8] { self.as_bytes() } } impl Hash for FixedCStr { fn hash(&self, state: &mut H) { self.as_bytes().hash(state); } } impl Default for FixedStr { fn default() -> Self { Self([0u8; N]) } } impl Debug for FixedStr { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match self.as_str() { Ok(string) => write!(f, "{}", string), Err(_) => write!(f, "{:?}", self.as_bytes()), } } }