Skip to main content

ntfs_core/usn/
attributes.rs

1use bitflags::bitflags;
2
3bitflags! {
4    /// Windows file attributes from USN records.
5    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6    pub struct FileAttributes: u32 {
7        const READONLY            = 0x0000_0001;
8        const HIDDEN              = 0x0000_0002;
9        const SYSTEM              = 0x0000_0004;
10        const DIRECTORY           = 0x0000_0010;
11        const ARCHIVE             = 0x0000_0020;
12        const DEVICE              = 0x0000_0040;
13        const NORMAL              = 0x0000_0080;
14        const TEMPORARY           = 0x0000_0100;
15        const SPARSE_FILE         = 0x0000_0200;
16        const REPARSE_POINT       = 0x0000_0400;
17        const COMPRESSED          = 0x0000_0800;
18        const OFFLINE             = 0x0000_1000;
19        const NOT_CONTENT_INDEXED = 0x0000_2000;
20        const ENCRYPTED           = 0x0000_4000;
21        const INTEGRITY_STREAM    = 0x0000_8000;
22        const VIRTUAL             = 0x0001_0000;
23        const NO_SCRUB_DATA       = 0x0002_0000;
24    }
25}
26
27impl std::fmt::Display for FileAttributes {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        let names: Vec<&str> = self.iter_names().map(|(name, _)| name).collect();
30        if names.is_empty() {
31            write!(f, "0x{:x}", self.bits())
32        } else {
33            write!(f, "{}", names.join("|"))
34        }
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn test_directory_attribute() {
44        let a = FileAttributes::DIRECTORY;
45        assert!(a.contains(FileAttributes::DIRECTORY));
46        assert_eq!(a.to_string(), "DIRECTORY");
47    }
48
49    #[test]
50    fn test_combined_attributes() {
51        let a = FileAttributes::HIDDEN | FileAttributes::SYSTEM | FileAttributes::ARCHIVE;
52        let s = a.to_string();
53        assert!(s.contains("HIDDEN"));
54        assert!(s.contains("SYSTEM"));
55        assert!(s.contains("ARCHIVE"));
56    }
57
58    #[test]
59    fn test_empty_attributes() {
60        let a = FileAttributes::from_bits_retain(0);
61        assert_eq!(a.to_string(), "0x0");
62    }
63}