Compare commits

..

2 Commits

Author SHA1 Message Date
Christopher Haster
f6e3193051 Added file config structure and lfs_file_opencfg
The optional config structure options up the possibility of adding
file-level configuration in a backwards compatible manner.

Also bumped minor version to v1.5
2018-07-16 15:39:10 -05:00
Damien George
97711d78c4 Added possibility to open multiple files with LFS_NO_MALLOC enabled. 2018-07-16 15:37:45 -05:00
10 changed files with 210 additions and 259 deletions

View File

@@ -134,57 +134,53 @@ jobs:
- STAGE=deploy - STAGE=deploy
- NAME=deploy - NAME=deploy
script: script:
# Find version defined in lfs.h # Update tag for version defined in lfs.h
- LFS_VERSION=$(grep -ox '#define LFS_VERSION .*' lfs.h | cut -d ' ' -f3) - LFS_VERSION=$(grep -ox '#define LFS_VERSION .*' lfs.h | cut -d ' ' -f3)
- LFS_VERSION_MAJOR=$((0xffff & ($LFS_VERSION >> 16))) - LFS_VERSION_MAJOR=$((0xffff & ($LFS_VERSION >> 16)))
- LFS_VERSION_MINOR=$((0xffff & ($LFS_VERSION >> 0))) - LFS_VERSION_MINOR=$((0xffff & ($LFS_VERSION >> 0)))
# Grab latests patch from repo tags, default to 0, needs finagling to get past github's pagination api - LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR"
- PREV_URL=https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR. - echo "littlefs version $LFS_VERSION"
- PREV_URL=$(curl -u "$GEKY_BOT_RELEASES" "$PREV_URL" -I
| sed -n '/^Link/{s/.*<\(.*\)>; rel="last"/\1/;p;q0};$q1'
|| echo $PREV_URL)
- LFS_VERSION_PATCH=$(curl -u "$GEKY_BOT_RELEASES" "$PREV_URL"
| jq 'map(.ref | match("\\bv.*\\..*\\.(.*)$";"g")
.captures[].string | tonumber) | max + 1'
|| echo 0)
# We have our new version
- LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR.$LFS_VERSION_PATCH"
- echo "VERSION $LFS_VERSION"
- | - |
# Check that we're the most recent commit curl -u $GEKY_BOT_RELEASES -X POST \
CURRENT_COMMIT=$(curl -f -u "$GEKY_BOT_RELEASES" \ https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs \
https://api.github.com/repos/$TRAVIS_REPO_SLUG/commits/master \ -d "{
| jq -re '.sha') \"ref\": \"refs/tags/$LFS_VERSION\",
if [ "$TRAVIS_COMMIT" == "$CURRENT_COMMIT" ] \"sha\": \"$TRAVIS_COMMIT\"
}"
- |
curl -f -u $GEKY_BOT_RELEASES -X PATCH \
https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/$LFS_VERSION \
-d "{
\"sha\": \"$TRAVIS_COMMIT\"
}"
# Create release notes from commits
- LFS_PREV_VERSION="v$LFS_VERSION_MAJOR.$(($LFS_VERSION_MINOR-1))"
- |
if [ $(git tag -l "$LFS_PREV_VERSION") ]
then then
# Create a simple tag curl -u $GEKY_BOT_RELEASES -X POST \
curl -f -u "$GEKY_BOT_RELEASES" -X POST \ https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases \
https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs \
-d "{ -d "{
\"ref\": \"refs/tags/$LFS_VERSION\", \"tag_name\": \"$LFS_VERSION\",
\"sha\": \"$TRAVIS_COMMIT\" \"name\": \"$LFS_VERSION\"
}" }"
# Minor release? RELEASE=$(
if [[ "$LFS_VERSION" == *.0 ]] curl -f -u $GEKY_BOT_RELEASES \
then https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/tags/$LFS_VERSION
# Build release notes )
PREV=$(git tag --sort=-v:refname -l "v*.0" | head -1) CHANGES=$(
if [ ! -z "$PREV" ] git log --oneline $LFS_PREV_VERSION.. --grep='^Merge' --invert-grep
then )
echo "PREV $PREV" curl -f -u $GEKY_BOT_RELEASES -X PATCH \
CHANGES=$'### Changes\n\n'$( \ https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/$(
git log --oneline $PREV.. --grep='^Merge' --invert-grep) jq -r '.id' <<< "$RELEASE"
printf "CHANGES\n%s\n\n" "$CHANGES" ) \
fi -d "$(
# Create the release jq -s '{
curl -f -u "$GEKY_BOT_RELEASES" -X POST \ "body": ((.[0] // "" | sub("(?<=\n)#+ Changes.*"; ""; "mi"))
https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases \ + "### Changes\n\n" + .[1])
-d "{ }' <(jq '.body' <<< "$RELEASE") <(jq -sR '.' <<< "$CHANGES")
\"tag_name\": \"$LFS_VERSION\", )"
\"name\": \"${LFS_VERSION%.0}\",
\"body\": $(jq -sR '.' <<< "$CHANGES")
}"
fi
fi fi
# Manage statuses # Manage statuses

