Compare commits

..

6 Commits

Author SHA1 Message Date
Christopher Haster
cb62bf2188 Fixed release script issue with fetching recent tags
Fetching all tags was triggering the pagination system inside the github
API. This prevent version tags from being found.

Modified to use the version tag prefix in the ref lookup, however this
still may cause an issue if there are still enough patch releases to trigger
pagination.

Simpleish solution is to grab the link header to jump to the last page,
since pagination results appear to be in sorted order.
2018-09-27 14:46:12 -05:00
Christopher Haster
646b1b5a6c Added -Wjump-misses-init and fixed uninitialized warnings 2018-09-26 18:58:54 -05:00
Christopher Haster
1b7a15599e Merge pull request #106 from conkerkh/master
If stats file doesn't exist lfs_emubd_create will fail.
2018-09-26 18:58:34 -05:00
Christopher Haster
e5a6938faf Fixed possible infinite loop in deorphan step
Normally, the linked-list of directory pairs should terminate at a null
pointer. However, it is possible if the filesystem is corrupted, that
that this linked-list forms a cycle.

This should never happen with littlefs's power resilience, but if it does
we should recover appropriately.

Modified lfs_deorphan to notice if we have a cycle and return
LFS_ERR_CORRUPT in that situation.

Found by kneko715
2018-09-26 18:58:11 -05:00
Chris
6ad544f3f3 If stats file doesn't exist lfs_emubd_create will fail.
This will create default stats file if it doesn't exist.
2018-09-26 18:24:58 -05:00
Christopher Haster
3419284689 Fixed issue with corruption due to different cache sizes
The lfs_cache_zero function that was recently added assumed a single cache
size, which is incorrect. This would cause a buffer overflow if
read_size != prog_size.

Since lfs_cache_zero is only used for scrubbing prog caches, the fix
here is to use lfs_cache_drop instead on read caches. Info in read
caches should never make its way to disk.

Found by nstcl
2018-09-04 13:57:22 -05:00
4 changed files with 152 additions and 129 deletions

View File

@@ -138,11 +138,13 @@ jobs:
- LFS_VERSION=$(grep -ox '#define LFS_VERSION .*' lfs.h | cut -d ' ' -f3)
- LFS_VERSION_MAJOR=$((0xffff & ($LFS_VERSION >> 16)))
- LFS_VERSION_MINOR=$((0xffff & ($LFS_VERSION >> 0)))
# Grab latests patch from repo tags, default to 0
- LFS_VERSION_PATCH=$(curl -f -u "$GEKY_BOT_RELEASES"
https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs
| jq 'map(.ref | match(
"refs/tags/v'"$LFS_VERSION_MAJOR"'\\.'"$LFS_VERSION_MINOR"'\\.(.*)$")
# Grab latests patch from repo tags, default to 0, needs finagling to get past github's pagination api
- PREV_URL=https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR.
- PREV_URL=$(curl -f -u "$GEKY_BOT_RELEASES" "$PREV_URL" -I
| sed -n '/^Link/{s/.*<\(.*\)>; rel="last"/\1/;p;q0};$q1'
|| echo $PREV_URL)
- LFS_VERSION_PATCH=$(curl -f -u "$GEKY_BOT_RELEASES" "$PREV_URL"
| jq 'map(.ref | match("\\bv.*\\..*\\.(.*)$";"g")
.captures[].string | tonumber + 1) | max // 0')
# We have our new version
- LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR.$LFS_VERSION_PATCH"

View File

@@ -25,7 +25,8 @@ ifdef WORD
override CFLAGS += -m$(WORD)
endif
override CFLAGS += -I.
override CFLAGS += -std=c99 -Wall -pedantic -Wshadow -Wunused-parameter
override CFLAGS += -std=c99 -Wall -pedantic
override CFLAGS += -Wshadow -Wunused-parameter -Wjump-misses-init
all: $(TARGET)

View File

