strate_fs_abstraction/capabilities.rs
1//! Filesystem capability flags.
2//!
3//! This module defines the capabilities that a filesystem implementation
4//! can advertise, allowing the VFS layer to adapt its behavior accordingly.
5
6/// Filesystem capabilities.
7///
8/// These flags describe what features a filesystem supports.
9/// The VFS layer uses this information to:
10/// - Reject unsupported operations early
11/// - Adapt behavior (e.g., case sensitivity)
12/// - Provide accurate information to applications
13#[derive(Debug, Clone)]
14pub struct FsCapabilities {
15 // === Access Mode ===
16 /// Filesystem is read-only (no write operations allowed)
17 pub read_only: bool,
18
19 // === Naming ===
20 /// Filesystem is case-sensitive (Linux default)
21 pub case_sensitive: bool,
22
23 /// Filesystem preserves case even if not case-sensitive
24 pub case_preserving: bool,
25
26 /// Maximum filename length in bytes
27 pub max_filename_len: usize,
28
29 /// Maximum full path length in bytes
30 pub max_path_len: usize,
31
32 // === Links ===
33 /// Supports symbolic links
34 pub supports_symlinks: bool,
35
36 /// Supports hard links
37 pub supports_hardlinks: bool,
38
39 // === File Features ===
40 /// Supports sparse files (holes in files)
41 pub supports_sparse_files: bool,
42
43 /// Maximum file size in bytes
44 pub max_file_size: u64,
45
46 // === Extended Attributes ===
47 /// Supports extended attributes (xattr)
48 pub supports_xattr: bool,
49
50 /// Supports POSIX ACLs
51 pub supports_acl: bool,
52
53 // === Timestamps ===
54 /// Supports sub-second timestamp precision
55 pub supports_nanoseconds: bool,
56
57 /// Supports creation/birth time (crtime)
58 pub supports_crtime: bool,
59}
60
61impl FsCapabilities {
62 /// Exbibyte constant (2^60) for max_file_size declarations.
63 const EIB: u64 = 1 << 60;
64
65 /// Create capabilities for a typical read-only Linux filesystem.
66 pub const fn read_only_linux() -> Self {
67 Self {
68 read_only: true,
69 case_sensitive: true,
70 case_preserving: true,
71 max_filename_len: 255,
72 max_path_len: 4096,
73 supports_symlinks: true,
74 supports_hardlinks: true,
75 supports_sparse_files: true,
76 max_file_size: i64::MAX as u64,
77 supports_xattr: false,
78 supports_acl: false,
79 supports_nanoseconds: true,
80 supports_crtime: false,
81 }
82 }
83
84 /// Create capabilities for a writable Linux filesystem.
85 pub const fn writable_linux() -> Self {
86 Self {
87 read_only: false,
88 ..Self::read_only_linux()
89 }
90 }
91
92 /// Create default XFS capabilities.
93 pub const fn xfs() -> Self {
94 Self {
95 read_only: false,
96 case_sensitive: true,
97 case_preserving: true,
98 max_filename_len: 255,
99 max_path_len: 4096,
100 supports_symlinks: true,
101 supports_hardlinks: true,
102 supports_sparse_files: true,
103 // XFS max file size: 8 EiB on 64-bit systems (was wrongly
104 // computed as 8 PiB : the literal chain had only five 1024s).
105 max_file_size: 8 * Self::EIB,
106 supports_xattr: true,
107 supports_acl: true,
108 supports_nanoseconds: true,
109 supports_crtime: true, // XFS v5 has crtime
110 }
111 }
112
113 /// Create default ext4 capabilities.
114 pub const fn ext4() -> Self {
115 Self {
116 read_only: false,
117 case_sensitive: true,
118 case_preserving: true,
119 max_filename_len: 255,
120 max_path_len: 4096,
121 supports_symlinks: true,
122 supports_hardlinks: true,
123 supports_sparse_files: true,
124 max_file_size: 16 * 1024 * 1024 * 1024 * 1024, // 16 TiB
125 supports_xattr: true,
126 supports_acl: true,
127 supports_nanoseconds: true,
128 supports_crtime: true,
129 }
130 }
131
132 /// Create default btrfs capabilities.
133 pub const fn btrfs() -> Self {
134 Self {
135 read_only: false,
136 case_sensitive: true,
137 case_preserving: true,
138 max_filename_len: 255,
139 max_path_len: 4096,
140 supports_symlinks: true,
141 supports_hardlinks: true,
142 supports_sparse_files: true,
143 // btrfs theoretical max file size is 16 EiB, which does NOT fit
144 // in u64 (2^64). Clamp to u64::MAX like other metadata that
145 // saturates; callers treat it as "unbounded".
146 max_file_size: u64::MAX,
147 supports_xattr: true,
148 supports_acl: true,
149 supports_nanoseconds: true,
150 supports_crtime: true,
151 }
152 }
153
154 /// Check if write operations are allowed.
155 pub const fn can_write(&self) -> bool {
156 !self.read_only
157 }
158}
159
160impl Default for FsCapabilities {
161 /// Implements default.
162 fn default() -> Self {
163 Self::read_only_linux()
164 }
165}