View File

@@ -22,3 +22,15 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
*Note*:
Individual files contain the following tag instead of the full license text.
SPDX-License-Identifier: BSD-3-Clause
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/

View File

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

View File

@@ -146,19 +146,6 @@ The tests assume a Linux environment and can be started with make:
make test make test
``` ```
## License
The littlefs is provided under the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html)
license. See [LICENSE.md](LICENSE.md) for more information. Contributions to
this project are accepted under the same license.
Individual files contain the following tag instead of the full license text.
SPDX-License-Identifier: BSD-3-Clause
This enables machine processing of license information based on the SPDX
License Identifiers that are here available: http://spdx.org/licenses/
## Related projects ## Related projects
[Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) - [Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) -

View File

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

314
lfs.c
View File

@@ -417,14 +417,11 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) {
// rather than clobbering one of the blocks we just pretend // rather than clobbering one of the blocks we just pretend
// the revision may be valid // the revision may be valid
int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->d.rev, 4); int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->d.rev, 4);
if (err && err != LFS_ERR_CORRUPT) { dir->d.rev = lfs_fromle32(dir->d.rev);
if (err) {
return err; return err;
} }
if (err != LFS_ERR_CORRUPT) {
dir->d.rev = lfs_fromle32(dir->d.rev);
}
// set defaults // set defaults
dir->d.rev += 1; dir->d.rev += 1;
dir->d.size = sizeof(dir->d)+4; dir->d.size = sizeof(dir->d)+4;
@@ -448,9 +445,6 @@ static int lfs_dir_fetch(lfs_t *lfs,
int err = lfs_bd_read(lfs, tpair[i], 0, &test, sizeof(test)); int err = lfs_bd_read(lfs, tpair[i], 0, &test, sizeof(test));
lfs_dir_fromle32(&test); lfs_dir_fromle32(&test);
if (err) { if (err) {
if (err == LFS_ERR_CORRUPT) {
continue;
}
return err; return err;
} }
@@ -470,9 +464,6 @@ static int lfs_dir_fetch(lfs_t *lfs,
err = lfs_bd_crc(lfs, tpair[i], sizeof(test), err = lfs_bd_crc(lfs, tpair[i], sizeof(test),
(0x7fffffff & test.size) - sizeof(test), &crc); (0x7fffffff & test.size) - sizeof(test), &crc);
if (err) { if (err) {
if (err == LFS_ERR_CORRUPT) {
continue;
}
return err; return err;
} }
@@ -1373,10 +1364,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
} }
// zero to avoid information leak // zero to avoid information leak
lfs_cache_drop(lfs, &file->cache); lfs_cache_zero(lfs, &file->cache);
if ((file->flags & 3) != LFS_O_RDONLY) {
lfs_cache_zero(lfs, &file->cache);
}
// add to list of files // add to list of files
file->next = lfs->files; file->next = lfs->files;
@@ -2019,21 +2007,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
/// Filesystem operations /// /// Filesystem operations ///
static void lfs_deinit(lfs_t *lfs) {
// free allocated memory
if (!lfs->cfg->read_buffer) {
lfs_free(lfs->rcache.buffer);
}
if (!lfs->cfg->prog_buffer) {
lfs_free(lfs->pcache.buffer);
}
if (!lfs->cfg->lookahead_buffer) {
lfs_free(lfs->free.buffer);
}
}
static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->cfg = cfg; lfs->cfg = cfg;
@@ -2043,7 +2016,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
} else { } else {
lfs->rcache.buffer = lfs_malloc(lfs->cfg->read_size); lfs->rcache.buffer = lfs_malloc(lfs->cfg->read_size);
if (!lfs->rcache.buffer) { if (!lfs->rcache.buffer) {
goto cleanup; return LFS_ERR_NOMEM;
} }
} }
@@ -2053,13 +2026,13 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
} else { } else {
lfs->pcache.buffer = lfs_malloc(lfs->cfg->prog_size); lfs->pcache.buffer = lfs_malloc(lfs->cfg->prog_size);
if (!lfs->pcache.buffer) { if (!lfs->pcache.buffer) {
goto cleanup; return LFS_ERR_NOMEM;
} }
} }
// zero to avoid information leaks // zero to avoid information leaks
lfs_cache_zero(lfs, &lfs->rcache);
lfs_cache_zero(lfs, &lfs->pcache); lfs_cache_zero(lfs, &lfs->pcache);
lfs_cache_drop(lfs, &lfs->rcache);
// setup lookahead, round down to nearest 32-bits // setup lookahead, round down to nearest 32-bits
LFS_ASSERT(lfs->cfg->lookahead % 32 == 0); LFS_ASSERT(lfs->cfg->lookahead % 32 == 0);
@@ -2069,7 +2042,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
} else { } else {
lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8); lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8);
if (!lfs->free.buffer) { if (!lfs->free.buffer) {
goto cleanup; return LFS_ERR_NOMEM;
} }
} }
@@ -2089,160 +2062,155 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->deorphaned = false; lfs->deorphaned = false;
return 0; return 0;
}
cleanup: static int lfs_deinit(lfs_t *lfs) {
lfs_deinit(lfs); // free allocated memory
return LFS_ERR_NOMEM; if (!lfs->cfg->read_buffer) {
lfs_free(lfs->rcache.buffer);
}
if (!lfs->cfg->prog_buffer) {
lfs_free(lfs->pcache.buffer);
}
if (!lfs->cfg->lookahead_buffer) {
lfs_free(lfs->free.buffer);
}
return 0;
} }
int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
int err = 0; int err = lfs_init(lfs, cfg);
if (true) { if (err) {
err = lfs_init(lfs, cfg); return err;
if (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 superblock dir
lfs_dir_t superdir;
err = lfs_dir_alloc(lfs, &superdir);
if (err) {
return err;
}
// write root directory
lfs_dir_t root;
err = lfs_dir_alloc(lfs, &root);
if (err) {
return err;
}
err = lfs_dir_commit(lfs, &root, NULL, 0);
if (err) {
return err;
}
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) {
return err; return err;
} }
// create free lookahead valid = valid || !err;
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) {
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: if (!valid) {
lfs_deinit(lfs); return LFS_ERR_CORRUPT;
return err; }
// sanity check that fetch works
err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
if (err) {
return err;
}
lfs_alloc_ack(lfs);
return lfs_deinit(lfs);
} }
int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
int err = 0; int err = lfs_init(lfs, cfg);
if (true) { if (err) {
err = lfs_init(lfs, cfg); 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) {
return err;
}
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) { if (err) {
return err; return err;
} }
// setup free lookahead lfs->root[0] = superblock.d.root[0];
lfs->free.off = 0; lfs->root[1] = superblock.d.root[1];
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);
if (err) {
goto cleanup;
}
lfs->root[0] = superblock.d.root[0];
lfs->root[1] = superblock.d.root[1];
}
if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
err = LFS_ERR_CORRUPT;
goto cleanup;
}
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: if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
return LFS_ERR_CORRUPT;
}
lfs_deinit(lfs); uint16_t major_version = (0xffff & (superblock.d.version >> 16));
return err; 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);
return LFS_ERR_INVAL;
}
return 0;
} }
int lfs_unmount(lfs_t *lfs) { int lfs_unmount(lfs_t *lfs) {
lfs_deinit(lfs); return lfs_deinit(lfs);
return 0;
} }
@@ -2481,11 +2449,7 @@ int lfs_deorphan(lfs_t *lfs) {
lfs_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1}; lfs_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1};
// iterate over all directory directory entries // iterate over all directory directory entries
for (lfs_size_t i = 0; i < lfs->cfg->block_count; i++) { while (!lfs_pairisnull(cwd.d.tail)) {
if (lfs_pairisnull(cwd.d.tail)) {
return 0;
}
int err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail); int err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail);
if (err) { if (err) {
return err; return err;
@@ -2514,7 +2478,7 @@ int lfs_deorphan(lfs_t *lfs) {
return err; return err;
} }
return 0; break;
} }
if (!lfs_pairsync(entry.d.u.dir, pdir.d.tail)) { if (!lfs_pairsync(entry.d.u.dir, pdir.d.tail)) {
@@ -2530,7 +2494,7 @@ int lfs_deorphan(lfs_t *lfs) {
return err; return err;
} }
return 0; break;
} }
} }
@@ -2575,7 +2539,5 @@ int lfs_deorphan(lfs_t *lfs) {
memcpy(&pdir, &cwd, sizeof(pdir)); memcpy(&pdir, &cwd, sizeof(pdir));
} }
// If we reached here, we have more directory pairs than blocks in the return 0;
// filesystem... So something must be horribly wrong
return LFS_ERR_CORRUPT;
} }

