smb_fscc/filesystem_info.rs
1//! File System Information Classes
2//!
3//! This module defined [`QueryFileSystemInfo`] and [`SetFileSystemInfo`] enums,
4//! and all the information structs in those.
5//!
6//! [MS-FSCC 2.5](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ee12042a-9352-46e3-9f67-c094b75fe6c3>)
7
8use crate::file_info_classes;
9use binrw::prelude::*;
10use modular_bitfield::prelude::*;
11use smb_dtyp::{Guid, binrw_util::prelude::*};
12
13file_info_classes! {
14 /// Query file system information classes.
15 pub QueryFileSystemInfo {
16 pub FsAttribute = 5,
17 pub FsControl = 6,
18 pub FsDevice = 4,
19 pub FsFullSize = 7,
20 pub FsObjectId = 8,
21 pub FsSectorSize = 11,
22 pub FsSize = 3,
23 pub FsVolume = 1,
24 }
25}
26
27file_info_classes! {
28 /// Set file system information classes.
29 pub SetFileSystemInfo {
30 pub FsControl = 6,
31 pub FsObjectId = 8,
32 }
33}
34
35/// Query attribute information for a file system.
36///
37/// [MS-FSCC 2.5.1](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ebc7e6e5-4650-4e54-b17c-cf60f6fbeeaa>)
38#[binrw::binrw]
39#[derive(Debug, PartialEq, Eq)]
40pub struct FileFsAttributeInformation {
41 /// Contains a bitmask of flags that specify attributes of the specified file system as a combination of the following flags.
42 /// The value of this field MUST be a bitwise OR of zero or more of the following with the exception that FILE_FILE_COMPRESSION and FILE_VOLUME_IS_COMPRESSED cannot both be set.
43 /// Any flag values not explicitly mentioned here can be set to any value, and MUST be ignored.
44 pub attributes: FileSystemAttributes,
45 /// The maximum file name component length, in characters, supported by the specified file system.
46 /// The value of this field MUST be greater than zero and MUST be no more than 255.
47 pub maximum_component_name_length: u32,
48 #[bw(calc = file_system_name.size() as u32)]
49 pub file_system_name_length: u32,
50 /// the name of the file system. This field is not null-terminated and MUST be handled as a sequence of FileSystemNameLength bytes.
51 /// This field is intended to be informative only. A client SHOULD NOT infer file system type specific behavior from this field.
52 #[br(args { size: SizedStringSize::bytes(file_system_name_length) })]
53 pub file_system_name: SizedWideString,
54}
55
56/// File system attributes.
57///
58/// Used in [`FileFsAttributeInformation`]
59#[smb_dtyp::mbitfield]
60pub struct FileSystemAttributes {
61 /// The file system supports case-sensitive file names when looking up (searching for) file names in a directory.
62 pub case_sensitive_search: bool,
63 /// The file system preserves the case of file names when it places a name on disk.
64 pub case_preserved_names: bool,
65 /// The file system supports Unicode in file and directory names. This flag applies only to file and directory names; the file system neither restricts nor interprets the bytes of data within a file.
66 pub unicode_on_disk: bool,
67 /// The file system preserves and enforces access control lists (ACLs).
68 pub persistent_acls: bool,
69 /// The file volume supports file-based compression. This flag is incompatible with the `volume_is_compressed` flag.
70 pub file_compression: bool,
71 /// The file system supports per-user quotas.
72 pub volume_quotas: bool,
73 /// The file system supports sparse files.
74 pub supports_sparse_files: bool,
75 /// The file system supports reparse points.
76 pub supports_reparse_points: bool,
77 /// The file system supports remote storage.
78 pub supports_remote_storage: bool,
79 #[skip]
80 __: B6,
81 /// The specified volume is a compressed volume. This flag is incompatible with the `file_compression` flag.
82 pub volume_is_compressed: bool,
83 /// The file system supports object identifiers.
84 pub supports_object_ids: bool,
85 /// The file system supports the Encrypted File System (EFS).
86 pub supports_encryption: bool,
87 /// The file system supports named streams.
88 pub named_streams: bool,
89 /// If set, the volume has been mounted in read-only mode.
90 pub read_only_volume: bool,
91 /// The underlying volume is write once.
92 pub sequential_write_once: bool,
93 /// The volume supports transactions.
94 pub supports_transactions: bool,
95 /// The file system supports hard linking files.
96 pub supports_hard_links: bool,
97 /// The file system persistently stores Extended Attribute information per file.
98 pub supports_extended_attributes: bool,
99 /// The file system supports opening a file by FileID or ObjectID.
100 pub supports_open_by_file_id: bool,
101 /// The file system implements a USN change journal.
102 pub supports_usn_journal: bool,
103 /// The file system supports integrity streams.
104 pub support_integrity_streams: bool,
105 /// The file system supports sharing logical clusters between files on the same volume. The file system reallocates on writes to shared clusters. Indicates that `FSCTL_DUPLICATE_EXTENTS_TO_FILE` is a supported operation.
106 pub supports_block_refcounting: bool,
107 /// The file system tracks whether each cluster of a file contains valid data (either from explicit file writes or automatic zeros) or invalid data (has not yet been written to or zeroed). File systems that use Sparse VDL do not store a valid data length and do not require that valid data be contiguous within a file.
108 pub supports_sparse_vdl: bool,
109 #[skip]
110 __: B3,
111}
112
113/// Query or Set quota and content indexing control information for a file system volume.
114///
115/// Setting quota information requires the caller to have permission to open a volume handle or a handle to the quota index file for write access.
116///
117/// [MS-FSCC 2.5.2](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/e5a70738-7ee4-46d9-a5f7-6644daa49a51>)
118#[binrw::binrw]
119#[derive(Debug, PartialEq, Eq)]
120pub struct FileFsControlInformation {
121 /// The minimum amount of free disk space, in bytes, that is required for the operating system's content indexing service to begin document filtering. This value SHOULD be set to 0 and MUST be ignored.
122 pub free_space_start_filtering: u64,
123 /// The minimum amount of free disk space, in bytes, that is required for the indexing service to continue to filter documents and merge word lists. This value SHOULD be set to 0 and MUST be ignored.
124 pub free_space_threshold: u64,
125 /// The minimum amount of free disk space, in bytes, that is required for the content indexing service to continue filtering. This value SHOULD be set to 0, and MUST be ignored.
126 pub free_space_stop_filtering: u64,
127 /// The default per-user disk quota warning threshold, in bytes, for the volume. A value of [`u64::MAX`] specifies that no default quota warning threshold per user is set.
128 pub default_quota_threshold: u64,
129 /// The default per-user disk quota limit, in bytes, for the volume. A value of [`u64::MAX`] specifies that no default quota limit per user is set.
130 pub default_quota_limit: u64,
131 /// Contains a bitmask of flags that control quota enforcement and logging of user-related quota events on the volume.
132 pub file_system_control_flags: FileSystemControlFlags,
133}
134
135#[binrw::binrw]
136#[derive(Debug, PartialEq, Eq)]
137pub struct FileFsDeviceInformation {
138 /// This identifies the type of given volume.
139 pub device_type: FsDeviceType,
140 /// A bit field which identifies various characteristics about a given volume.
141 pub characteristics: FsDeviceCharacteristics,
142}
143
144#[binrw::binrw]
145#[derive(Debug, PartialEq, Eq, Clone, Copy)]
146#[brw(repr(u32))]
147pub enum FsDeviceType {
148 /// Volume resides on a CD ROM.
149 CdRom = 2,
150 /// Volume resides on a disk.
151 Disk = 7,
152}
153
154/// Characteristics of a file system volume.
155///
156/// See [`FileFsDeviceInformation`]
157#[smb_dtyp::mbitfield]
158pub struct FsDeviceCharacteristics {
159 /// Indicates that the storage device supports removable media.
160 /// Notice that this characteristic indicates removable media, not a removable device.
161 /// For example, drivers for JAZ drive devices specify this characteristic, but drivers for PCMCIA flash disks do not.
162 pub removable_media: bool,
163 /// Indicates that the device cannot be written to.
164 pub read_only: bool,
165 /// Indicates that the device is a floppy disk device.
166 pub floppy_diskette: bool,
167 /// Indicates that the device supports write-once media.
168 pub write_once_media: bool,
169
170 /// Indicates that the volume is for a remote file system like SMB or CIFS.
171 pub remote: bool,
172 /// Indicates that a file system is mounted on the device.
173 pub device_is_mounted: bool,
174 /// Indicates that the volume does not directly reside on storage media but resides on some other type of media (memory for example).
175 pub virtual_volume: bool,
176 #[skip]
177 __: bool,
178
179 /// By default, volumes do not check the ACL associated with the volume, but instead use the ACLs associated with individual files on the volume.
180 /// When this flag is set the volume ACL is also checked.
181 pub secure_open: bool,
182 #[skip]
183 __: B3,
184
185 /// Indicates that the device object is part of a Terminal Services device stack. See [MS-RDPBCGR] for more information.
186 pub ts: bool,
187 /// Indicates that a web-based Distributed Authoring and Versioning (WebDAV) file system is mounted on the device. See [MS-WDVME] for more information.
188 pub webda: bool,
189 #[skip]
190 __: B3,
191
192 /// The IO Manager normally performs a full security check for traverse access on every file open when the client is an appcontainer.
193 /// Setting of this flag bypasses this enforced traverse access check if the client token already has traverse privileges.
194 pub allow_appcontainer_traversal: bool,
195 /// Indicates that the given device resides on a portable bus like USB or Firewire and that the entire device (not just the media) can be removed from the system.
196 pub portable: bool,
197 #[skip]
198 __: B13,
199}
200
201/// File system control flags.
202///
203/// Used in [`FileFsControlInformation`]
204#[smb_dtyp::mbitfield]
205pub struct FileSystemControlFlags {
206 /// Quotas are tracked on the volume, but they are not enforced.
207 /// Tracked quotas enable reporting on the file system space used by system users.
208 /// If both this flag and FILE_VC_QUOTA_ENFORCE are specified, FILE_VC_QUOTA_ENFORCE is ignored.
209 ///
210 /// Note: This flag takes precedence over FILE_VC_QUOTA_ENFORCE.
211 /// In other words, if both FILE_VC_QUOTA_TRACK and FILE_VC_QUOTA_ENFORCE are set,
212 /// the FILE_VC_QUOTA_ENFORCE flag is ignored.
213 /// This flag will be ignored if a client attempts to set it.
214 pub quota_track: bool,
215 /// Quotas are tracked and enforced on the volume.
216 ///
217 /// Note: FILE_VC_QUOTA_TRACK takes precedence over this flag.
218 /// In other words, if both FILE_VC_QUOTA_TRACK and FILE_VC_QUOTA_ENFORCE are set,
219 /// the FILE_VC_QUOTA_ENFORCE flag is ignored.
220 /// This flag will be ignored if a client attempts to set it.
221 pub quota_enforce: bool,
222 /// Content indexing is disabled.
223 pub content_indexing_disabled: bool,
224 #[skip]
225 __: bool,
226
227 /// An event log entry will be created when the user exceeds his or her assigned quota warning threshold.
228 pub log_quota_threshold: bool,
229 /// An event log entry will be created when the user exceeds the assigned disk quota limit.
230 pub log_quota_limit: bool,
231 /// An event log entry will be created when the volume's free space threshold is exceeded.
232 pub log_volume_threshold: bool,
233 /// An event log entry will be created when the volume's free space limit is exceeded.
234 pub log_volume_limit: bool,
235
236 /// The quota information for the volume is incomplete because it is corrupt, or the system is in the process of rebuilding the quota information.
237 /// Note: This does not necessarily imply that FILE_VC_QUOTAS_REBUILDING is set. This flag will be ignored if a client attempts to set it.
238 pub quotas_incomplete: bool,
239
240 /// The file system is rebuilding the quota information for the volume.
241 /// Note: This does not necessarily imply that FILE_VC_QUOTAS_INCOMPLETE is set. This flag will be ignored if a client attempts to set it.
242 pub quotas_rebuilding: bool,
243 #[skip]
244 __: B22,
245}
246
247/// Query sector size information for a file system volume.
248///
249/// [MS-FSCC 2.5.4](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/63768db7-9012-4209-8cca-00781e7322f5)
250#[binrw::binrw]
251#[derive(Debug, PartialEq, Eq)]
252pub struct FileFsFullSizeInformation {
253 pub total_allocation_units: u64,
254 pub caller_available_allocation_units: u64,
255 pub actual_available_allocation_units: u64,
256 pub sectors_per_allocation_unit: u32,
257 pub bytes_per_sector: u32,
258}
259
260/// Query or Set the object ID for a file system data element. The operation MUST fail if the file system does not support object IDs.
261///
262/// [MS-FSCC 2.5.6](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/dbf535ae-315a-4508-8bc5-84276ea106d4>)
263#[binrw::binrw]
264#[derive(Debug, PartialEq, Eq)]
265pub struct FileFsObjectIdInformation {
266 /// Identifies the file system volume on the disk. This value is not required to be unique on the system.
267 pub object_id: Guid,
268 /// A 48-byte value containing extended information on the file system volume. If no extended information has been written for this file system volume, the server MUST return 48 bytes of 0x00 in this field.
269 pub extended_info: [u8; 48],
270}
271
272/// Query for the extended sector size and alignment information for a volume.
273///
274/// The message contains a FILE_FS_SECTOR_SIZE_INFORMATION data element.
275///
276/// [MS-FSCC 2.5.7](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/3e75d97f-1d0b-4e47-b435-73c513837a57>)
277#[binrw::binrw]
278#[derive(Debug, PartialEq, Eq)]
279pub struct FileFsSectorSizeInformation {
280 /// The number of bytes in a logical sector for the device backing the volume.
281 /// This field is the unit of logical addressing for the device and is not the unit of atomic write.
282 /// Applications SHOULD NOT utilize this value for operations requiring physical sector alignment.
283 pub logical_bytes_per_sector: u32,
284 /// The number of bytes in a physical sector for the device backing the volume.
285 /// Note that this is the reported physical sector size of the device and is the unit of atomic write.
286 /// Applications SHOULD utilize this value for operations requiring sector alignment.
287 pub physical_bytes_per_sector: u32,
288 /// The number of bytes in a physical sector for the device backing the volume.
289 /// This is the reported physical sector size of the device and is the unit of performance.
290 /// Applications SHOULD utilize this value for operations requiring sector alignment.
291 pub physical_bytes_per_sector_for_performance: u32,
292 /// The unit, in bytes, that the file system on the volume will use for internal operations that require alignment and atomicity.
293 pub effective_physical_bytes_per_sector_for_atomicity: u32,
294 /// Flags for this operation.
295 pub flags: SectorSizeInfoFlags,
296 /// The logical sector offset within the first physical sector where the first logical sector is placed, in bytes.
297 /// If this value is set to SSINFO_OFFSET_UNKNOWN (0XFFFFFFFF), there was insufficient information to compute this field.
298 pub byte_offset_for_sector_alignment: u32,
299 /// The byte offset from the first physical sector where the first partition is placed.
300 /// If this value is set to SSINFO_OFFSET_UNKNOWN (0XFFFFFFFF),
301 /// there was either insufficient information or an error was encountered in computing this field.
302 pub byte_offset_for_partition_alignment: u32,
303}
304
305/// File system sector flags.
306#[smb_dtyp::mbitfield]
307pub struct SectorSizeInfoFlags {
308 /// When set, this flag indicates that the first physical sector of the device is aligned with the first logical sector.
309 /// When not set, the first physical sector of the device is misaligned with the first logical sector.
310 pub aligned_device: bool,
311 /// When set, this flag indicates that the partition is aligned to physical sector boundaries on the storage device.
312 pub partition_aligned_on_device: bool,
313 /// When set, the device reports that it does not incur a seek penalty (this typically indicates that the device does not have rotating media, such as flash-based disks).
314 pub no_seek_penalty: bool,
315 /// When set, the device supports TRIM operations, either T13 (ATA) TRIM or T10 (SCSI/SAS) UNMAP.
316 pub trim_enabled: bool,
317 #[skip]
318 __: B28,
319}
320
321/// Query sector size information for a file system volume.
322///
323/// [MS-FSCC 2.5.8](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/e13e068c-e3a7-4dd4-94fd-3892b492e6e7>)
324#[binrw::binrw]
325#[derive(Debug, PartialEq, Eq)]
326pub struct FileFsSizeInformation {
327 /// The total number of allocation units on the volume that are available to the user associated with the calling thread. This value MUST be greater than or equal to 0.
328 pub total_allocation_units: u64,
329 /// The total number of free allocation units on the volume that are available to the user associated with the calling thread. This value MUST be greater than or equal to 0.
330 pub available_allocation_units: u64,
331 /// The number of sectors in each allocation unit.
332 pub sectors_per_allocation_unit: u32,
333 /// The number of bytes in each sector.
334 pub bytes_per_sector: u32,
335}
336
337/// Query information on a volume on which a file system is mounted.
338///
339/// [MS-FSCC 2.5.9](<https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/bf691378-c34e-4a13-976e-404ea1a87738>)
340#[binrw::binrw]
341#[derive(Debug, PartialEq, Eq)]
342pub struct FileFsVolumeInformation {
343 /// The time when the volume was created.
344 pub volume_creation_time: FileTime,
345 /// C contains the serial number of the volume.
346 /// The serial number is an opaque value generated by the file system at format time,
347 /// and is not necessarily related to any hardware serial number for the device on which the file system is located.
348 /// No specific format or content of this field is required for protocol interoperation.
349 /// This value is not required to be unique.
350 pub volume_serial_number: u32,
351 #[bw(calc = volume_label.size() as u32)]
352 pub volume_label_length: u32,
353 /// Set to TRUE if the file system supports object-oriented file system objects; set to FALSE otherwise.
354 pub supports_objects: Boolean,
355 #[bw(calc = 0)]
356 #[br(temp)]
357 _reserved: u8,
358 /// The content of this field can be a null-terminated string or can be a string padded with the space character to be VolumeLabelLength bytes long.
359 #[br(args { size: SizedStringSize::bytes(volume_label_length) })]
360 pub volume_label: SizedWideString,
361}
362
363#[cfg(test)]
364mod tests {
365 use super::*;
366 use smb_dtyp::make_guid;
367 use smb_tests::*;
368 use time::macros::datetime;
369
370 test_binrw! {
371 struct FileFsVolumeInformation {
372 volume_creation_time: datetime!(2025-10-13 12:35:04.593237).into(),
373 volume_serial_number: 0x529d2cf4,
374 volume_label: "MyShare".into(),
375 supports_objects: false.into(),
376 } => "525119cd3d3cdc01f42c9d520e00000000004d00790053006800610072006500"
377 }
378
379 test_binrw! {
380 struct FileFsSizeInformation {
381 total_allocation_units: 61202244,
382 available_allocation_units: 45713576,
383 sectors_per_allocation_unit: 2,
384 bytes_per_sector: 512,
385 } => "44dfa50300000000a888b902000000000200000000020000"
386 }
387
388 test_binrw! {
389 struct FileFsFullSizeInformation {
390 total_allocation_units: 0x03a5df44,
391 actual_available_allocation_units: 0x02b98894,
392 caller_available_allocation_units: 0x02b98894,
393 sectors_per_allocation_unit: 2,
394 bytes_per_sector: 512,
395 } => "44dfa503000000009488b902000000009488b902000000000200000000020000"
396 }
397
398 test_binrw! {
399 struct FileFsDeviceInformation {
400 device_type: FsDeviceType::Disk,
401 characteristics: FsDeviceCharacteristics::new().with_device_is_mounted(true),
402 } => "0700000020000000"
403 }
404
405 test_binrw! {
406 struct FileFsAttributeInformation {
407 attributes: FileSystemAttributes::new()
408 .with_case_sensitive_search(true)
409 .with_case_preserved_names(true)
410 .with_unicode_on_disk(true)
411 .with_persistent_acls(true)
412 .with_volume_quotas(true)
413 .with_supports_sparse_files(true)
414 .with_supports_object_ids(true)
415 .with_named_streams(true),
416 maximum_component_name_length: 255,
417 file_system_name: "NTFS".into(),
418 } => "6f000500ff000000080000004e00540046005300"
419 }
420
421 test_binrw! {
422 struct FileFsSectorSizeInformation {
423 logical_bytes_per_sector: 512,
424 physical_bytes_per_sector: 512,
425 physical_bytes_per_sector_for_performance: 512,
426 effective_physical_bytes_per_sector_for_atomicity: 512,
427 flags: SectorSizeInfoFlags::new()
428 .with_aligned_device(true)
429 .with_partition_aligned_on_device(true),
430 byte_offset_for_sector_alignment: 0,
431 byte_offset_for_partition_alignment: 0,
432 } => "00020000000200000002000000020000030000000000000000000000"
433 }
434
435 test_binrw! {
436 struct FileFsObjectIdInformation {
437 object_id: make_guid!("ed3e2170-2733-48b3-e5c0-bd5334f85a37"),
438 extended_info: [0x61, 0x42, 0x6d, 0x53, 0x0, 0x6, 0x14, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x2e, 0x32, 0x30, 0x2e,
439 0x36, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
440 } => "70213eed3327b348e5c0bd5334f85a3761426d5300061404000000000000000000000000342e32302e3600000000000000000000000000000000000000000000"
441 }
442}