mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 00:38:29 +01:00
Compare commits
25 Commits
fix-migrat
...
inline-fil
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21ef0b7169 | ||
|
|
fec133dfba | ||
|
|
9b4530f8de | ||
|
|
3a12b40fff | ||
|
|
12aa4bde06 | ||
|
|
09c7df83db | ||
|
|
5387f52de5 | ||
|
|
c5b11d2a62 | ||
|
|
66cdab8327 | ||
|
|
8aba03d25f | ||
|
|
9064fa6dbb | ||
|
|
fcc5c764e4 | ||
|
|
37f799d8a2 | ||
|
|
04b1103de1 | ||
|
|
87df75d009 | ||
|
|
1ea3d04d9c | ||
|
|
126f6d334e | ||
|
|
385b74944d | ||
|
|
3a10f5c29b | ||
|
|
96cca2f5b6 | ||
|
|
32f43462ea | ||
|
|
efc634f3ed | ||
|
|
2f7adc3461 | ||
|
|
e934a22c3a | ||
|
|
5937fd79dd |
128
lfs.h
128
lfs.h
@@ -27,14 +27,14 @@
|
|||||||
// Software library version
|
// Software library version
|
||||||
// Major (top-nibble), incremented on backwards incompatible changes
|
// Major (top-nibble), incremented on backwards incompatible changes
|
||||||
// Minor (bottom-nibble), incremented on feature additions
|
// Minor (bottom-nibble), incremented on feature additions
|
||||||
#define LFS_VERSION 0x00010003
|
#define LFS_VERSION 0x00010004
|
||||||
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
||||||
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
||||||
|
|
||||||
// Version of On-disk data structures
|
// Version of On-disk data structures
|
||||||
// Major (top-nibble), incremented on backwards incompatible changes
|
// Major (top-nibble), incremented on backwards incompatible changes
|
||||||
// Minor (bottom-nibble), incremented on feature additions
|
// Minor (bottom-nibble), incremented on feature additions
|
||||||
#define LFS_DISK_VERSION 0x00010001
|
#define LFS_DISK_VERSION 0x00010002
|
||||||
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
|
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
|
||||||
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
|
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
|
||||||
|
|
||||||
@@ -50,51 +50,78 @@ typedef int32_t lfs_soff_t;
|
|||||||
|
|
||||||
typedef uint32_t lfs_block_t;
|
typedef uint32_t lfs_block_t;
|
||||||
|
|
||||||
// Max name size in bytes
|
// Maximum inline file size in bytes. Large inline files require a larger
|
||||||
|
// read and prog cache, but if a file can be inline it does not need its own
|
||||||
|
// data block. LFS_ATTRS_MAX + LFS_INLINE_MAX must be <= 0xffff. Stored in
|
||||||
|
// superblock and must be respected by other littlefs drivers.
|
||||||
|
#ifndef LFS_INLINE_MAX
|
||||||
|
#define LFS_INLINE_MAX 0x3ff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Maximum size of all attributes per file in bytes, may be redefined but a
|
||||||
|
// a smaller LFS_ATTRS_MAX has no benefit. LFS_ATTRS_MAX + LFS_INLINE_MAX
|
||||||
|
// must be <= 0xffff. Stored in superblock and must be respected by other
|
||||||
|
// littlefs drivers.
|
||||||
|
#ifndef LFS_ATTRS_MAX
|
||||||
|
#define LFS_ATTRS_MAX 0x3f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Max name size in bytes, may be redefined to reduce the size of the
|
||||||
|
// info struct. Stored in superblock and must be respected by other
|
||||||
|
// littlefs drivers.
|
||||||
#ifndef LFS_NAME_MAX
|
#ifndef LFS_NAME_MAX
|
||||||
#define LFS_NAME_MAX 255
|
#define LFS_NAME_MAX 0xff
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Possible error codes, these are negative to allow
|
// Possible error codes, these are negative to allow
|
||||||
// valid positive return values
|
// valid positive return values
|
||||||
enum lfs_error {
|
enum lfs_error {
|
||||||
LFS_ERR_OK = 0, // No error
|
LFS_ERR_OK = 0, // No error
|
||||||
LFS_ERR_IO = -5, // Error during device operation
|
LFS_ERR_IO = -5, // Error during device operation
|
||||||
LFS_ERR_CORRUPT = -52, // Corrupted
|
LFS_ERR_CORRUPT = -52, // Corrupted
|
||||||
LFS_ERR_NOENT = -2, // No directory entry
|
LFS_ERR_NOENT = -2, // No directory entry
|
||||||
LFS_ERR_EXIST = -17, // Entry already exists
|
LFS_ERR_EXIST = -17, // Entry already exists
|
||||||
LFS_ERR_NOTDIR = -20, // Entry is not a dir
|
LFS_ERR_NOTDIR = -20, // Entry is not a dir
|
||||||
LFS_ERR_ISDIR = -21, // Entry is a dir
|
LFS_ERR_ISDIR = -21, // Entry is a dir
|
||||||
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
|
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
|
||||||
LFS_ERR_BADF = -9, // Bad file number
|
LFS_ERR_BADF = -9, // Bad file number
|
||||||
LFS_ERR_INVAL = -22, // Invalid parameter
|
LFS_ERR_INVAL = -22, // Invalid parameter
|
||||||
LFS_ERR_NOSPC = -28, // No space left on device
|
LFS_ERR_NOSPC = -28, // No space left on device
|
||||||
LFS_ERR_NOMEM = -12, // No more memory available
|
LFS_ERR_NOMEM = -12, // No more memory available
|
||||||
|
LFS_ERR_NAMETOOLONG = -36, // File name too long
|
||||||
};
|
};
|
||||||
|
|
||||||
// File types
|
// File types
|
||||||
enum lfs_type {
|
enum lfs_type {
|
||||||
LFS_TYPE_REG = 0x11,
|
// file type
|
||||||
LFS_TYPE_DIR = 0x22,
|
LFS_TYPE_REG = 0x01,
|
||||||
LFS_TYPE_SUPERBLOCK = 0x2e,
|
LFS_TYPE_DIR = 0x02,
|
||||||
|
LFS_TYPE_SUPERBLOCK = 0x0e,
|
||||||
|
|
||||||
|
// on disk structure
|
||||||
|
LFS_STRUCT_CTZ = 0x10,
|
||||||
|
LFS_STRUCT_DIR = 0x20,
|
||||||
|
LFS_STRUCT_INLINE = 0x30,
|
||||||
|
LFS_STRUCT_MOVED = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
// File open flags
|
// File open flags
|
||||||
enum lfs_open_flags {
|
enum lfs_open_flags {
|
||||||
// open flags
|
// open flags
|
||||||
LFS_O_RDONLY = 1, // Open a file as read only
|
LFS_O_RDONLY = 1, // Open a file as read only
|
||||||
LFS_O_WRONLY = 2, // Open a file as write only
|
LFS_O_WRONLY = 2, // Open a file as write only
|
||||||
LFS_O_RDWR = 3, // Open a file as read and write
|
LFS_O_RDWR = 3, // Open a file as read and write
|
||||||
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
|
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
|
||||||
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
||||||
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
||||||
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
||||||
|
|
||||||
// internally used flags
|
// internally used flags
|
||||||
LFS_F_DIRTY = 0x10000, // File does not match storage
|
LFS_F_DIRTY = 0x010000, // File does not match storage
|
||||||
LFS_F_WRITING = 0x20000, // File has been written since last flush
|
LFS_F_WRITING = 0x020000, // File has been written since last flush
|
||||||
LFS_F_READING = 0x40000, // File has been read since last flush
|
LFS_F_READING = 0x040000, // File has been read since last flush
|
||||||
LFS_F_ERRED = 0x80000, // An error occured during write
|
LFS_F_ERRED = 0x080000, // An error occured during write
|
||||||
|
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
|
||||||
};
|
};
|
||||||
|
|
||||||
// File seek flags
|
// File seek flags
|
||||||
@@ -171,6 +198,25 @@ struct lfs_config {
|
|||||||
// Optional, statically allocated buffer for files. Must be program sized.
|
// Optional, statically allocated buffer for files. Must be program sized.
|
||||||
// If enabled, only one file may be opened at a time.
|
// If enabled, only one file may be opened at a time.
|
||||||
void *file_buffer;
|
void *file_buffer;
|
||||||
|
|
||||||
|
// Optional upper limit on inlined files in bytes. Large inline files
|
||||||
|
// require a larger read and prog cache, but if a file can be inlined it
|
||||||
|
// does not need its own data block. Must be smaller than the read size
|
||||||
|
// and prog size. Defaults to min(LFS_INLINE_MAX, read_size) when zero.
|
||||||
|
// Stored in superblock and must be respected by other littlefs drivers.
|
||||||
|
lfs_size_t inline_size;
|
||||||
|
|
||||||
|
// Optional upper limit on attributes per file in bytes. No downside for
|
||||||
|
// larger attributes size but must be less than LFS_ATTRS_MAX. Defaults to
|
||||||
|
// LFS_ATTRS_MAX when zero.Stored in superblock and must be respected by
|
||||||
|
// other littlefs drivers.
|
||||||
|
lfs_size_t attrs_size;
|
||||||
|
|
||||||
|
// Optional upper limit on length of file names in bytes. No downside for
|
||||||
|
// larger names except the size of the info struct which is controlled by
|
||||||
|
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
|
||||||
|
// superblock and must be respected by other littlefs drivers.
|
||||||
|
lfs_size_t name_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -190,6 +236,7 @@ struct lfs_info {
|
|||||||
/// littlefs data structures ///
|
/// littlefs data structures ///
|
||||||
typedef struct lfs_entry {
|
typedef struct lfs_entry {
|
||||||
lfs_off_t off;
|
lfs_off_t off;
|
||||||
|
lfs_size_t size;
|
||||||
|
|
||||||
struct lfs_disk_entry {
|
struct lfs_disk_entry {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -221,6 +268,7 @@ typedef struct lfs_file {
|
|||||||
lfs_size_t size;
|
lfs_size_t size;
|
||||||
|
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
|
lfs_size_t inline_size;
|
||||||
lfs_off_t pos;
|
lfs_off_t pos;
|
||||||
lfs_block_t block;
|
lfs_block_t block;
|
||||||
lfs_off_t off;
|
lfs_off_t off;
|
||||||
@@ -243,18 +291,16 @@ typedef struct lfs_dir {
|
|||||||
} lfs_dir_t;
|
} lfs_dir_t;
|
||||||
|
|
||||||
typedef struct lfs_superblock {
|
typedef struct lfs_superblock {
|
||||||
lfs_off_t off;
|
|
||||||
|
|
||||||
struct lfs_disk_superblock {
|
struct lfs_disk_superblock {
|
||||||
uint8_t type;
|
|
||||||
uint8_t elen;
|
|
||||||
uint8_t alen;
|
|
||||||
uint8_t nlen;
|
|
||||||
lfs_block_t root[2];
|
lfs_block_t root[2];
|
||||||
uint32_t block_size;
|
|
||||||
uint32_t block_count;
|
lfs_size_t block_size;
|
||||||
|
lfs_size_t block_count;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
char magic[8];
|
|
||||||
|
lfs_size_t inline_size;
|
||||||
|
lfs_size_t attrs_size;
|
||||||
|
lfs_size_t name_size;
|
||||||
} d;
|
} d;
|
||||||
} lfs_superblock_t;
|
} lfs_superblock_t;
|
||||||
|
|
||||||
@@ -279,6 +325,10 @@ typedef struct lfs {
|
|||||||
|
|
||||||
lfs_free_t free;
|
lfs_free_t free;
|
||||||
bool deorphaned;
|
bool deorphaned;
|
||||||
|
|
||||||
|
lfs_size_t inline_size;
|
||||||
|
lfs_size_t attrs_size;
|
||||||
|
lfs_size_t name_size;
|
||||||
} lfs_t;
|
} lfs_t;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -274,9 +274,12 @@ TEST
|
|||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_mount(&lfs, &cfg) => 0;
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
|
||||||
// create one block whole for half a directory
|
// create one block hole for half a directory
|
||||||
lfs_file_open(&lfs, &file[0], "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
lfs_file_open(&lfs, &file[0], "bump", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
||||||
lfs_file_write(&lfs, &file[0], (void*)"hi", 2) => 2;
|
for (lfs_size_t i = 0; i < cfg.block_size; i += 2) {
|
||||||
|
memcpy(&buffer[i], "hi", 2);
|
||||||
|
}
|
||||||
|
lfs_file_write(&lfs, &file[0], buffer, cfg.block_size) => cfg.block_size;
|
||||||
lfs_file_close(&lfs, &file[0]) => 0;
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
|
||||||
lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
|
lfs_file_open(&lfs, &file[0], "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
|
||||||
@@ -289,13 +292,16 @@ tests/test.py << TEST
|
|||||||
}
|
}
|
||||||
lfs_file_close(&lfs, &file[0]) => 0;
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
|
||||||
// open whole
|
// open hole
|
||||||
lfs_remove(&lfs, "bump") => 0;
|
lfs_remove(&lfs, "bump") => 0;
|
||||||
|
|
||||||
lfs_mkdir(&lfs, "splitdir") => 0;
|
lfs_mkdir(&lfs, "splitdir") => 0;
|
||||||
lfs_file_open(&lfs, &file[0], "splitdir/bump",
|
lfs_file_open(&lfs, &file[0], "splitdir/bump",
|
||||||
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
||||||
lfs_file_write(&lfs, &file[0], buffer, size) => LFS_ERR_NOSPC;
|
for (lfs_size_t i = 0; i < cfg.block_size; i += 2) {
|
||||||
|
memcpy(&buffer[i], "hi", 2);
|
||||||
|
}
|
||||||
|
lfs_file_write(&lfs, &file[0], buffer, cfg.block_size) => LFS_ERR_NOSPC;
|
||||||
lfs_file_close(&lfs, &file[0]) => 0;
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
|
||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ lfs_mktree
|
|||||||
lfs_chktree
|
lfs_chktree
|
||||||
|
|
||||||
echo "--- Block corruption ---"
|
echo "--- Block corruption ---"
|
||||||
for i in {0..33}
|
for i in {2..33}
|
||||||
do
|
do
|
||||||
rm -rf blocks
|
rm -rf blocks
|
||||||
mkdir blocks
|
mkdir blocks
|
||||||
@@ -83,12 +83,12 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
echo "--- Block persistance ---"
|
echo "--- Block persistance ---"
|
||||||
for i in {0..33}
|
for i in {2..33}
|
||||||
do
|
do
|
||||||
rm -rf blocks
|
rm -rf blocks
|
||||||
mkdir blocks
|
mkdir blocks
|
||||||
lfs_mktree
|
lfs_mktree
|
||||||
chmod a-w blocks/$(printf '%x' $i)
|
chmod a-w blocks/$(printf '%x' $i) || true
|
||||||
lfs_mktree
|
lfs_mktree
|
||||||
lfs_chktree
|
lfs_chktree
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -30,20 +30,10 @@ echo "--- Invalid mount ---"
|
|||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_format(&lfs, &cfg) => 0;
|
lfs_format(&lfs, &cfg) => 0;
|
||||||
TEST
|
TEST
|
||||||
rm blocks/0 blocks/1
|
rm -f blocks/0 blocks/1
|
||||||
tests/test.py << TEST
|
tests/test.py << TEST
|
||||||
lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
|
lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
|
||||||
TEST
|
TEST
|
||||||
|
|
||||||
echo "--- Valid corrupt mount ---"
|
|
||||||
tests/test.py << TEST
|
|
||||||
lfs_format(&lfs, &cfg) => 0;
|
|
||||||
TEST
|
|
||||||
rm blocks/0
|
|
||||||
tests/test.py << TEST
|
|
||||||
lfs_mount(&lfs, &cfg) => 0;
|
|
||||||
lfs_unmount(&lfs) => 0;
|
|
||||||
TEST
|
|
||||||
|
|
||||||
echo "--- Results ---"
|
echo "--- Results ---"
|
||||||
tests/stats.py
|
tests/stats.py
|
||||||
|
|||||||
Reference in New Issue
Block a user