littlefs2_core/
fs.rs

1use core::{cmp, ffi::c_int};
2
3use bitflags::bitflags;
4
5use crate::path::{Path, PathBuf};
6
7bitflags! {
8    /// Definition of file open flags which can be mixed and matched as appropriate. These definitions
9    /// are reminiscent of the ones defined by POSIX.
10    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
11    pub struct FileOpenFlags: c_int {
12        /// Open file in read only mode.
13        const READ = 0x1;
14        /// Open file in write only mode.
15        const WRITE = 0x2;
16        /// Open file for reading and writing.
17        const READWRITE = Self::READ.bits() | Self::WRITE.bits();
18        /// Create the file if it does not exist.
19        const CREATE = 0x0100;
20        /// Fail if creating a file that already exists.
21        /// TODO: Good name for this
22        const EXCL = 0x0200;
23        /// Truncate the file if it already exists.
24        const TRUNCATE = 0x0400;
25        /// Open the file in append only mode.
26        const APPEND = 0x0800;
27    }
28}
29
30/// Regular file vs directory
31#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
33pub enum FileType {
34    File,
35    Dir,
36}
37
38impl FileType {
39    pub fn is_dir(&self) -> bool {
40        *self == FileType::Dir
41    }
42
43    pub fn is_file(&self) -> bool {
44        *self == FileType::File
45    }
46}
47
48/// File type (regular vs directory) and size of a file.
49#[derive(Clone, Debug, Eq, PartialEq)]
50#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51pub struct Metadata {
52    file_type: FileType,
53    size: usize,
54}
55
56impl Metadata {
57    pub fn new(file_type: FileType, size: usize) -> Self {
58        Self { file_type, size }
59    }
60
61    pub fn file_type(&self) -> FileType {
62        self.file_type
63    }
64
65    pub fn is_dir(&self) -> bool {
66        self.file_type().is_dir()
67    }
68
69    pub fn is_file(&self) -> bool {
70        self.file_type().is_file()
71    }
72
73    pub fn len(&self) -> usize {
74        self.size
75    }
76
77    pub fn is_empty(&self) -> bool {
78        self.size == 0
79    }
80}
81
82#[derive(Clone, Debug, Eq, PartialEq)]
83/// Custom user attribute that can be set on files and directories.
84///
85/// This struct stores the data that has been read from the filesystem and
86/// the total size of the attribute on the filesystem.  The maximum size of an
87/// attribute is [`Attribute::MAX_SIZE`][].
88///
89/// See [`DynFilesystem::attribute`](`crate::object_safe::DynFilesystem::attribute`).
90pub struct Attribute<'a> {
91    data: &'a [u8],
92    total_size: usize,
93}
94
95impl<'a> Attribute<'a> {
96    pub const MAX_SIZE: u32 = 1_022;
97
98    pub fn new(data: &'a [u8], total_size: usize) -> Self {
99        let n = cmp::min(data.len(), total_size);
100        let data = &data[..n];
101        Attribute { data, total_size }
102    }
103
104    pub fn data(&self) -> &[u8] {
105        self.data
106    }
107
108    pub fn total_size(&self) -> usize {
109        self.total_size
110    }
111}
112
113#[derive(Clone, Debug, PartialEq, Eq)]
114#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
115pub struct DirEntry {
116    file_name: PathBuf,
117    metadata: Metadata,
118    path: PathBuf,
119}
120
121impl DirEntry {
122    pub fn new(file_name: PathBuf, metadata: Metadata, path: PathBuf) -> Self {
123        Self {
124            file_name,
125            metadata,
126            path,
127        }
128    }
129
130    // Returns the metadata for the file that this entry points at.
131    pub fn metadata(&self) -> Metadata {
132        self.metadata.clone()
133    }
134
135    // Returns the file type for the file that this entry points at.
136    pub fn file_type(&self) -> FileType {
137        self.metadata.file_type
138    }
139
140    // Returns the bare file name of this directory entry without any other leading path component.
141    pub fn file_name(&self) -> &Path {
142        &self.file_name
143    }
144
145    /// Returns the full path to the file that this entry represents.
146    ///
147    /// The full path is created by joining the original path to read_dir with the filename of this entry.
148    pub fn path(&self) -> &Path {
149        &self.path
150    }
151
152    #[doc(hidden)]
153    // This is used in `crypto-service` to "namespace" paths
154    // by mutating a DirEntry in-place.
155    pub unsafe fn path_buf_mut(&mut self) -> &mut PathBuf {
156        &mut self.path
157    }
158}