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 LFS_H
8 #define LFS_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 LFS_VERSION 0x00020002
25 #define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
26 #define LFS_VERSION_MINOR (0xffff & (LFS_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 LFS_DISK_VERSION 0x00020000
32 #define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
33 #define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >>  0))
34 
35 
36 /// Definitions ///
37 
38 // Type definitions
39 typedef uint32_t lfs_size_t;
40 typedef uint32_t lfs_off_t;
41 
42 typedef int32_t  lfs_ssize_t;
43 typedef int32_t  lfs_soff_t;
44 
45 typedef uint32_t lfs_block_t;
46 
47 // Maximum name size in bytes, may be redefined to reduce the size of the
48 // info struct. Limited to <= 1022. Stored in superblock and must be
49 // respected by other littlefs drivers.
50 #ifndef LFS_NAME_MAX
51 #define LFS_NAME_MAX 255
52 #endif
53 
54 // Maximum size of a file in bytes, may be redefined to limit to support other
55 // drivers. Limited on disk to <= 4294967296. However, above 2147483647 the
56 // functions lfs_file_seek, lfs_file_size, and lfs_file_tell will return
57 // incorrect values due to using signed integers. Stored in superblock and
58 // must be respected by other littlefs drivers.
59 #ifndef LFS_FILE_MAX
60 #define LFS_FILE_MAX 2147483647
61 #endif
62 
63 // Maximum size of custom attributes in bytes, may be redefined, but there is
64 // no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022.
65 #ifndef LFS_ATTR_MAX
66 #define LFS_ATTR_MAX 1022
67 #endif
68 
69 // Possible error codes, these are negative to allow
70 // valid positive return values
71 enum lfs_error {
72     LFS_ERR_OK          = 0,    // No error
73     LFS_ERR_IO          = -5,   // Error during device operation
74     LFS_ERR_CORRUPT     = -84,  // Corrupted
75     LFS_ERR_NOENT       = -2,   // No directory entry
76     LFS_ERR_EXIST       = -17,  // Entry already exists
77     LFS_ERR_NOTDIR      = -20,  // Entry is not a dir
78     LFS_ERR_ISDIR       = -21,  // Entry is a dir
79     LFS_ERR_NOTEMPTY    = -39,  // Dir is not empty
80     LFS_ERR_BADF        = -9,   // Bad file number
81     LFS_ERR_FBIG        = -27,  // File too large
82     LFS_ERR_INVAL       = -22,  // Invalid parameter
83     LFS_ERR_NOSPC       = -28,  // No space left on device
84     LFS_ERR_NOMEM       = -12,  // No more memory available
85     LFS_ERR_NOATTR      = -61,  // No data/attr available
86     LFS_ERR_NAMETOOLONG = -36,  // File name too long
87 };
88 
89 // File types
90 enum lfs_type {
91     // file types
92     LFS_TYPE_REG            = 0x001,
93     LFS_TYPE_DIR            = 0x002,
94 
95     // internally used types
96     LFS_TYPE_SPLICE         = 0x400,
97     LFS_TYPE_NAME           = 0x000,
98     LFS_TYPE_STRUCT         = 0x200,
99     LFS_TYPE_USERATTR       = 0x300,
100     LFS_TYPE_FROM           = 0x100,
101     LFS_TYPE_TAIL           = 0x600,
102     LFS_TYPE_GLOBALS        = 0x700,
103     LFS_TYPE_CRC            = 0x500,
104 
105     // internally used type specializations
106     LFS_TYPE_CREATE         = 0x401,
107     LFS_TYPE_DELETE         = 0x4ff,
108     LFS_TYPE_SUPERBLOCK     = 0x0ff,
109     LFS_TYPE_DIRSTRUCT      = 0x200,
110     LFS_TYPE_CTZSTRUCT      = 0x202,
111     LFS_TYPE_INLINESTRUCT   = 0x201,
112     LFS_TYPE_SOFTTAIL       = 0x600,
113     LFS_TYPE_HARDTAIL       = 0x601,
114     LFS_TYPE_MOVESTATE      = 0x7ff,
115 
116     // internal chip sources
117     LFS_FROM_NOOP           = 0x000,
118     LFS_FROM_MOVE           = 0x101,
119     LFS_FROM_USERATTRS      = 0x102,
120 };
121 
122 // File open flags
123 enum lfs_open_flags {
124     // open flags
125     LFS_O_RDONLY = 1,         // Open a file as read only
126     LFS_O_WRONLY = 2,         // Open a file as write only
127     LFS_O_RDWR   = 3,         // Open a file as read and write
128     LFS_O_CREAT  = 0x0100,    // Create a file if it does not exist
129     LFS_O_EXCL   = 0x0200,    // Fail if a file already exists
130     LFS_O_TRUNC  = 0x0400,    // Truncate the existing file to zero size
131     LFS_O_APPEND = 0x0800,    // Move to end of file on every write
132 
133     // internally used flags
134     LFS_F_DIRTY   = 0x010000, // File does not match storage
135     LFS_F_WRITING = 0x020000, // File has been written since last flush
136     LFS_F_READING = 0x040000, // File has been read since last flush
137     LFS_F_ERRED   = 0x080000, // An error occured during write
138     LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry
139     LFS_F_OPENED  = 0x200000, // File has been opened
140 };
141 
142 // File seek flags
143 enum lfs_whence_flags {
144     LFS_SEEK_SET = 0,   // Seek relative to an absolute position
145     LFS_SEEK_CUR = 1,   // Seek relative to the current file position
146     LFS_SEEK_END = 2,   // Seek relative to the end of the file
147 };
148 
149 
150 // Configuration provided during initialization of the littlefs
151 struct lfs_config {
152     // Opaque user provided context that can be used to pass
153     // information to the block device operations
154     void *context;
155 
156     // Read a region in a block. Negative error codes are propogated
157     // to the user.
158     int (*read)(const struct lfs_config *c, lfs_block_t block,
159             lfs_off_t off, void *buffer, lfs_size_t size);
160 
161     // Program a region in a block. The block must have previously
162     // been erased. Negative error codes are propogated to the user.
163     // May return LFS_ERR_CORRUPT if the block should be considered bad.
164     int (*prog)(const struct lfs_config *c, lfs_block_t block,
165             lfs_off_t off, const void *buffer, lfs_size_t size);
166 
167     // Erase a block. A block must be erased before being programmed.
168     // The state of an erased block is undefined. Negative error codes
169     // are propogated to the user.
170     // May return LFS_ERR_CORRUPT if the block should be considered bad.
171     int (*erase)(const struct lfs_config *c, lfs_block_t block);
172 
173     // Sync the state of the underlying block device. Negative error codes
174     // are propogated to the user.
175     int (*sync)(const struct lfs_config *c);
176 
177     // Minimum size of a block read. All read operations will be a
178     // multiple of this value.
179     lfs_size_t read_size;
180 
181     // Minimum size of a block program. All program operations will be a
182     // multiple of this value.
183     lfs_size_t prog_size;
184 
185     // Size of an erasable block. This does not impact ram consumption and
186     // may be larger than the physical erase size. However, non-inlined files
187     // take up at minimum one block. Must be a multiple of the read
188     // and program sizes.
189     lfs_size_t block_size;
190 
191     // Number of erasable blocks on the device.
192     lfs_size_t block_count;
193 
194     // Number of erase cycles before littlefs evicts metadata logs and moves
195     // the metadata to another block. Suggested values are in the
196     // range 100-1000, with large values having better performance at the cost
197     // of less consistent wear distribution.
198     //
199     // Set to -1 to disable block-level wear-leveling.
200     int32_t block_cycles;
201 
202     // Size of block caches. Each cache buffers a portion of a block in RAM.
203     // The littlefs needs a read cache, a program cache, and one additional
204     // cache per file. Larger caches can improve performance by storing more
205     // data and reducing the number of disk accesses. Must be a multiple of
206     // the read and program sizes, and a factor of the block size.
207     lfs_size_t cache_size;
208 
209     // Size of the lookahead buffer in bytes. A larger lookahead buffer
210     // increases the number of blocks found during an allocation pass. The
211     // lookahead buffer is stored as a compact bitmap, so each byte of RAM
212     // can track 8 blocks. Must be a multiple of 8.
213     lfs_size_t lookahead_size;
214 
215     // Optional statically allocated read buffer. Must be cache_size.
216     // By default lfs_malloc is used to allocate this buffer.
217     void *read_buffer;
218 
219     // Optional statically allocated program buffer. Must be cache_size.
220     // By default lfs_malloc is used to allocate this buffer.
221     void *prog_buffer;
222 
223     // Optional statically allocated lookahead buffer. Must be lookahead_size
224     // and aligned to a 32-bit boundary. By default lfs_malloc is used to
225     // allocate this buffer.
226     void *lookahead_buffer;
227 
228     // Optional upper limit on length of file names in bytes. No downside for
229     // larger names except the size of the info struct which is controlled by
230     // the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
231     // superblock and must be respected by other littlefs drivers.
232     lfs_size_t name_max;
233 
234     // Optional upper limit on files in bytes. No downside for larger files
235     // but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX when zero. Stored
236     // in superblock and must be respected by other littlefs drivers.
237     lfs_size_t file_max;
238 
239     // Optional upper limit on custom attributes in bytes. No downside for
240     // larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
241     // LFS_ATTR_MAX when zero.
242     lfs_size_t attr_max;
243 };
244 
245 // File info structure
246 struct lfs_info {
247     // Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
248     uint8_t type;
249 
250     // Size of the file, only valid for REG files. Limited to 32-bits.
251     lfs_size_t size;
252 
253     // Name of the file stored as a null-terminated string. Limited to
254     // LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to
255     // reduce RAM. LFS_NAME_MAX is stored in superblock and must be
256     // respected by other littlefs drivers.
257     char name[LFS_NAME_MAX+1];
258 };
259 
260 // Custom attribute structure, used to describe custom attributes
261 // committed atomically during file writes.
262 struct lfs_attr {
263     // 8-bit type of attribute, provided by user and used to
264     // identify the attribute
265     uint8_t type;
266 
267     // Pointer to buffer containing the attribute
268     void *buffer;
269 
270     // Size of attribute in bytes, limited to LFS_ATTR_MAX
271     lfs_size_t size;
272 };
273 
274 // Optional configuration provided during lfs_file_opencfg
275 struct lfs_file_config {
276     // Optional statically allocated file buffer. Must be cache_size.
277     // By default lfs_malloc is used to allocate this buffer.
278     void *buffer;
279 
280     // Optional list of custom attributes related to the file. If the file
281     // is opened with read access, these attributes will be read from disk
282     // during the open call. If the file is opened with write access, the
283     // attributes will be written to disk every file sync or close. This
284     // write occurs atomically with update to the file's contents.
285     //
286     // Custom attributes are uniquely identified by an 8-bit type and limited
287     // to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller
288     // than the buffer, it will be padded with zeros. If the stored attribute
289     // is larger, then it will be silently truncated. If the attribute is not
290     // found, it will be created implicitly.
291     struct lfs_attr *attrs;
292 
293     // Number of custom attributes in the list
294     lfs_size_t attr_count;
295 };
296 
297 
298 /// internal littlefs data structures ///
299 typedef struct lfs_cache {
300     lfs_block_t block;
301     lfs_off_t off;
302     lfs_size_t size;
303     uint8_t *buffer;
304 } lfs_cache_t;
305 
306 typedef struct lfs_mdir {
307     lfs_block_t pair[2];
308     uint32_t rev;
309     lfs_off_t off;
310     uint32_t etag;
311     uint16_t count;
312     bool erased;
313     bool split;
314     lfs_block_t tail[2];
315 } lfs_mdir_t;
316 
317 // littlefs directory type
318 typedef struct lfs_dir {
319     struct lfs_dir *next;
320     uint16_t id;
321     uint8_t type;
322     lfs_mdir_t m;
323 
324     lfs_off_t pos;
325     lfs_block_t head[2];
326 } lfs_dir_t;
327 
328 // littlefs file type
329 typedef struct lfs_file {
330     struct lfs_file *next;
331     uint16_t id;
332     uint8_t type;
333     lfs_mdir_t m;
334 
335     struct lfs_ctz {
336         lfs_block_t head;
337         lfs_size_t size;
338     } ctz;
339 
340     uint32_t flags;
341     lfs_off_t pos;
342     lfs_block_t block;
343     lfs_off_t off;
344     lfs_cache_t cache;
345 
346     const struct lfs_file_config *cfg;
347 } lfs_file_t;
348 
349 typedef struct lfs_superblock {
350     uint32_t version;
351     lfs_size_t block_size;
352     lfs_size_t block_count;
353     lfs_size_t name_max;
354     lfs_size_t file_max;
355     lfs_size_t attr_max;
356 } lfs_superblock_t;
357 
358 typedef struct lfs_gstate {
359     uint32_t tag;
360     lfs_block_t pair[2];
361 } lfs_gstate_t;
362 
363 // The littlefs filesystem type
364 typedef struct lfs {
365     lfs_cache_t rcache;
366     lfs_cache_t pcache;
367 
368     lfs_block_t root[2];
369     struct lfs_mlist {
370         struct lfs_mlist *next;
371         uint16_t id;
372         uint8_t type;
373         lfs_mdir_t m;
374     } *mlist;
375     uint32_t seed;
376 
377     lfs_gstate_t gstate;
378     lfs_gstate_t gdisk;
379     lfs_gstate_t gdelta;
380 
381     struct lfs_free {
382         lfs_block_t off;
383         lfs_block_t size;
384         lfs_block_t i;
385         lfs_block_t ack;
386         uint32_t *buffer;
387     } free;
388 
389     const struct lfs_config *cfg;
390     lfs_size_t name_max;
391     lfs_size_t file_max;
392     lfs_size_t attr_max;
393 
394 #ifdef LFS_MIGRATE
395     struct lfs1 *lfs1;
396 #endif
397 } lfs_t;
398 
399 
400 /// Filesystem functions ///
401 
402 // Format a block device with the littlefs
403 //
404 // Requires a littlefs object and config struct. This clobbers the littlefs
405 // object, and does not leave the filesystem mounted. The config struct must
406 // be zeroed for defaults and backwards compatibility.
407 //
408 // Returns a negative error code on failure.
409 int lfs_format(lfs_t *lfs, const struct lfs_config *config);
410 
411 // Mounts a littlefs
412 //
413 // Requires a littlefs object and config struct. Multiple filesystems
414 // may be mounted simultaneously with multiple littlefs objects. Both
415 // lfs and config must be allocated while mounted. The config struct must
416 // be zeroed for defaults and backwards compatibility.
417 //
418 // Returns a negative error code on failure.
419 int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
420 
421 // Unmounts a littlefs
422 //
423 // Does nothing besides releasing any allocated resources.
424 // Returns a negative error code on failure.
425 int lfs_unmount(lfs_t *lfs);
426 
427 /// General operations ///
428 
429 // Removes a file or directory
430 //
431 // If removing a directory, the directory must be empty.
432 // Returns a negative error code on failure.
433 int lfs_remove(lfs_t *lfs, const char *path);
434 
435 // Rename or move a file or directory
436 //
437 // If the destination exists, it must match the source in type.
438 // If the destination is a directory, the directory must be empty.
439 //
440 // Returns a negative error code on failure.
441 int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
442 
443 // Find info about a file or directory
444 //
445 // Fills out the info structure, based on the specified file or directory.
446 // Returns a negative error code on failure.
447 int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
448 
449 // Get a custom attribute
450 //
451 // Custom attributes are uniquely identified by an 8-bit type and limited
452 // to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
453 // the buffer, it will be padded with zeros. If the stored attribute is larger,
454 // then it will be silently truncated. If no attribute is found, the error
455 // LFS_ERR_NOATTR is returned and the buffer is filled with zeros.
456 //
457 // Returns the size of the attribute, or a negative error code on failure.
458 // Note, the returned size is the size of the attribute on disk, irrespective
459 // of the size of the buffer. This can be used to dynamically allocate a buffer
460 // or check for existance.
461 lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
462         uint8_t type, void *buffer, lfs_size_t size);
463 
464 // Set custom attributes
465 //
466 // Custom attributes are uniquely identified by an 8-bit type and limited
467 // to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
468 // implicitly created.
469 //
470 // Returns a negative error code on failure.
471 int lfs_setattr(lfs_t *lfs, const char *path,
472         uint8_t type, const void *buffer, lfs_size_t size);
473 
474 // Removes a custom attribute
475 //
476 // If an attribute is not found, nothing happens.
477 //
478 // Returns a negative error code on failure.
479 int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
480 
481 
482 /// File operations ///
483 
484 // Open a file
485 //
486 // The mode that the file is opened in is determined by the flags, which
487 // are values from the enum lfs_open_flags that are bitwise-ored together.
488 //
489 // Returns a negative error code on failure.
490 int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
491         const char *path, int flags);
492 
493 // Open a file with extra configuration
494 //
495 // The mode that the file is opened in is determined by the flags, which
496 // are values from the enum lfs_open_flags that are bitwise-ored together.
497 //
498 // The config struct provides additional config options per file as described
499 // above. The config struct must be allocated while the file is open, and the
500 // config struct must be zeroed for defaults and backwards compatibility.
501 //
502 // Returns a negative error code on failure.
503 int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
504         const char *path, int flags,
505         const struct lfs_file_config *config);
506 
507 // Close a file
508 //
509 // Any pending writes are written out to storage as though
510 // sync had been called and releases any allocated resources.
511 //
512 // Returns a negative error code on failure.
513 int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
514 
515 // Synchronize a file on storage
516 //
517 // Any pending writes are written out to storage.
518 // Returns a negative error code on failure.
519 int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
520 
521 // Read data from file
522 //
523 // Takes a buffer and size indicating where to store the read data.
524 // Returns the number of bytes read, or a negative error code on failure.
525 lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
526         void *buffer, lfs_size_t size);
527 
528 // Write data to file
529 //
530 // Takes a buffer and size indicating the data to write. The file will not
531 // actually be updated on the storage until either sync or close is called.
532 //
533 // Returns the number of bytes written, or a negative error code on failure.
534 lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
535         const void *buffer, lfs_size_t size);
536 
537 // Change the position of the file
538 //
539 // The change in position is determined by the offset and whence flag.
540 // Returns the new position of the file, or a negative error code on failure.
541 lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
542         lfs_soff_t off, int whence);
543 
544 // Truncates the size of the file to the specified size
545 //
546 // Returns a negative error code on failure.
547 int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
548 
549 // Return the position of the file
550 //
551 // Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
552 // Returns the position of the file, or a negative error code on failure.
553 lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
554 
555 // Change the position of the file to the beginning of the file
556 //
557 // Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_SET)
558 // Returns a negative error code on failure.
559 int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
560 
561 // Return the size of the file
562 //
563 // Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
564 // Returns the size of the file, or a negative error code on failure.
565 lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
566 
567 
568 /// Directory operations ///
569 
570 // Create a directory
571 //
572 // Returns a negative error code on failure.
573 int lfs_mkdir(lfs_t *lfs, const char *path);
574 
575 // Open a directory
576 //
577 // Once open a directory can be used with read to iterate over files.
578 // Returns a negative error code on failure.
579 int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
580 
581 // Close a directory
582 //
583 // Releases any allocated resources.
584 // Returns a negative error code on failure.
585 int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
586 
587 // Read an entry in the directory
588 //
589 // Fills out the info structure, based on the specified file or directory.
590 // Returns a positive value on success, 0 at the end of directory,
591 // or a negative error code on failure.
592 int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
593 
594 // Change the position of the directory
595 //
596 // The new off must be a value previous returned from tell and specifies
597 // an absolute offset in the directory seek.
598 //
599 // Returns a negative error code on failure.
600 int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
601 
602 // Return the position of the directory
603 //
604 // The returned offset is only meant to be consumed by seek and may not make
605 // sense, but does indicate the current position in the directory iteration.
606 //
607 // Returns the position of the directory, or a negative error code on failure.
608 lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
609 
610 // Change the position of the directory to the beginning of the directory
611 //
612 // Returns a negative error code on failure.
613 int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
614 
615 
616 /// Filesystem-level filesystem operations
617 
618 // Finds the current size of the filesystem
619 //
620 // Note: Result is best effort. If files share COW structures, the returned
621 // size may be larger than the filesystem actually is.
622 //
623 // Returns the number of allocated blocks, or a negative error code on failure.
624 lfs_ssize_t lfs_fs_size(lfs_t *lfs);
625 
626 // Traverse through all blocks in use by the filesystem
627 //
628 // The provided callback will be called with each block address that is
629 // currently in use by the filesystem. This can be used to determine which
630 // blocks are in use or how much of the storage is available.
631 //
632 // Returns a negative error code on failure.
633 int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
634 
635 #ifdef LFS_MIGRATE
636 // Attempts to migrate a previous version of littlefs
637 //
638 // Behaves similarly to the lfs_format function. Attempts to mount
639 // the previous version of littlefs and update the filesystem so it can be
640 // mounted with the current version of littlefs.
641 //
642 // Requires a littlefs object and config struct. This clobbers the littlefs
643 // object, and does not leave the filesystem mounted. The config struct must
644 // be zeroed for defaults and backwards compatibility.
645 //
646 // Returns a negative error code on failure.
647 int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
648 #endif
649 
650 
651 #ifdef __cplusplus
652 } /* extern "C" */
653 #endif
654 
655 #endif
656