2
lfs.h
View File

@@ -21,7 +21,7 @@ extern "C"
// 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 0x00010006 #define LFS_VERSION 0x00010005
#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))

View File

@@ -32,18 +32,18 @@ lfs_alloc_singleproc() {
tests/test.py << TEST tests/test.py << TEST
const char *names[] = {"bacon", "eggs", "pancakes"}; const char *names[] = {"bacon", "eggs", "pancakes"};
lfs_mount(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (unsigned n = 0; n < sizeof(names)/sizeof(names[0]); n++) { for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) {
sprintf((char*)buffer, "$1/%s", names[n]); sprintf((char*)buffer, "$1/%s", names[n]);
lfs_file_open(&lfs, &file[n], (char*)buffer, lfs_file_open(&lfs, &file[n], (char*)buffer,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
} }
for (unsigned n = 0; n < sizeof(names)/sizeof(names[0]); n++) { for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) {
size = strlen(names[n]); size = strlen(names[n]);
for (int i = 0; i < $SIZE; i++) { for (int i = 0; i < $SIZE; i++) {
lfs_file_write(&lfs, &file[n], names[n], size) => size; lfs_file_write(&lfs, &file[n], names[n], size) => size;
} }
} }
for (unsigned n = 0; n < sizeof(names)/sizeof(names[0]); n++) { for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) {
lfs_file_close(&lfs, &file[n]) => 0; lfs_file_close(&lfs, &file[n]) => 0;
} }
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;

View File

@@ -301,7 +301,7 @@ tests/test.py << TEST
size = strlen("hedgehoghog"); size = strlen("hedgehoghog");
const lfs_soff_t offsets[] = {512, 1020, 513, 1021, 511, 1019}; const lfs_soff_t offsets[] = {512, 1020, 513, 1021, 511, 1019};
for (unsigned i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) { for (int i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) {
lfs_soff_t off = offsets[i]; lfs_soff_t off = offsets[i];
memcpy(buffer, "hedgehoghog", size); memcpy(buffer, "hedgehoghog", size);
lfs_file_seek(&lfs, &file[0], off, LFS_SEEK_SET) => off; lfs_file_seek(&lfs, &file[0], off, LFS_SEEK_SET) => off;

View File

@@ -23,14 +23,14 @@ tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (unsigned i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) { for (int i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) {
sprintf((char*)buffer, "hairyhead%d", i); sprintf((char*)buffer, "hairyhead%d", i);
lfs_file_open(&lfs, &file[0], (const char*)buffer, lfs_file_open(&lfs, &file[0], (const char*)buffer,
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
strcpy((char*)buffer, "hair"); strcpy((char*)buffer, "hair");
size = strlen((char*)buffer); size = strlen((char*)buffer);
for (lfs_off_t j = 0; j < startsizes[i]; j += size) { for (int j = 0; j < startsizes[i]; j += size) {
lfs_file_write(&lfs, &file[0], buffer, size) => size; lfs_file_write(&lfs, &file[0], buffer, size) => size;
} }
lfs_file_size(&lfs, &file[0]) => startsizes[i]; lfs_file_size(&lfs, &file[0]) => startsizes[i];
@@ -55,13 +55,13 @@ tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (unsigned i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) { for (int i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) {
sprintf((char*)buffer, "hairyhead%d", i); sprintf((char*)buffer, "hairyhead%d", i);
lfs_file_open(&lfs, &file[0], (const char*)buffer, LFS_O_RDWR) => 0; lfs_file_open(&lfs, &file[0], (const char*)buffer, LFS_O_RDWR) => 0;
lfs_file_size(&lfs, &file[0]) => hotsizes[i]; lfs_file_size(&lfs, &file[0]) => hotsizes[i];
size = strlen("hair"); size = strlen("hair");
lfs_off_t j = 0; int j = 0;
for (; j < startsizes[i] && j < hotsizes[i]; j += size) { for (; j < startsizes[i] && j < hotsizes[i]; j += size) {
lfs_file_read(&lfs, &file[0], buffer, size) => size; lfs_file_read(&lfs, &file[0], buffer, size) => size;
memcmp(buffer, "hair", size) => 0; memcmp(buffer, "hair", size) => 0;
@@ -87,13 +87,13 @@ tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;
for (unsigned i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) { for (int i = 0; i < sizeof(startsizes)/sizeof(startsizes[0]); i++) {
sprintf((char*)buffer, "hairyhead%d", i); sprintf((char*)buffer, "hairyhead%d", i);
lfs_file_open(&lfs, &file[0], (const char*)buffer, LFS_O_RDONLY) => 0; lfs_file_open(&lfs, &file[0], (const char*)buffer, LFS_O_RDONLY) => 0;
lfs_file_size(&lfs, &file[0]) => coldsizes[i]; lfs_file_size(&lfs, &file[0]) => coldsizes[i];
size = strlen("hair"); size = strlen("hair");
lfs_off_t j = 0; int j = 0;
for (; j < startsizes[i] && j < hotsizes[i] && j < coldsizes[i]; for (; j < startsizes[i] && j < hotsizes[i] && j < coldsizes[i];
j += size) { j += size) {
lfs_file_read(&lfs, &file[0], buffer, size) => size; lfs_file_read(&lfs, &file[0], buffer, size) => size;