mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-02 00:38:28 +01:00
Compare commits
24 Commits
v2.0.0
...
fix-file-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb2e35143e | ||
|
|
abd90cb84c | ||
|
|
b73ac594f2 | ||
|
|
614f7b1e68 | ||
|
|
a9a61a3e78 | ||
|
|
36973d8fd5 | ||
|
|
f06dc5737f | ||
|
|
3fb242f3ae | ||
|
|
ef77195a64 | ||
|
|
12e464e9c3 | ||
|
|
9899c7fe48 | ||
|
|
bc7bed740b | ||
|
|
cf9afdddff | ||
|
|
2533a0f6d6 | ||
|
|
2a7f0ed11b | ||
|
|
f35fb8c148 | ||
|
|
0a1f706ca2 | ||
|
|
fdd239fe21 | ||
|
|
780ef2fce4 | ||
|
|
73ea008b74 | ||
|
|
c849748453 | ||
|
|
25a843aab7 | ||
|
|
905727b684 | ||
|
|
26d25608b6 |
20
.travis.yml
20
.travis.yml
@@ -66,7 +66,10 @@ jobs:
|
|||||||
- CC="arm-linux-gnueabi-gcc --static -mthumb"
|
- CC="arm-linux-gnueabi-gcc --static -mthumb"
|
||||||
- EXEC="qemu-arm"
|
- EXEC="qemu-arm"
|
||||||
install:
|
install:
|
||||||
- sudo apt-get install gcc-arm-linux-gnueabi qemu-user
|
- sudo apt-get install
|
||||||
|
gcc-arm-linux-gnueabi
|
||||||
|
libc6-dev-armel-cross
|
||||||
|
qemu-user
|
||||||
- arm-linux-gnueabi-gcc --version
|
- arm-linux-gnueabi-gcc --version
|
||||||
- qemu-arm -version
|
- qemu-arm -version
|
||||||
|
|
||||||
@@ -78,7 +81,10 @@ jobs:
|
|||||||
- CC="powerpc-linux-gnu-gcc --static"
|
- CC="powerpc-linux-gnu-gcc --static"
|
||||||
- EXEC="qemu-ppc"
|
- EXEC="qemu-ppc"
|
||||||
install:
|
install:
|
||||||
- sudo apt-get install gcc-powerpc-linux-gnu qemu-user
|
- sudo apt-get install
|
||||||
|
gcc-powerpc-linux-gnu
|
||||||
|
libc6-dev-powerpc-cross
|
||||||
|
qemu-user
|
||||||
- powerpc-linux-gnu-gcc --version
|
- powerpc-linux-gnu-gcc --version
|
||||||
- qemu-ppc -version
|
- qemu-ppc -version
|
||||||
|
|
||||||
@@ -90,9 +96,10 @@ jobs:
|
|||||||
- CC="mips-linux-gnu-gcc --static"
|
- CC="mips-linux-gnu-gcc --static"
|
||||||
- EXEC="qemu-mips"
|
- EXEC="qemu-mips"
|
||||||
install:
|
install:
|
||||||
- sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ xenial main universe"
|
- sudo apt-get install
|
||||||
- sudo apt-get -qq update
|
gcc-mips-linux-gnu
|
||||||
- sudo apt-get install gcc-mips-linux-gnu qemu-user
|
libc6-dev-mips-cross
|
||||||
|
qemu-user
|
||||||
- mips-linux-gnu-gcc --version
|
- mips-linux-gnu-gcc --version
|
||||||
- qemu-mips -version
|
- qemu-mips -version
|
||||||
|
|
||||||
@@ -136,10 +143,11 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
- STAGE=test
|
- STAGE=test
|
||||||
- NAME=littlefs-migration
|
- NAME=littlefs-migration
|
||||||
|
if: branch !~ -prefix$
|
||||||
install:
|
install:
|
||||||
- sudo apt-get install libfuse-dev
|
- sudo apt-get install libfuse-dev
|
||||||
- git clone --depth 1 https://github.com/geky/littlefs-fuse -b v2-alpha v2
|
- git clone --depth 1 https://github.com/geky/littlefs-fuse -b v2-alpha v2
|
||||||
- git clone --depth 1 https://github.com/geky/littlefs-fuse v1
|
- git clone --depth 1 https://github.com/geky/littlefs-fuse -b v1 v1
|
||||||
- fusermount -V
|
- fusermount -V
|
||||||
- gcc --version
|
- gcc --version
|
||||||
before_script:
|
before_script:
|
||||||
|
|||||||
103
lfs.c
103
lfs.c
@@ -29,7 +29,7 @@ static inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) {
|
|||||||
|
|
||||||
static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) {
|
static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) {
|
||||||
// zero to avoid information leak
|
// zero to avoid information leak
|
||||||
memset(pcache->buffer, 0xff, lfs->cfg->prog_size);
|
memset(pcache->buffer, 0xff, lfs->cfg->cache_size);
|
||||||
pcache->block = 0xffffffff;
|
pcache->block = 0xffffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,28 +80,16 @@ static int lfs_bd_read(lfs_t *lfs,
|
|||||||
diff = lfs_min(diff, rcache->off-off);
|
diff = lfs_min(diff, rcache->off-off);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size >= hint && off % lfs->cfg->read_size == 0 &&
|
|
||||||
size >= lfs->cfg->read_size) {
|
|
||||||
// bypass cache?
|
|
||||||
diff = lfs_aligndown(diff, lfs->cfg->read_size);
|
|
||||||
int err = lfs->cfg->read(lfs->cfg, block, off, data, diff);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
data += diff;
|
|
||||||
off += diff;
|
|
||||||
size -= diff;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load to cache, first condition can no longer fail
|
// load to cache, first condition can no longer fail
|
||||||
LFS_ASSERT(block < lfs->cfg->block_count);
|
LFS_ASSERT(block < lfs->cfg->block_count);
|
||||||
rcache->block = block;
|
rcache->block = block;
|
||||||
rcache->off = lfs_aligndown(off, lfs->cfg->read_size);
|
rcache->off = lfs_aligndown(off, lfs->cfg->read_size);
|
||||||
rcache->size = lfs_min(lfs_alignup(off+hint, lfs->cfg->read_size),
|
rcache->size = lfs_min(
|
||||||
lfs_min(lfs->cfg->block_size - rcache->off,
|
lfs_min(
|
||||||
lfs->cfg->cache_size));
|
lfs_alignup(off+hint, lfs->cfg->read_size),
|
||||||
|
lfs->cfg->block_size)
|
||||||
|
- rcache->off,
|
||||||
|
lfs->cfg->cache_size);
|
||||||
int err = lfs->cfg->read(lfs->cfg, rcache->block,
|
int err = lfs->cfg->read(lfs->cfg, rcache->block,
|
||||||
rcache->off, rcache->buffer, rcache->size);
|
rcache->off, rcache->buffer, rcache->size);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -206,7 +194,7 @@ static int lfs_bd_prog(lfs_t *lfs,
|
|||||||
off += diff;
|
off += diff;
|
||||||
size -= diff;
|
size -= diff;
|
||||||
|
|
||||||
pcache->size = off - pcache->off;
|
pcache->size = lfs_max(pcache->size, off - pcache->off);
|
||||||
if (pcache->size == lfs->cfg->cache_size) {
|
if (pcache->size == lfs->cfg->cache_size) {
|
||||||
// eagerly flush out pcache if we fill up
|
// eagerly flush out pcache if we fill up
|
||||||
int err = lfs_bd_flush(lfs, pcache, rcache, validate);
|
int err = lfs_bd_flush(lfs, pcache, rcache, validate);
|
||||||
@@ -427,6 +415,7 @@ static int lfs_dir_compact(lfs_t *lfs,
|
|||||||
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
|
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
|
||||||
lfs_mdir_t *source, uint16_t begin, uint16_t end);
|
lfs_mdir_t *source, uint16_t begin, uint16_t end);
|
||||||
static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file);
|
static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file);
|
||||||
|
static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);
|
||||||
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
|
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
|
||||||
static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans);
|
static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans);
|
||||||
static void lfs_fs_prepmove(lfs_t *lfs,
|
static void lfs_fs_prepmove(lfs_t *lfs,
|
||||||
@@ -629,7 +618,7 @@ static int lfs_dir_getread(lfs_t *lfs, const lfs_mdir_t *dir,
|
|||||||
lfs->cfg->cache_size);
|
lfs->cfg->cache_size);
|
||||||
int err = lfs_dir_getslice(lfs, dir, gmask, gtag,
|
int err = lfs_dir_getslice(lfs, dir, gmask, gtag,
|
||||||
rcache->off, rcache->buffer, rcache->size);
|
rcache->off, rcache->buffer, rcache->size);
|
||||||
if (err) {
|
if (err < 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -645,8 +634,9 @@ static int lfs_dir_traverse_filter(void *p,
|
|||||||
// check for redundancy
|
// check for redundancy
|
||||||
uint32_t mask = LFS_MKTAG(0x7ff, 0x3ff, 0);
|
uint32_t mask = LFS_MKTAG(0x7ff, 0x3ff, 0);
|
||||||
if ((mask & tag) == (mask & *filtertag) ||
|
if ((mask & tag) == (mask & *filtertag) ||
|
||||||
(mask & tag) == (LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) |
|
lfs_tag_isdelete(*filtertag) ||
|
||||||
(LFS_MKTAG(0, 0x3ff, 0) & *filtertag))) {
|
(mask & tag) == (LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) |
|
||||||
|
(LFS_MKTAG(0, 0x3ff, 0) & *filtertag))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1655,11 +1645,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
|
|||||||
if (dir != &f->m && lfs_pair_cmp(f->m.pair, dir->pair) == 0 &&
|
if (dir != &f->m && lfs_pair_cmp(f->m.pair, dir->pair) == 0 &&
|
||||||
f->type == LFS_TYPE_REG && (f->flags & LFS_F_INLINE) &&
|
f->type == LFS_TYPE_REG && (f->flags & LFS_F_INLINE) &&
|
||||||
f->ctz.size > lfs->cfg->cache_size) {
|
f->ctz.size > lfs->cfg->cache_size) {
|
||||||
f->flags &= ~LFS_F_READING;
|
int err = lfs_file_outline(lfs, f);
|
||||||
f->off = 0;
|
|
||||||
|
|
||||||
lfs_alloc_ack(lfs);
|
|
||||||
int err = lfs_file_relocate(lfs, f);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -2485,7 +2471,6 @@ static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
|
|||||||
lfs_cache_zero(lfs, &lfs->pcache);
|
lfs_cache_zero(lfs, &lfs->pcache);
|
||||||
|
|
||||||
file->block = nblock;
|
file->block = nblock;
|
||||||
file->flags &= ~LFS_F_INLINE;
|
|
||||||
file->flags |= LFS_F_WRITING;
|
file->flags |= LFS_F_WRITING;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -2497,6 +2482,19 @@ relocate:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
|
||||||
|
file->off = file->pos;
|
||||||
|
lfs_alloc_ack(lfs);
|
||||||
|
int err = lfs_file_relocate(lfs, file);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->flags &= ~LFS_F_INLINE;
|
||||||
|
file->flags |= LFS_F_OUTLINE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
|
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
|
||||||
if (file->flags & LFS_F_READING) {
|
if (file->flags & LFS_F_READING) {
|
||||||
if (!(file->flags & LFS_F_INLINE)) {
|
if (!(file->flags & LFS_F_INLINE)) {
|
||||||
@@ -2560,7 +2558,7 @@ relocate:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file->ctz.size = lfs_max(file->pos, file->ctz.size);
|
file->pos = lfs_max(file->pos, file->ctz.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// actual file updates
|
// actual file updates
|
||||||
@@ -2608,6 +2606,9 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
|
|||||||
|
|
||||||
// commit file data and attributes
|
// commit file data and attributes
|
||||||
err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(
|
err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(
|
||||||
|
{file->flags & LFS_F_OUTLINE
|
||||||
|
? LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0x3ff)
|
||||||
|
: LFS_MKTAG(LFS_FROM_NOOP, 0, 0), NULL},
|
||||||
{LFS_MKTAG(type, file->id, size), buffer},
|
{LFS_MKTAG(type, file->id, size), buffer},
|
||||||
{LFS_MKTAG(LFS_FROM_USERATTRS, file->id,
|
{LFS_MKTAG(LFS_FROM_USERATTRS, file->id,
|
||||||
file->cfg->attr_count), file->cfg->attrs}));
|
file->cfg->attr_count), file->cfg->attrs}));
|
||||||
@@ -2619,15 +2620,14 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
file->flags &= ~LFS_F_DIRTY;
|
file->flags &= ~LFS_F_DIRTY & ~LFS_F_OUTLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
relocate:
|
relocate:
|
||||||
// inline file doesn't fit anymore
|
// inline file doesn't fit anymore
|
||||||
file->off = file->pos;
|
err = lfs_file_outline(lfs, file);
|
||||||
err = lfs_file_relocate(lfs, file);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
file->flags |= LFS_F_ERRED;
|
file->flags |= LFS_F_ERRED;
|
||||||
return err;
|
return err;
|
||||||
@@ -2749,12 +2749,10 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
|||||||
|
|
||||||
if ((file->flags & LFS_F_INLINE) &&
|
if ((file->flags & LFS_F_INLINE) &&
|
||||||
lfs_max(file->pos+nsize, file->ctz.size) >
|
lfs_max(file->pos+nsize, file->ctz.size) >
|
||||||
lfs_min(LFS_ATTR_MAX, lfs_min(
|
lfs_min(0x3fe, lfs_min(
|
||||||
lfs->cfg->cache_size, lfs->cfg->block_size/8))) {
|
lfs->cfg->cache_size, lfs->cfg->block_size/8))) {
|
||||||
// inline file doesn't fit anymore
|
// inline file doesn't fit anymore
|
||||||
file->off = file->pos;
|
int err = lfs_file_outline(lfs, file);
|
||||||
lfs_alloc_ack(lfs);
|
|
||||||
int err = lfs_file_relocate(lfs, file);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
file->flags |= LFS_F_ERRED;
|
file->flags |= LFS_F_ERRED;
|
||||||
return err;
|
return err;
|
||||||
@@ -2864,6 +2862,10 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
|||||||
return LFS_ERR_BADF;
|
return LFS_ERR_BADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size > LFS_FILE_MAX) {
|
||||||
|
return LFS_ERR_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
lfs_off_t oldsize = lfs_file_size(lfs, file);
|
lfs_off_t oldsize = lfs_file_size(lfs, file);
|
||||||
if (size < oldsize) {
|
if (size < oldsize) {
|
||||||
// need to flush since directly changing metadata
|
// need to flush since directly changing metadata
|
||||||
@@ -2875,13 +2877,14 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
|||||||
// lookup new head in ctz skip list
|
// lookup new head in ctz skip list
|
||||||
err = lfs_ctz_find(lfs, NULL, &file->cache,
|
err = lfs_ctz_find(lfs, NULL, &file->cache,
|
||||||
file->ctz.head, file->ctz.size,
|
file->ctz.head, file->ctz.size,
|
||||||
size, &file->ctz.head, &(lfs_off_t){0});
|
size, &file->block, &file->off);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file->ctz.head = file->block;
|
||||||
file->ctz.size = size;
|
file->ctz.size = size;
|
||||||
file->flags |= LFS_F_DIRTY;
|
file->flags |= LFS_F_DIRTY | LFS_F_READING;
|
||||||
} else if (size > oldsize) {
|
} else if (size > oldsize) {
|
||||||
lfs_off_t pos = file->pos;
|
lfs_off_t pos = file->pos;
|
||||||
|
|
||||||
@@ -3345,6 +3348,14 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
if (err) {
|
if (err) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// force compaction to prevent accidentally mounting any
|
||||||
|
// older version of littlefs that may live on disk
|
||||||
|
root.erased = false;
|
||||||
|
err = lfs_dir_commit(lfs, &root, NULL, 0);
|
||||||
|
if (err) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@@ -3911,7 +3922,7 @@ typedef struct lfs1_superblock {
|
|||||||
|
|
||||||
|
|
||||||
/// Low-level wrappers v1->v2 ///
|
/// Low-level wrappers v1->v2 ///
|
||||||
void lfs1_crc(uint32_t *crc, const void *buffer, size_t size) {
|
static void lfs1_crc(uint32_t *crc, const void *buffer, size_t size) {
|
||||||
*crc = lfs_crc(*crc, buffer, size);
|
*crc = lfs_crc(*crc, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4406,6 +4417,11 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = lfs_bd_flush(lfs, &lfs->pcache, &lfs->rcache, true);
|
||||||
|
if (err) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new superblock. This marks a successful migration!
|
// Create new superblock. This marks a successful migration!
|
||||||
@@ -4449,6 +4465,13 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
if (err) {
|
if (err) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// force compaction to prevent accidentally mounting v1
|
||||||
|
dir2.erased = false;
|
||||||
|
err = lfs_dir_commit(lfs, &dir2, NULL, 0);
|
||||||
|
if (err) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|||||||
18
lfs.h
18
lfs.h
@@ -122,13 +122,13 @@ enum lfs_type {
|
|||||||
// 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 = 0x010000, // File does not match storage
|
LFS_F_DIRTY = 0x010000, // File does not match storage
|
||||||
@@ -136,6 +136,7 @@ enum lfs_open_flags {
|
|||||||
LFS_F_READING = 0x040000, // File has been read since last flush
|
LFS_F_READING = 0x040000, // File has been read since last flush
|
||||||
LFS_F_ERRED = 0x080000, // An error occured during write
|
LFS_F_ERRED = 0x080000, // An error occured during write
|
||||||
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
|
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
|
||||||
|
LFS_F_OUTLINE = 0x200000, // Need to delete inlined directory entry
|
||||||
};
|
};
|
||||||
|
|
||||||
// File seek flags
|
// File seek flags
|
||||||
@@ -578,7 +579,8 @@ int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
|
|||||||
// Read an entry in the directory
|
// Read an entry in the directory
|
||||||
//
|
//
|
||||||
// Fills out the info structure, based on the specified file or directory.
|
// Fills out the info structure, based on the specified file or directory.
|
||||||
// Returns a negative error code on failure.
|
// Returns a positive value on success, 0 at the end of directory,
|
||||||
|
// or a negative error code on failure.
|
||||||
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
|
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
|
||||||
|
|
||||||
// Change the position of the directory
|
// Change the position of the directory
|
||||||
|
|||||||
24
lfs_util.h
24
lfs_util.h
@@ -143,14 +143,14 @@ static inline int lfs_scmp(uint32_t a, uint32_t b) {
|
|||||||
// Convert between 32-bit little-endian and native order
|
// Convert between 32-bit little-endian and native order
|
||||||
static inline uint32_t lfs_fromle32(uint32_t a) {
|
static inline uint32_t lfs_fromle32(uint32_t a) {
|
||||||
#if !defined(LFS_NO_INTRINSICS) && ( \
|
#if !defined(LFS_NO_INTRINSICS) && ( \
|
||||||
(defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||||
return a;
|
return a;
|
||||||
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
||||||
(defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||||
return __builtin_bswap32(a);
|
return __builtin_bswap32(a);
|
||||||
#else
|
#else
|
||||||
return (((uint8_t*)&a)[0] << 0) |
|
return (((uint8_t*)&a)[0] << 0) |
|
||||||
@@ -167,14 +167,14 @@ static inline uint32_t lfs_tole32(uint32_t a) {
|
|||||||
// Convert between 32-bit big-endian and native order
|
// Convert between 32-bit big-endian and native order
|
||||||
static inline uint32_t lfs_frombe32(uint32_t a) {
|
static inline uint32_t lfs_frombe32(uint32_t a) {
|
||||||
#if !defined(LFS_NO_INTRINSICS) && ( \
|
#if !defined(LFS_NO_INTRINSICS) && ( \
|
||||||
(defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||||
return __builtin_bswap32(a);
|
return __builtin_bswap32(a);
|
||||||
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
||||||
(defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||||
return a;
|
return a;
|
||||||
#else
|
#else
|
||||||
return (((uint8_t*)&a)[0] << 24) |
|
return (((uint8_t*)&a)[0] << 24) |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
# This script replaces prefixes of files, and symbols in that file.
|
# This script replaces prefixes of files, and symbols in that file.
|
||||||
# Useful for creating different versions of the codebase that don't
|
# Useful for creating different versions of the codebase that don't
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@@ -357,5 +357,73 @@ tests/test.py << TEST
|
|||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
TEST
|
TEST
|
||||||
|
|
||||||
|
echo "--- Inline write and seek ---"
|
||||||
|
for SIZE in $SMALLSIZE $MEDIUMSIZE $LARGESIZE
|
||||||
|
do
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "hello/tinykitty$SIZE",
|
||||||
|
LFS_O_RDWR | LFS_O_CREAT) => 0;
|
||||||
|
int j = 0;
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
memcpy(buffer, "abcdefghijklmnopqrstuvwxyz", 26);
|
||||||
|
for (unsigned i = 0; i < $SIZE; i++) {
|
||||||
|
lfs_file_write(&lfs, &file[0], &buffer[j++ % 26], 1) => 1;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => i+1;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => i+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_SET) => 0;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
for (unsigned i = 0; i < $SIZE; i++) {
|
||||||
|
uint8_t c;
|
||||||
|
lfs_file_read(&lfs, &file[0], &c, 1) => 1;
|
||||||
|
c => buffer[k++ % 26];
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_file_sync(&lfs, &file[0]) => 0;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => $SIZE;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
|
||||||
|
lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_SET) => 0;
|
||||||
|
for (unsigned i = 0; i < $SIZE; i++) {
|
||||||
|
lfs_file_write(&lfs, &file[0], &buffer[j++ % 26], 1) => 1;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => i+1;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
lfs_file_sync(&lfs, &file[0]) => 0;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => i+1;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
if (i < $SIZE-2) {
|
||||||
|
uint8_t c[3];
|
||||||
|
lfs_file_seek(&lfs, &file[0], -1, LFS_SEEK_CUR) => i;
|
||||||
|
lfs_file_read(&lfs, &file[0], &c, 3) => 3;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => i+3;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
lfs_file_seek(&lfs, &file[0], i+1, LFS_SEEK_SET) => i+1;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => i+1;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_SET) => 0;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
for (unsigned i = 0; i < $SIZE; i++) {
|
||||||
|
uint8_t c;
|
||||||
|
lfs_file_read(&lfs, &file[0], &c, 1) => 1;
|
||||||
|
c => buffer[k++ % 26];
|
||||||
|
}
|
||||||
|
|
||||||
|
lfs_file_sync(&lfs, &file[0]) => 0;
|
||||||
|
lfs_file_tell(&lfs, &file[0]) => $SIZE;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $SIZE;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
done
|
||||||
|
|
||||||
echo "--- Results ---"
|
echo "--- Results ---"
|
||||||
tests/stats.py
|
tests/stats.py
|
||||||
|
|||||||
@@ -11,6 +11,150 @@ tests/test.py << TEST
|
|||||||
lfs_format(&lfs, &cfg) => 0;
|
lfs_format(&lfs, &cfg) => 0;
|
||||||
TEST
|
TEST
|
||||||
|
|
||||||
|
echo "--- Simple truncate ---"
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldynoop",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
||||||
|
|
||||||
|
strcpy((char*)buffer, "hair");
|
||||||
|
size = strlen((char*)buffer);
|
||||||
|
for (lfs_off_t j = 0; j < $LARGESIZE; j += size) {
|
||||||
|
lfs_file_write(&lfs, &file[0], buffer, size) => size;
|
||||||
|
}
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $LARGESIZE;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldynoop", LFS_O_RDWR) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $LARGESIZE;
|
||||||
|
|
||||||
|
lfs_file_truncate(&lfs, &file[0], $MEDIUMSIZE) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $MEDIUMSIZE;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldynoop", LFS_O_RDONLY) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $MEDIUMSIZE;
|
||||||
|
|
||||||
|
size = strlen("hair");
|
||||||
|
for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) {
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "hair", size) => 0;
|
||||||
|
}
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => 0;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
|
||||||
|
echo "--- Truncate and read ---"
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldyread",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
||||||
|
|
||||||
|
strcpy((char*)buffer, "hair");
|
||||||
|
size = strlen((char*)buffer);
|
||||||
|
for (lfs_off_t j = 0; j < $LARGESIZE; j += size) {
|
||||||
|
lfs_file_write(&lfs, &file[0], buffer, size) => size;
|
||||||
|
}
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $LARGESIZE;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldyread", LFS_O_RDWR) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $LARGESIZE;
|
||||||
|
|
||||||
|
lfs_file_truncate(&lfs, &file[0], $MEDIUMSIZE) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $MEDIUMSIZE;
|
||||||
|
|
||||||
|
size = strlen("hair");
|
||||||
|
for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) {
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "hair", size) => 0;
|
||||||
|
}
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => 0;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldyread", LFS_O_RDONLY) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $MEDIUMSIZE;
|
||||||
|
|
||||||
|
size = strlen("hair");
|
||||||
|
for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) {
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "hair", size) => 0;
|
||||||
|
}
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => 0;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
|
||||||
|
echo "--- Truncate and write ---"
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldywrite",
|
||||||
|
LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
||||||
|
|
||||||
|
strcpy((char*)buffer, "hair");
|
||||||
|
size = strlen((char*)buffer);
|
||||||
|
for (lfs_off_t j = 0; j < $LARGESIZE; j += size) {
|
||||||
|
lfs_file_write(&lfs, &file[0], buffer, size) => size;
|
||||||
|
}
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $LARGESIZE;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldywrite", LFS_O_RDWR) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $LARGESIZE;
|
||||||
|
|
||||||
|
lfs_file_truncate(&lfs, &file[0], $MEDIUMSIZE) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $MEDIUMSIZE;
|
||||||
|
|
||||||
|
strcpy((char*)buffer, "bald");
|
||||||
|
size = strlen((char*)buffer);
|
||||||
|
for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) {
|
||||||
|
lfs_file_write(&lfs, &file[0], buffer, size) => size;
|
||||||
|
}
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $MEDIUMSIZE;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
tests/test.py << TEST
|
||||||
|
lfs_mount(&lfs, &cfg) => 0;
|
||||||
|
lfs_file_open(&lfs, &file[0], "baldywrite", LFS_O_RDONLY) => 0;
|
||||||
|
lfs_file_size(&lfs, &file[0]) => $MEDIUMSIZE;
|
||||||
|
|
||||||
|
size = strlen("bald");
|
||||||
|
for (lfs_off_t j = 0; j < $MEDIUMSIZE; j += size) {
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => size;
|
||||||
|
memcmp(buffer, "bald", size) => 0;
|
||||||
|
}
|
||||||
|
lfs_file_read(&lfs, &file[0], buffer, size) => 0;
|
||||||
|
|
||||||
|
lfs_file_close(&lfs, &file[0]) => 0;
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
TEST
|
||||||
|
|
||||||
|
# More aggressive general truncation tests
|
||||||
truncate_test() {
|
truncate_test() {
|
||||||
STARTSIZES="$1"
|
STARTSIZES="$1"
|
||||||
STARTSEEKS="$2"
|
STARTSEEKS="$2"
|
||||||
|
|||||||
Reference in New Issue
Block a user