1 /*
2  * The little filesystem
3  *
4  * Copyright (c) 2017, Arm Limited. All rights reserved.
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 #ifndef LFS1_H
8 #define LFS1_H
9 
10 #include <stdint.h>
11 #include <stdbool.h>
12 
13 #ifdef __cplusplus
14 extern "C"
15 {
16 #endif
17 
18 
19 /// Version info ///
20 
21 // Software library version
22 // Major (top-nibble), incremented on backwards incompatible changes
23 // Minor (bottom-nibble), incremented on feature additions
24 #define LFS1_VERSION 0x00010007
25 #define LFS1_VERSION_MAJOR (0xffff & (LFS1_VERSION >> 16))
26 #define LFS1_VERSION_MINOR (0xffff & (LFS1_VERSION >>  0))
27 
28 // Version of On-disk data structures
29 // Major (top-nibble), incremented on backwards incompatible changes
30 // Minor (bottom-nibble), incremented on feature additions
31 #define LFS1_DISK_VERSION 0x00010001
32 #define LFS1_DISK_VERSION_MAJOR (0xffff & (LFS1_DISK_VERSION >> 16))
33 #define LFS1_DISK_VERSION_MINOR (0xffff & (LFS1_DISK_VERSION >>  0))
34 
35 
36 /// Definitions ///
37 
38 // Type definitions
39 typedef uint32_t lfs1_size_t;
40 typedef uint32_t lfs1_off_t;
41 
42 typedef int32_t  lfs1_ssize_t;
43 typedef int32_t  lfs1_soff_t;
44 
45 typedef uint32_t lfs1_block_t;
46 
47 // Max name size in bytes
48 #ifndef LFS1_NAME_MAX
49 #define LFS1_NAME_MAX 255
50 #endif
51 
52 // Max file size in bytes
53 #ifndef LFS1_FILE_MAX
54 #define LFS1_FILE_MAX 2147483647
55 #endif
56 
57 // Possible error codes, these are negative to allow
58 // valid positive return values
59 enum lfs1_error {
60     LFS1_ERR_OK       = 0,    // No error
61     LFS1_ERR_IO       = -5,   // Error during device operation
62     LFS1_ERR_CORRUPT  = -52,  // Corrupted
63     LFS1_ERR_NOENT    = -2,   // No directory entry
64     LFS1_ERR_EXIST    = -17,  // Entry already exists
65     LFS1_ERR_NOTDIR   = -20,  // Entry is not a dir
66     LFS1_ERR_ISDIR    = -21,  // Entry is a dir
67     LFS1_ERR_NOTEMPTY = -39,  // Dir is not empty
68     LFS1_ERR_BADF     = -9,   // Bad file number
69     LFS1_ERR_FBIG     = -27,  // File too large
70     LFS1_ERR_INVAL    = -22,  // Invalid parameter
71     LFS1_ERR_NOSPC    = -28,  // No space left on device
72     LFS1_ERR_NOMEM    = -12,  // No more memory available
73 };
74 
75 // File types
76 enum lfs1_type {
77     LFS1_TYPE_REG        = 0x11,
78     LFS1_TYPE_DIR        = 0x22,
79     LFS1_TYPE_SUPERBLOCK = 0x2e,
80 };
81 
82 // File open flags
83 enum lfs1_open_flags {
84     // open flags
85     LFS1_O_RDONLY = 1,        // Open a file as read only
86     LFS1_O_WRONLY = 2,        // Open a file as write only
87     LFS1_O_RDWR   = 3,        // Open a file as read and write
88     LFS1_O_CREAT  = 0x0100,   // Create a file if it does not exist
89     LFS1_O_EXCL   = 0x0200,   // Fail if a file already exists
90     LFS1_O_TRUNC  = 0x0400,   // Truncate the existing file to zero size
91     LFS1_O_APPEND = 0x0800,   // Move to end of file on every write
92 
93     // internally used flags
94     LFS1_F_DIRTY   = 0x10000, // File does not match storage
95     LFS1_F_WRITING = 0x20000, // File has been written since last flush
96     LFS1_F_READING = 0x40000, // File has been read since last flush
97     LFS1_F_ERRED   = 0x80000, // An error occured during write
98 };
99 
100 // File seek flags
101 enum lfs1_whence_flags {
102     LFS1_SEEK_SET = 0,   // Seek relative to an absolute position
103     LFS1_SEEK_CUR = 1,   // Seek relative to the current file position
104     LFS1_SEEK_END = 2,   // Seek relative to the end of the file
105 };
106 
107 
108 // Configuration provided during initialization of the littlefs
109 struct lfs1_config {
110     // Opaque user provided context that can be used to pass
111     // information to the block device operations
112     void *context;
113 
114     // Read a region in a block. Negative error codes are propogated
115     // to the user.
116     int (*read)(const struct lfs1_config *c, lfs1_block_t block,
117             lfs1_off_t off, void *buffer, lfs1_size_t size);
118 
119     // Program a region in a block. The block must have previously
120     // been erased. Negative error codes are propogated to the user.
121     // May return LFS1_ERR_CORRUPT if the block should be considered bad.
122     int (*prog)(const struct lfs1_config *c, lfs1_block_t block,
123             lfs1_off_t off, const void *buffer, lfs1_size_t size);
124 
125     // Erase a block. A block must be erased before being programmed.
126     // The state of an erased block is undefined. Negative error codes
127     // are propogated to the user.
128     // May return LFS1_ERR_CORRUPT if the block should be considered bad.
129     int (*erase)(const struct lfs1_config *c, lfs1_block_t block);
130 
131     // Sync the state of the underlying block device. Negative error codes
132     // are propogated to the user.
133     int (*sync)(const struct lfs1_config *c);
134 
135     // Minimum size of a block read. This determines the size of read buffers.
136     // This may be larger than the physical read size to improve performance
137     // by caching more of the block device.
138     lfs1_size_t read_size;
139 
140     // Minimum size of a block program. This determines the size of program
141     // buffers. This may be larger than the physical program size to improve
142     // performance by caching more of the block device.
143     // Must be a multiple of the read size.
144     lfs1_size_t prog_size;
145 
146     // Size of an erasable block. This does not impact ram consumption and
147     // may be larger than the physical erase size. However, this should be
148     // kept small as each file currently takes up an entire block.
149     // Must be a multiple of the program size.
150     lfs1_size_t block_size;
151 
152     // Number of erasable blocks on the device.
153     lfs1_size_t block_count;
154 
155     // Number of blocks to lookahead during block allocation. A larger
156     // lookahead reduces the number of passes required to allocate a block.
157     // The lookahead buffer requires only 1 bit per block so it can be quite
158     // large with little ram impact. Should be a multiple of 32.
159     lfs1_size_t lookahead;
160 
161     // Optional, statically allocated read buffer. Must be read sized.
162     void *read_buffer;
163 
164     // Optional, statically allocated program buffer. Must be program sized.
165     void *prog_buffer;
166 
167     // Optional, statically allocated lookahead buffer. Must be 1 bit per
168     // lookahead block.
169     void *lookahead_buffer;
170 
171     // Optional, statically allocated buffer for files. Must be program sized.
172     // If enabled, only one file may be opened at a time.
173     void *file_buffer;
174 };
175 
176 // Optional configuration provided during lfs1_file_opencfg
177 struct lfs1_file_config {
178     // Optional, statically allocated buffer for files. Must be program sized.
179     // If NULL, malloc will be used by default.
180     void *buffer;
181 };
182 
183 // File info structure
184 struct lfs1_info {
185     // Type of the file, either LFS1_TYPE_REG or LFS1_TYPE_DIR
186     uint8_t type;
187 
188     // Size of the file, only valid for REG files
189     lfs1_size_t size;
190 
191     // Name of the file stored as a null-terminated string
192     char name[LFS1_NAME_MAX+1];
193 };
194 
195 
196 /// littlefs data structures ///
197 typedef struct lfs1_entry {
198     lfs1_off_t off;
199 
200     struct lfs1_disk_entry {
201         uint8_t type;
202         uint8_t elen;
203         uint8_t alen;
204         uint8_t nlen;
205         union {
206             struct {
207                 lfs1_block_t head;
208                 lfs1_size_t size;
209             } file;
210             lfs1_block_t dir[2];
211         } u;
212     } d;
213 } lfs1_entry_t;
214 
215 typedef struct lfs1_cache {
216     lfs1_block_t block;
217     lfs1_off_t off;
218     uint8_t *buffer;
219 } lfs1_cache_t;
220 
221 typedef struct lfs1_file {
222     struct lfs1_file *next;
223     lfs1_block_t pair[2];
224     lfs1_off_t poff;
225 
226     lfs1_block_t head;
227     lfs1_size_t size;
228 
229     const struct lfs1_file_config *cfg;
230     uint32_t flags;
231     lfs1_off_t pos;
232     lfs1_block_t block;
233     lfs1_off_t off;
234     lfs1_cache_t cache;
235 } lfs1_file_t;
236 
237 typedef struct lfs1_dir {
238     struct lfs1_dir *next;
239     lfs1_block_t pair[2];
240     lfs1_off_t off;
241 
242     lfs1_block_t head[2];
243     lfs1_off_t pos;
244 
245     struct lfs1_disk_dir {
246         uint32_t rev;
247         lfs1_size_t size;
248         lfs1_block_t tail[2];
249     } d;
250 } lfs1_dir_t;
251 
252 typedef struct lfs1_superblock {
253     lfs1_off_t off;
254 
255     struct lfs1_disk_superblock {
256         uint8_t type;
257         uint8_t elen;
258         uint8_t alen;
259         uint8_t nlen;
260         lfs1_block_t root[2];
261         uint32_t block_size;
262         uint32_t block_count;
263         uint32_t version;
264         char magic[8];
265     } d;
266 } lfs1_superblock_t;
267 
268 typedef struct lfs1_free {
269     lfs1_block_t off;
270     lfs1_block_t size;
271     lfs1_block_t i;
272     lfs1_block_t ack;
273     uint32_t *buffer;
274 } lfs1_free_t;
275 
276 // The littlefs type
277 typedef struct lfs1 {
278     const struct lfs1_config *cfg;
279 
280     lfs1_block_t root[2];
281     lfs1_file_t *files;
282     lfs1_dir_t *dirs;
283 
284     lfs1_cache_t rcache;
285     lfs1_cache_t pcache;
286 
287     lfs1_free_t free;
288     bool deorphaned;
289     bool moving;
290 } lfs1_t;
291 
292 
293 /// Filesystem functions ///
294 
295 // Format a block device with the littlefs
296 //
297 // Requires a littlefs object and config struct. This clobbers the littlefs
298 // object, and does not leave the filesystem mounted. The config struct must
299 // be zeroed for defaults and backwards compatibility.
300 //
301 // Returns a negative error code on failure.
302 int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *config);
303 
304 // Mounts a littlefs
305 //
306 // Requires a littlefs object and config struct. Multiple filesystems
307 // may be mounted simultaneously with multiple littlefs objects. Both
308 // lfs1 and config must be allocated while mounted. The config struct must
309 // be zeroed for defaults and backwards compatibility.
310 //
311 // Returns a negative error code on failure.
312 int lfs1_mount(lfs1_t *lfs1, const struct lfs1_config *config);
313 
314 // Unmounts a littlefs
315 //
316 // Does nothing besides releasing any allocated resources.
317 // Returns a negative error code on failure.
318 int lfs1_unmount(lfs1_t *lfs1);
319 
320 /// General operations ///
321 
322 // Removes a file or directory
323 //
324 // If removing a directory, the directory must be empty.
325 // Returns a negative error code on failure.
326 int lfs1_remove(lfs1_t *lfs1, const char *path);
327 
328 // Rename or move a file or directory
329 //
330 // If the destination exists, it must match the source in type.
331 // If the destination is a directory, the directory must be empty.
332 //
333 // Returns a negative error code on failure.
334 int lfs1_rename(lfs1_t *lfs1, const char *oldpath, const char *newpath);
335 
336 // Find info about a file or directory
337 //
338 // Fills out the info structure, based on the specified file or directory.
339 // Returns a negative error code on failure.
340 int lfs1_stat(lfs1_t *lfs1, const char *path, struct lfs1_info *info);
341 
342 
343 /// File operations ///
344 
345 // Open a file
346 //
347 // The mode that the file is opened in is determined by the flags, which
348 // are values from the enum lfs1_open_flags that are bitwise-ored together.
349 //
350 // Returns a negative error code on failure.
351 int lfs1_file_open(lfs1_t *lfs1, lfs1_file_t *file,
352         const char *path, int flags);
353 
354 // Open a file with extra configuration
355 //
356 // The mode that the file is opened in is determined by the flags, which
357 // are values from the enum lfs1_open_flags that are bitwise-ored together.
358 //
359 // The config struct provides additional config options per file as described
360 // above. The config struct must be allocated while the file is open, and the
361 // config struct must be zeroed for defaults and backwards compatibility.
362 //
363 // Returns a negative error code on failure.
364 int lfs1_file_opencfg(lfs1_t *lfs1, lfs1_file_t *file,
365         const char *path, int flags,
366         const struct lfs1_file_config *config);
367 
368 // Close a file
369 //
370 // Any pending writes are written out to storage as though
371 // sync had been called and releases any allocated resources.
372 //
373 // Returns a negative error code on failure.
374 int lfs1_file_close(lfs1_t *lfs1, lfs1_file_t *file);
375 
376 // Synchronize a file on storage
377 //
378 // Any pending writes are written out to storage.
379 // Returns a negative error code on failure.
380 int lfs1_file_sync(lfs1_t *lfs1, lfs1_file_t *file);
381 
382 // Read data from file
383 //
384 // Takes a buffer and size indicating where to store the read data.
385 // Returns the number of bytes read, or a negative error code on failure.
386 lfs1_ssize_t lfs1_file_read(lfs1_t *lfs1, lfs1_file_t *file,
387         void *buffer, lfs1_size_t size);
388 
389 // Write data to file
390 //
391 // Takes a buffer and size indicating the data to write. The file will not
392 // actually be updated on the storage until either sync or close is called.
393 //
394 // Returns the number of bytes written, or a negative error code on failure.
395 lfs1_ssize_t lfs1_file_write(lfs1_t *lfs1, lfs1_file_t *file,
396         const void *buffer, lfs1_size_t size);
397 
398 // Change the position of the file
399 //
400 // The change in position is determined by the offset and whence flag.
401 // Returns the old position of the file, or a negative error code on failure.
402 lfs1_soff_t lfs1_file_seek(lfs1_t *lfs1, lfs1_file_t *file,
403         lfs1_soff_t off, int whence);
404 
405 // Truncates the size of the file to the specified size
406 //
407 // Returns a negative error code on failure.
408 int lfs1_file_truncate(lfs1_t *lfs1, lfs1_file_t *file, lfs1_off_t size);
409 
410 // Return the position of the file
411 //
412 // Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR)
413 // Returns the position of the file, or a negative error code on failure.
414 lfs1_soff_t lfs1_file_tell(lfs1_t *lfs1, lfs1_file_t *file);
415 
416 // Change the position of the file to the beginning of the file
417 //
418 // Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR)
419 // Returns a negative error code on failure.
420 int lfs1_file_rewind(lfs1_t *lfs1, lfs1_file_t *file);
421 
422 // Return the size of the file
423 //
424 // Similar to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_END)
425 // Returns the size of the file, or a negative error code on failure.
426 lfs1_soff_t lfs1_file_size(lfs1_t *lfs1, lfs1_file_t *file);
427 
428 
429 /// Directory operations ///
430 
431 // Create a directory
432 //
433 // Returns a negative error code on failure.
434 int lfs1_mkdir(lfs1_t *lfs1, const char *path);
435 
436 // Open a directory
437 //
438 // Once open a directory can be used with read to iterate over files.
439 // Returns a negative error code on failure.
440 int lfs1_dir_open(lfs1_t *lfs1, lfs1_dir_t *dir, const char *path);
441 
442 // Close a directory
443 //
444 // Releases any allocated resources.
445 // Returns a negative error code on failure.
446 int lfs1_dir_close(lfs1_t *lfs1, lfs1_dir_t *dir);
447 
448 // Read an entry in the directory
449 //
450 // Fills out the info structure, based on the specified file or directory.
451 // Returns a negative error code on failure.
452 int lfs1_dir_read(lfs1_t *lfs1, lfs1_dir_t *dir, struct lfs1_info *info);
453 
454 // Change the position of the directory
455 //
456 // The new off must be a value previous returned from tell and specifies
457 // an absolute offset in the directory seek.
458 //
459 // Returns a negative error code on failure.
460 int lfs1_dir_seek(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_off_t off);
461 
462 // Return the position of the directory
463 //
464 // The returned offset is only meant to be consumed by seek and may not make
465 // sense, but does indicate the current position in the directory iteration.
466 //
467 // Returns the position of the directory, or a negative error code on failure.
468 lfs1_soff_t lfs1_dir_tell(lfs1_t *lfs1, lfs1_dir_t *dir);
469 
470 // Change the position of the directory to the beginning of the directory
471 //
472 // Returns a negative error code on failure.
473 int lfs1_dir_rewind(lfs1_t *lfs1, lfs1_dir_t *dir);
474 
475 
476 /// Miscellaneous littlefs specific operations ///
477 
478 // Traverse through all blocks in use by the filesystem
479 //
480 // The provided callback will be called with each block address that is
481 // currently in use by the filesystem. This can be used to determine which
482 // blocks are in use or how much of the storage is available.
483 //
484 // Returns a negative error code on failure.
485 int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data);
486 
487 // Prunes any recoverable errors that may have occured in the filesystem
488 //
489 // Not needed to be called by user unless an operation is interrupted
490 // but the filesystem is still mounted. This is already called on first
491 // allocation.
492 //
493 // Returns a negative error code on failure.
494 int lfs1_deorphan(lfs1_t *lfs1);
495 
496 
497 #ifdef __cplusplus
498 } /* extern "C" */
499 #endif
500 
501 #endif
502