@@ -47,19 +47,24 @@ int lfs_emubd_create(const struct lfs_config *cfg, const char *path) {
// Load stats to continue incrementing
snprintf(emu->child, LFS_NAME_MAX, "stats");
FILE *f = fopen(emu->path, "r");
if (!f) {
if (!f && errno != ENOENT) {
return -errno;
}
size_t res = fread(&emu->stats, sizeof(emu->stats), 1, f);
if (res < 1) {
return -errno;
}
if (errno == ENOENT) {
memset(&emu->stats, 0x0, sizeof(emu->stats));
} else {
size_t res = fread(&emu->stats, sizeof(emu->stats), 1, f);
if (res < 1) {
return -errno;
}
err = fclose(f);
if (err) {
return -errno;
err = fclose(f);
if (err) {
return -errno;
}
}
return 0;

245
lfs.c
View File

@@ -1373,7 +1373,10 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
}
// zero to avoid information leak
lfs_cache_zero(lfs, &file->cache);
lfs_cache_drop(lfs, &file->cache);
if ((file->flags & 3) != LFS_O_RDONLY) {
lfs_cache_zero(lfs, &file->cache);
}
// add to list of files
file->next = lfs->files;
@@ -2055,8 +2058,8 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
}
// zero to avoid information leaks
lfs_cache_zero(lfs, &lfs->rcache);
lfs_cache_zero(lfs, &lfs->pcache);
lfs_cache_drop(lfs, &lfs->rcache);
// setup lookahead, round down to nearest 32-bits
LFS_ASSERT(lfs->cfg->lookahead % 32 == 0);
@@ -2093,83 +2096,86 @@ cleanup:
}
int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
int err = lfs_init(lfs, cfg);
if (err) {
return err;
}
int err = 0;
if (true) {
err = lfs_init(lfs, cfg);
if (err) {
return err;
}
// create free lookahead
memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8);
lfs->free.off = 0;
lfs->free.size = lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count);
lfs->free.i = 0;
lfs_alloc_ack(lfs);
// create free lookahead
memset(lfs->free.buffer, 0, lfs->cfg->lookahead/8);
lfs->free.off = 0;
lfs->free.size = lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count);
lfs->free.i = 0;
lfs_alloc_ack(lfs);
// create superblock dir
lfs_dir_t superdir;
err = lfs_dir_alloc(lfs, &superdir);
if (err) {
goto cleanup;
}
// write root directory
lfs_dir_t root;
err = lfs_dir_alloc(lfs, &root);
if (err) {
goto cleanup;
}
err = lfs_dir_commit(lfs, &root, NULL, 0);
if (err) {
goto cleanup;
}
lfs->root[0] = root.pair[0];
lfs->root[1] = root.pair[1];
// write superblocks
lfs_superblock_t superblock = {
.off = sizeof(superdir.d),
.d.type = LFS_TYPE_SUPERBLOCK,
.d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4,
.d.nlen = sizeof(superblock.d.magic),
.d.version = LFS_DISK_VERSION,
.d.magic = {"littlefs"},
.d.block_size = lfs->cfg->block_size,
.d.block_count = lfs->cfg->block_count,
.d.root = {lfs->root[0], lfs->root[1]},
};
superdir.d.tail[0] = root.pair[0];
superdir.d.tail[1] = root.pair[1];
superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4;
// write both pairs to be safe
lfs_superblock_tole32(&superblock.d);
bool valid = false;
for (int i = 0; i < 2; i++) {
err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){
{sizeof(superdir.d), sizeof(superblock.d),
&superblock.d, sizeof(superblock.d)}
}, 1);
if (err && err != LFS_ERR_CORRUPT) {
// create superblock dir
lfs_dir_t superdir;
err = lfs_dir_alloc(lfs, &superdir);
if (err) {
goto cleanup;
}
valid = valid || !err;
}
// write root directory
lfs_dir_t root;
err = lfs_dir_alloc(lfs, &root);
if (err) {
goto cleanup;
}
if (!valid) {
err = LFS_ERR_CORRUPT;
goto cleanup;
}
err = lfs_dir_commit(lfs, &root, NULL, 0);
if (err) {
goto cleanup;
}
// sanity check that fetch works
err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
if (err) {
goto cleanup;
}
lfs->root[0] = root.pair[0];
lfs->root[1] = root.pair[1];
lfs_alloc_ack(lfs);
// write superblocks
lfs_superblock_t superblock = {
.off = sizeof(superdir.d),
.d.type = LFS_TYPE_SUPERBLOCK,
.d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4,
.d.nlen = sizeof(superblock.d.magic),
.d.version = LFS_DISK_VERSION,
.d.magic = {"littlefs"},
.d.block_size = lfs->cfg->block_size,
.d.block_count = lfs->cfg->block_count,
.d.root = {lfs->root[0], lfs->root[1]},
};
superdir.d.tail[0] = root.pair[0];
superdir.d.tail[1] = root.pair[1];
superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4;
// write both pairs to be safe
lfs_superblock_tole32(&superblock.d);
bool valid = false;
for (int i = 0; i < 2; i++) {
err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){
{sizeof(superdir.d), sizeof(superblock.d),
&superblock.d, sizeof(superblock.d)}
}, 1);
if (err && err != LFS_ERR_CORRUPT) {
goto cleanup;
}
valid = valid || !err;
}
if (!valid) {
err = LFS_ERR_CORRUPT;
goto cleanup;
}
// sanity check that fetch works
err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
if (err) {
goto cleanup;
}
lfs_alloc_ack(lfs);
}
cleanup:
lfs_deinit(lfs);
@@ -2177,53 +2183,56 @@ cleanup:
}
int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
int err = lfs_init(lfs, cfg);
if (err) {
return err;
}
// setup free lookahead
lfs->free.off = 0;
lfs->free.size = 0;
lfs->free.i = 0;
lfs_alloc_ack(lfs);
// load superblock
lfs_dir_t dir;
lfs_superblock_t superblock;
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
if (err && err != LFS_ERR_CORRUPT) {
goto cleanup;
}
if (!err) {
err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d),
&superblock.d, sizeof(superblock.d));
lfs_superblock_fromle32(&superblock.d);
int err = 0;
if (true) {
err = lfs_init(lfs, cfg);
if (err) {
return err;
}
// setup free lookahead
lfs->free.off = 0;
lfs->free.size = 0;
lfs->free.i = 0;
lfs_alloc_ack(lfs);
// load superblock
lfs_dir_t dir;
lfs_superblock_t superblock;
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
if (err && err != LFS_ERR_CORRUPT) {
goto cleanup;
}
lfs->root[0] = superblock.d.root[0];
lfs->root[1] = superblock.d.root[1];
}
if (!err) {
err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d),
&superblock.d, sizeof(superblock.d));
lfs_superblock_fromle32(&superblock.d);
if (err) {
goto cleanup;
}
if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
err = LFS_ERR_CORRUPT;
goto cleanup;
}
lfs->root[0] = superblock.d.root[0];
lfs->root[1] = superblock.d.root[1];
}
uint16_t major_version = (0xffff & (superblock.d.version >> 16));
uint16_t minor_version = (0xffff & (superblock.d.version >> 0));
if ((major_version != LFS_DISK_VERSION_MAJOR ||
minor_version > LFS_DISK_VERSION_MINOR)) {
LFS_ERROR("Invalid version %d.%d", major_version, minor_version);
err = LFS_ERR_INVAL;
goto cleanup;
}
if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
err = LFS_ERR_CORRUPT;
goto cleanup;
}
return 0;
uint16_t major_version = (0xffff & (superblock.d.version >> 16));
uint16_t minor_version = (0xffff & (superblock.d.version >> 0));
if ((major_version != LFS_DISK_VERSION_MAJOR ||
minor_version > LFS_DISK_VERSION_MINOR)) {
LFS_ERROR("Invalid version %d.%d", major_version, minor_version);
err = LFS_ERR_INVAL;
goto cleanup;
}
return 0;
}
cleanup:
@@ -2472,7 +2481,11 @@ int lfs_deorphan(lfs_t *lfs) {
lfs_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1};
// iterate over all directory directory entries
while (!lfs_pairisnull(cwd.d.tail)) {
for (int i = 0; i < lfs->cfg->block_count; i++) {
if (lfs_pairisnull(cwd.d.tail)) {
return 0;
}
int err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail);
if (err) {
return err;
@@ -2501,7 +2514,7 @@ int lfs_deorphan(lfs_t *lfs) {
return err;
}
break;
return 0;
}
if (!lfs_pairsync(entry.d.u.dir, pdir.d.tail)) {
@@ -2517,7 +2530,7 @@ int lfs_deorphan(lfs_t *lfs) {
return err;
}
break;
return 0;
}
}
@@ -2562,5 +2575,7 @@ int lfs_deorphan(lfs_t *lfs) {
memcpy(&pdir, &cwd, sizeof(pdir));
}
return 0;
// If we reached here, we have more directory pairs than blocks in the
// filesystem... So something must be horribly wrong
return LFS_ERR_CORRUPT;
}