2024-01-03 03:22:36 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2022-12-30 03:22:04 +00:00
|
|
|
//! VFS components
|
|
|
|
|
|
|
|
|
|
pub use access_mode::AccessMode;
|
2023-01-06 08:06:33 +00:00
|
|
|
pub use creation_flags::CreationFlags;
|
2025-07-08 12:27:49 +00:00
|
|
|
pub use dirent_visitor::{DirentCounter, DirentVisitor};
|
2023-04-18 10:09:57 +00:00
|
|
|
pub use direntry_vec::DirEntryVecExt;
|
2025-06-13 09:33:50 +00:00
|
|
|
pub use endpoint::{Endpoint, EndpointState};
|
2024-06-28 10:45:16 +00:00
|
|
|
pub use falloc_mode::FallocMode;
|
2025-09-22 03:38:07 +00:00
|
|
|
pub use file_creation_mask::{AtomicFileCreationMask, FileCreationMask};
|
2024-08-12 03:51:32 +00:00
|
|
|
pub use flock::{FlockItem, FlockList, FlockType};
|
2023-03-27 05:53:29 +00:00
|
|
|
pub use fs::{FileSystem, FsFlags, SuperBlock};
|
2025-09-21 13:03:18 +00:00
|
|
|
pub use inode::{Extension, Inode, InodeType, Metadata, MknodType, Permission};
|
|
|
|
|
pub use inode_mode::InodeMode;
|
|
|
|
|
pub(crate) use inode_mode::{chmod, mkmod, perms_to_mask, who_and_perms_to_mask, who_to_mask};
|
2023-02-15 02:43:41 +00:00
|
|
|
pub use ioctl::IoctlCmd;
|
2025-10-16 15:57:17 +00:00
|
|
|
pub use open_args::OpenArgs;
|
2024-12-27 03:55:56 +00:00
|
|
|
pub use page_cache::{CachePage, PageCache, PageCacheBackend};
|
2024-03-18 07:58:37 +00:00
|
|
|
pub use random_test::{generate_random_operation, new_fs_in_memory};
|
2025-08-23 03:16:27 +00:00
|
|
|
pub use range_lock::{FileRange, RangeLockItem, RangeLockList, RangeLockType, OFFSET_MAX};
|
2022-12-30 03:22:04 +00:00
|
|
|
pub use status_flags::StatusFlags;
|
2025-03-28 05:58:37 +00:00
|
|
|
pub use xattr::{
|
|
|
|
|
XattrName, XattrNamespace, XattrSetFlags, XATTR_LIST_MAX_LEN, XATTR_NAME_MAX_LEN,
|
|
|
|
|
XATTR_VALUE_MAX_LEN,
|
|
|
|
|
};
|
2022-12-30 03:22:04 +00:00
|
|
|
|
|
|
|
|
mod access_mode;
|
2023-01-06 08:06:33 +00:00
|
|
|
mod creation_flags;
|
2023-03-08 07:08:31 +00:00
|
|
|
mod dirent_visitor;
|
2023-03-24 10:15:08 +00:00
|
|
|
mod direntry_vec;
|
2025-06-13 09:33:50 +00:00
|
|
|
mod endpoint;
|
2024-06-28 10:45:16 +00:00
|
|
|
mod falloc_mode;
|
2023-03-09 09:07:30 +00:00
|
|
|
mod file_creation_mask;
|
2024-08-12 03:51:32 +00:00
|
|
|
mod flock;
|
2022-12-30 03:22:04 +00:00
|
|
|
mod fs;
|
|
|
|
|
mod inode;
|
2025-09-21 13:03:18 +00:00
|
|
|
mod inode_mode;
|
2023-02-15 02:43:41 +00:00
|
|
|
mod ioctl;
|
2025-10-16 15:57:17 +00:00
|
|
|
mod open_args;
|
2023-01-04 09:26:49 +00:00
|
|
|
mod page_cache;
|
2024-03-18 07:58:37 +00:00
|
|
|
mod random_test;
|
2024-08-12 03:51:32 +00:00
|
|
|
mod range_lock;
|
2022-12-30 03:22:04 +00:00
|
|
|
mod status_flags;
|
2025-07-07 06:32:00 +00:00
|
|
|
pub mod systree_inode;
|
2025-03-28 05:58:37 +00:00
|
|
|
mod xattr;
|
2022-12-30 03:22:04 +00:00
|
|
|
|
2024-09-14 07:15:28 +00:00
|
|
|
use core::{
|
|
|
|
|
borrow::Borrow,
|
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-18 03:47:17 +00:00
|
|
|
use crate::prelude::*;
|
|
|
|
|
|
2022-12-30 03:22:04 +00:00
|
|
|
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
|
|
|
|
pub enum SeekFrom {
|
2023-02-20 08:40:04 +00:00
|
|
|
Start(usize),
|
|
|
|
|
End(isize),
|
|
|
|
|
Current(isize),
|
2022-12-30 03:22:04 +00:00
|
|
|
}
|
2023-01-06 08:06:33 +00:00
|
|
|
|
|
|
|
|
/// 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;
|
2023-09-18 03:47:17 +00:00
|
|
|
|
|
|
|
|
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<const N: usize>([u8; N]);
|
|
|
|
|
|
|
|
|
|
impl<const N: usize> FixedCStr<N> {
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.0.iter().position(|&b| b == 0).unwrap()
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-22 01:30:20 +00:00
|
|
|
#[expect(dead_code)]
|
2023-09-18 03:47:17 +00:00
|
|
|
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<N> {
|
|
|
|
|
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<N> {
|
|
|
|
|
fn from(string: &'a str) -> Self {
|
|
|
|
|
let bytes = string.as_bytes();
|
|
|
|
|
Self::from(bytes)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a, const N: usize> From<&'a CStr> for FixedCStr<N> {
|
|
|
|
|
fn from(cstr: &'a CStr) -> Self {
|
|
|
|
|
let bytes = cstr.to_bytes_with_nul();
|
|
|
|
|
Self::from(bytes)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<const N: usize> Default for FixedCStr<N> {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self([0u8; N])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<const N: usize> Debug for FixedCStr<N> {
|
|
|
|
|
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<const N: usize>([u8; N]);
|
|
|
|
|
|
|
|
|
|
impl<const N: usize> FixedStr<N> {
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.0.iter().position(|&b| b == 0).unwrap_or(N)
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-22 01:30:20 +00:00
|
|
|
#[expect(dead_code)]
|
2023-09-18 03:47:17 +00:00
|
|
|
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<N> {
|
|
|
|
|
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<N> {
|
|
|
|
|
fn from(string: &'a str) -> Self {
|
|
|
|
|
let bytes = string.as_bytes();
|
|
|
|
|
Self::from(bytes)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-14 07:15:28 +00:00
|
|
|
impl<const N: usize> Borrow<[u8]> for FixedCStr<N> {
|
|
|
|
|
fn borrow(&self) -> &[u8] {
|
|
|
|
|
self.as_bytes()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<const N: usize> Hash for FixedCStr<N> {
|
|
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
|
|
self.as_bytes().hash(state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-18 03:47:17 +00:00
|
|
|
impl<const N: usize> Default for FixedStr<N> {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self([0u8; N])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<const N: usize> Debug for FixedStr<N> {
|
|
|
|
|
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()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|