mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 00:38:29 +01:00
Merge pull request #28 from geky/configurables
Add better general support in lfs_utils.h
This commit is contained in:
271
.travis.yml
271
.travis.yml
@@ -1,107 +1,210 @@
|
|||||||
|
# Environment variables
|
||||||
env:
|
env:
|
||||||
|
global:
|
||||||
- CFLAGS=-Werror
|
- CFLAGS=-Werror
|
||||||
|
|
||||||
|
# Common test script
|
||||||
script:
|
script:
|
||||||
# make sure example can at least compile
|
# make sure example can at least compile
|
||||||
- sed -n '/``` c/,/```/{/```/d; p;}' README.md > test.c &&
|
- sed -n '/``` c/,/```/{/```/d; p;}' README.md > test.c &&
|
||||||
make all size CFLAGS+="
|
make all CFLAGS+="
|
||||||
-Duser_provided_block_device_read=NULL
|
-Duser_provided_block_device_read=NULL
|
||||||
-Duser_provided_block_device_prog=NULL
|
-Duser_provided_block_device_prog=NULL
|
||||||
-Duser_provided_block_device_erase=NULL
|
-Duser_provided_block_device_erase=NULL
|
||||||
-Duser_provided_block_device_sync=NULL
|
-Duser_provided_block_device_sync=NULL
|
||||||
-include stdio.h"
|
-include stdio.h"
|
||||||
|
|
||||||
# run tests
|
# run tests
|
||||||
- make test QUIET=1
|
- make test QUIET=1
|
||||||
|
|
||||||
# run tests with a few different configurations
|
# run tests with a few different configurations
|
||||||
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1"
|
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1"
|
||||||
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512"
|
- make test QUIET=1 CFLAGS+="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512"
|
||||||
- make test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048"
|
- make test QUIET=1 CFLAGS+="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048"
|
||||||
|
|
||||||
|
- make clean test QUIET=1 CFLAGS+="-DLFS_NO_INTRINSICS"
|
||||||
|
|
||||||
|
# compile and find the code size with the smalles configuration
|
||||||
|
- make clean size
|
||||||
|
OBJ="$(ls lfs*.o | tr '\n' ' ')"
|
||||||
|
CFLAGS+="-DLFS_NO{ASSERT,DEBUG,WARN,ERROR}"
|
||||||
|
| tee sizes
|
||||||
|
|
||||||
|
# update status if we succeeded, compare with master if possible
|
||||||
|
- |
|
||||||
|
if [ "$TRAVIS_TEST_RESULT" -eq 0 ]
|
||||||
|
then
|
||||||
|
CURR=$(tail -n1 sizes | awk '{print $1}')
|
||||||
|
STATUS="Passed, code size is ${CURR}B"
|
||||||
|
|
||||||
|
PREV=$(curl https://api.github.com/repos/$TRAVIS_REPO_SLUG/status/master \
|
||||||
|
| jq -r ".statuses[] | select(.context == \"ci/$NAME\").description" \
|
||||||
|
| sed 's/.*code size is \([0-9]*\).*/\1/' \
|
||||||
|
|| echo 0)
|
||||||
|
if [ "$PREV" -ne 0 ]
|
||||||
|
then
|
||||||
|
STATUS="$STATUS ($(python -c "print '%+.2f' % (100*($CURR-$PREV)/$PREV.0)")%)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# CI matrix
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
# native testing
|
||||||
|
- env:
|
||||||
|
- NAME=littlefs-x86
|
||||||
|
|
||||||
|
# cross-compile with ARM (thumb mode)
|
||||||
|
- env:
|
||||||
|
- NAME=littlefs-arm
|
||||||
|
- CC="arm-linux-gnueabi-gcc --static -mthumb"
|
||||||
|
- EXEC="qemu-arm"
|
||||||
|
install:
|
||||||
|
- sudo apt-get install gcc-arm-linux-gnueabi qemu-user
|
||||||
|
- arm-linux-gnueabi-gcc --version
|
||||||
|
- qemu-arm -version
|
||||||
|
|
||||||
|
# cross-compile with PowerPC
|
||||||
|
- env:
|
||||||
|
- NAME=littlefs-powerpc
|
||||||
|
- CC="powerpc-linux-gnu-gcc --static"
|
||||||
|
- EXEC="qemu-ppc"
|
||||||
|
install:
|
||||||
|
- sudo apt-get install gcc-powerpc-linux-gnu qemu-user
|
||||||
|
- powerpc-linux-gnu-gcc --version
|
||||||
|
- qemu-ppc -version
|
||||||
|
|
||||||
|
# cross-compile with MIPS
|
||||||
|
- env:
|
||||||
|
- NAME=littlefs-mips
|
||||||
|
- CC="mips-linux-gnu-gcc --static"
|
||||||
|
- EXEC="qemu-mips"
|
||||||
|
install:
|
||||||
|
- sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ xenial main universe"
|
||||||
|
- sudo apt-get -qq update
|
||||||
|
- sudo apt-get install gcc-mips-linux-gnu qemu-user
|
||||||
|
- mips-linux-gnu-gcc --version
|
||||||
|
- qemu-mips -version
|
||||||
|
|
||||||
# self-host with littlefs-fuse for fuzz test
|
# self-host with littlefs-fuse for fuzz test
|
||||||
- make -C littlefs-fuse
|
- env:
|
||||||
|
- NAME=littlefs-fuse
|
||||||
|
install:
|
||||||
|
- sudo apt-get install libfuse-dev
|
||||||
|
- git clone --depth 1 https://github.com/geky/littlefs-fuse
|
||||||
|
- fusermount -V
|
||||||
|
- gcc --version
|
||||||
|
before_script:
|
||||||
|
# setup disk for littlefs-fuse
|
||||||
|
- rm -rf littlefs-fuse/littlefs/*
|
||||||
|
- cp -r $(git ls-tree --name-only HEAD) littlefs-fuse/littlefs
|
||||||
|
|
||||||
- littlefs-fuse/lfs --format /dev/loop0
|
- mkdir mount
|
||||||
- littlefs-fuse/lfs /dev/loop0 mount
|
- sudo chmod a+rw /dev/loop0
|
||||||
|
- dd if=/dev/zero bs=512 count=2048 of=disk
|
||||||
|
- losetup /dev/loop0 disk
|
||||||
|
script:
|
||||||
|
# self-host test
|
||||||
|
- make -C littlefs-fuse
|
||||||
|
|
||||||
- ls mount
|
- littlefs-fuse/lfs --format /dev/loop0
|
||||||
- mkdir mount/littlefs
|
- littlefs-fuse/lfs /dev/loop0 mount
|
||||||
- cp -r $(git ls-tree --name-only HEAD) mount/littlefs
|
|
||||||
- cd mount/littlefs
|
|
||||||
- ls
|
|
||||||
- make -B test_dirs test_files QUIET=1
|
|
||||||
|
|
||||||
|
- ls mount
|
||||||
|
- mkdir mount/littlefs
|
||||||
|
- cp -r $(git ls-tree --name-only HEAD) mount/littlefs
|
||||||
|
- cd mount/littlefs
|
||||||
|
- ls
|
||||||
|
- make -B test_dirs test_files QUIET=1
|
||||||
|
|
||||||
|
# Manage statuses
|
||||||
before_install:
|
before_install:
|
||||||
- fusermount -V
|
- |
|
||||||
- gcc --version
|
curl -u $GEKY_BOT_STATUSES -X POST \
|
||||||
|
https://api.github.com/repos/$TRAVIS_REPO_SLUG/statuses/${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT} \
|
||||||
|
-d "{
|
||||||
|
\"context\": \"ci/$NAME\",
|
||||||
|
\"state\": \"pending\",
|
||||||
|
\"description\": \"${STATUS:-In progress}\",
|
||||||
|
\"target_url\": \"https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$TRAVIS_JOB_ID\"
|
||||||
|
}"
|
||||||
|
|
||||||
install:
|
after_failure:
|
||||||
- sudo apt-get install libfuse-dev
|
- |
|
||||||
- git clone --depth 1 https://github.com/geky/littlefs-fuse
|
curl -u $GEKY_BOT_STATUSES -X POST \
|
||||||
|
https://api.github.com/repos/$TRAVIS_REPO_SLUG/statuses/${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT} \
|
||||||
|
-d "{
|
||||||
|
\"context\": \"ci/$NAME\",
|
||||||
|
\"state\": \"failure\",
|
||||||
|
\"description\": \"${STATUS:-Failed}\",
|
||||||
|
\"target_url\": \"https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$TRAVIS_JOB_ID\"
|
||||||
|
}"
|
||||||
|
|
||||||
before_script:
|
after_success:
|
||||||
- rm -rf littlefs-fuse/littlefs/*
|
- |
|
||||||
- cp -r $(git ls-tree --name-only HEAD) littlefs-fuse/littlefs
|
curl -u $GEKY_BOT_STATUSES -X POST \
|
||||||
|
https://api.github.com/repos/$TRAVIS_REPO_SLUG/statuses/${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT} \
|
||||||
- mkdir mount
|
-d "{
|
||||||
- sudo chmod a+rw /dev/loop0
|
\"context\": \"ci/$NAME\",
|
||||||
- dd if=/dev/zero bs=512 count=2048 of=disk
|
\"state\": \"success\",
|
||||||
- losetup /dev/loop0 disk
|
\"description\": \"${STATUS:-Passed}\",
|
||||||
|
\"target_url\": \"https://travis-ci.org/$TRAVIS_REPO_SLUG/jobs/$TRAVIS_JOB_ID\"
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Automatically update releases
|
||||||
deploy:
|
deploy:
|
||||||
# Let before_deploy take over
|
# Let before_deploy take over
|
||||||
provider: script
|
provider: script
|
||||||
script: 'true'
|
script: 'true'
|
||||||
on:
|
on:
|
||||||
branch: master
|
branch: master
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- cd $TRAVIS_BUILD_DIR
|
- cd $TRAVIS_BUILD_DIR
|
||||||
# Update tag for 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)))
|
||||||
- LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR"
|
- LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR"
|
||||||
- echo "littlefs version $LFS_VERSION"
|
- echo "littlefs version $LFS_VERSION"
|
||||||
- |
|
- |
|
||||||
curl -u $GEKY_BOT -X POST \
|
curl -u $GEKY_BOT_RELEASES -X POST \
|
||||||
https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs \
|
https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs \
|
||||||
-d "{
|
-d "{
|
||||||
\"ref\": \"refs/tags/$LFS_VERSION\",
|
\"ref\": \"refs/tags/$LFS_VERSION\",
|
||||||
\"sha\": \"$TRAVIS_COMMIT\"
|
\"sha\": \"$TRAVIS_COMMIT\"
|
||||||
}"
|
}"
|
||||||
- |
|
- |
|
||||||
curl -f -u $GEKY_BOT -X PATCH \
|
curl -f -u $GEKY_BOT_RELEASES -X PATCH \
|
||||||
https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/$LFS_VERSION \
|
https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/$LFS_VERSION \
|
||||||
-d "{
|
-d "{
|
||||||
\"sha\": \"$TRAVIS_COMMIT\"
|
\"sha\": \"$TRAVIS_COMMIT\"
|
||||||
}"
|
}"
|
||||||
# Create release notes from commits
|
# Create release notes from commits
|
||||||
- LFS_PREV_VERSION="v$LFS_VERSION_MAJOR.$(($LFS_VERSION_MINOR-1))"
|
- LFS_PREV_VERSION="v$LFS_VERSION_MAJOR.$(($LFS_VERSION_MINOR-1))"
|
||||||
- |
|
- |
|
||||||
if [ $(git tag -l "$LFS_PREV_VERSION") ]
|
if [ $(git tag -l "$LFS_PREV_VERSION") ]
|
||||||
then
|
then
|
||||||
curl -u $GEKY_BOT -X POST \
|
curl -u $GEKY_BOT_RELEASES -X POST \
|
||||||
https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases \
|
https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases \
|
||||||
-d "{
|
-d "{
|
||||||
\"tag_name\": \"$LFS_VERSION\",
|
\"tag_name\": \"$LFS_VERSION\",
|
||||||
\"name\": \"$LFS_VERSION\"
|
\"name\": \"$LFS_VERSION\"
|
||||||
}"
|
}"
|
||||||
RELEASE=$(
|
RELEASE=$(
|
||||||
curl -f https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/tags/$LFS_VERSION
|
curl -f https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/tags/$LFS_VERSION
|
||||||
)
|
)
|
||||||
CHANGES=$(
|
CHANGES=$(
|
||||||
git log --oneline $LFS_PREV_VERSION.. --grep='^Merge' --invert-grep
|
git log --oneline $LFS_PREV_VERSION.. --grep='^Merge' --invert-grep
|
||||||
)
|
)
|
||||||
curl -f -u $GEKY_BOT -X PATCH \
|
curl -f -u $GEKY_BOT_RELEASES -X PATCH \
|
||||||
https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/$(
|
https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/$(
|
||||||
jq -r '.id' <<< "$RELEASE"
|
jq -r '.id' <<< "$RELEASE"
|
||||||
) \
|
) \
|
||||||
-d "$(
|
-d "$(
|
||||||
jq -s '{
|
jq -s '{
|
||||||
"body": ((.[0] // "" | sub("(?<=\n)#+ Changes.*"; ""; "mi"))
|
"body": ((.[0] // "" | sub("(?<=\n)#+ Changes.*"; ""; "mi"))
|
||||||
+ "### Changes\n\n" + .[1])
|
+ "### Changes\n\n" + .[1])
|
||||||
}' <(jq '.body' <<< "$RELEASE") <(jq -sR '.' <<< "$CHANGES")
|
}' <(jq '.body' <<< "$RELEASE") <(jq -sR '.' <<< "$CHANGES")
|
||||||
)"
|
)"
|
||||||
fi
|
fi
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -1,8 +1,8 @@
|
|||||||
TARGET = lfs
|
TARGET = lfs
|
||||||
|
|
||||||
CC = gcc
|
CC ?= gcc
|
||||||
AR = ar
|
AR ?= ar
|
||||||
SIZE = size
|
SIZE ?= size
|
||||||
|
|
||||||
SRC += $(wildcard *.c emubd/*.c)
|
SRC += $(wildcard *.c emubd/*.c)
|
||||||
OBJ := $(SRC:.c=.o)
|
OBJ := $(SRC:.c=.o)
|
||||||
|
|||||||
128
lfs.c
128
lfs.c
@@ -18,17 +18,13 @@
|
|||||||
#include "lfs.h"
|
#include "lfs.h"
|
||||||
#include "lfs_util.h"
|
#include "lfs_util.h"
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
|
||||||
/// Caching block device operations ///
|
/// Caching block device operations ///
|
||||||
static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache,
|
static int lfs_cache_read(lfs_t *lfs, lfs_cache_t *rcache,
|
||||||
const lfs_cache_t *pcache, lfs_block_t block,
|
const lfs_cache_t *pcache, lfs_block_t block,
|
||||||
lfs_off_t off, void *buffer, lfs_size_t size) {
|
lfs_off_t off, void *buffer, lfs_size_t size) {
|
||||||
uint8_t *data = buffer;
|
uint8_t *data = buffer;
|
||||||
assert(block < lfs->cfg->block_count);
|
LFS_ASSERT(block < lfs->cfg->block_count);
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
if (pcache && block == pcache->block && off >= pcache->off &&
|
if (pcache && block == pcache->block && off >= pcache->off &&
|
||||||
@@ -153,7 +149,7 @@ static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache,
|
|||||||
lfs_cache_t *rcache, lfs_block_t block,
|
lfs_cache_t *rcache, lfs_block_t block,
|
||||||
lfs_off_t off, const void *buffer, lfs_size_t size) {
|
lfs_off_t off, const void *buffer, lfs_size_t size) {
|
||||||
const uint8_t *data = buffer;
|
const uint8_t *data = buffer;
|
||||||
assert(block < lfs->cfg->block_count);
|
LFS_ASSERT(block < lfs->cfg->block_count);
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
if (block == pcache->block && off >= pcache->off &&
|
if (block == pcache->block && off >= pcache->off &&
|
||||||
@@ -180,7 +176,7 @@ static int lfs_cache_prog(lfs_t *lfs, lfs_cache_t *pcache,
|
|||||||
|
|
||||||
// pcache must have been flushed, either by programming and
|
// pcache must have been flushed, either by programming and
|
||||||
// entire block or manually flushing the pcache
|
// entire block or manually flushing the pcache
|
||||||
assert(pcache->block == 0xffffffff);
|
LFS_ASSERT(pcache->block == 0xffffffff);
|
||||||
|
|
||||||
if (off % lfs->cfg->prog_size == 0 &&
|
if (off % lfs->cfg->prog_size == 0 &&
|
||||||
size >= lfs->cfg->prog_size) {
|
size >= lfs->cfg->prog_size) {
|
||||||
@@ -323,6 +319,48 @@ static void lfs_alloc_ack(lfs_t *lfs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Endian swapping functions ///
|
||||||
|
static void lfs_dir_fromle32(struct lfs_disk_dir *d) {
|
||||||
|
d->rev = lfs_fromle32(d->rev);
|
||||||
|
d->size = lfs_fromle32(d->size);
|
||||||
|
d->tail[0] = lfs_fromle32(d->tail[0]);
|
||||||
|
d->tail[1] = lfs_fromle32(d->tail[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lfs_dir_tole32(struct lfs_disk_dir *d) {
|
||||||
|
d->rev = lfs_tole32(d->rev);
|
||||||
|
d->size = lfs_tole32(d->size);
|
||||||
|
d->tail[0] = lfs_tole32(d->tail[0]);
|
||||||
|
d->tail[1] = lfs_tole32(d->tail[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lfs_entry_fromle32(struct lfs_disk_entry *d) {
|
||||||
|
d->u.dir[0] = lfs_fromle32(d->u.dir[0]);
|
||||||
|
d->u.dir[1] = lfs_fromle32(d->u.dir[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lfs_entry_tole32(struct lfs_disk_entry *d) {
|
||||||
|
d->u.dir[0] = lfs_tole32(d->u.dir[0]);
|
||||||
|
d->u.dir[1] = lfs_tole32(d->u.dir[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lfs_superblock_fromle32(struct lfs_disk_superblock *d) {
|
||||||
|
d->root[0] = lfs_fromle32(d->root[0]);
|
||||||
|
d->root[1] = lfs_fromle32(d->root[1]);
|
||||||
|
d->block_size = lfs_fromle32(d->block_size);
|
||||||
|
d->block_count = lfs_fromle32(d->block_count);
|
||||||
|
d->version = lfs_fromle32(d->version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lfs_superblock_tole32(struct lfs_disk_superblock *d) {
|
||||||
|
d->root[0] = lfs_tole32(d->root[0]);
|
||||||
|
d->root[1] = lfs_tole32(d->root[1]);
|
||||||
|
d->block_size = lfs_tole32(d->block_size);
|
||||||
|
d->block_count = lfs_tole32(d->block_count);
|
||||||
|
d->version = lfs_tole32(d->version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Metadata pair and directory operations ///
|
/// Metadata pair and directory operations ///
|
||||||
static inline void lfs_pairswap(lfs_block_t pair[2]) {
|
static inline void lfs_pairswap(lfs_block_t pair[2]) {
|
||||||
lfs_block_t t = pair[0];
|
lfs_block_t t = pair[0];
|
||||||
@@ -364,6 +402,7 @@ 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);
|
||||||
|
dir->d.rev = lfs_fromle32(dir->d.rev);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -389,6 +428,7 @@ static int lfs_dir_fetch(lfs_t *lfs,
|
|||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
struct lfs_disk_dir test;
|
struct lfs_disk_dir test;
|
||||||
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);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -403,7 +443,9 @@ static int lfs_dir_fetch(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t crc = 0xffffffff;
|
uint32_t crc = 0xffffffff;
|
||||||
|
lfs_dir_tole32(&test);
|
||||||
lfs_crc(&crc, &test, sizeof(test));
|
lfs_crc(&crc, &test, sizeof(test));
|
||||||
|
lfs_dir_fromle32(&test);
|
||||||
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) {
|
||||||
@@ -463,8 +505,10 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t crc = 0xffffffff;
|
uint32_t crc = 0xffffffff;
|
||||||
|
lfs_dir_tole32(&dir->d);
|
||||||
lfs_crc(&crc, &dir->d, sizeof(dir->d));
|
lfs_crc(&crc, &dir->d, sizeof(dir->d));
|
||||||
err = lfs_bd_prog(lfs, dir->pair[0], 0, &dir->d, sizeof(dir->d));
|
err = lfs_bd_prog(lfs, dir->pair[0], 0, &dir->d, sizeof(dir->d));
|
||||||
|
lfs_dir_fromle32(&dir->d);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
goto relocate;
|
goto relocate;
|
||||||
@@ -511,7 +555,9 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crc = lfs_tole32(crc);
|
||||||
err = lfs_bd_prog(lfs, dir->pair[0], newoff, &crc, 4);
|
err = lfs_bd_prog(lfs, dir->pair[0], newoff, &crc, 4);
|
||||||
|
crc = lfs_fromle32(crc);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
goto relocate;
|
goto relocate;
|
||||||
@@ -584,11 +630,14 @@ relocate:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
|
static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
|
||||||
const lfs_entry_t *entry, const void *data) {
|
lfs_entry_t *entry, const void *data) {
|
||||||
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
lfs_entry_tole32(&entry->d);
|
||||||
|
int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
||||||
{entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)},
|
{entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)},
|
||||||
{entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen}
|
{entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen}
|
||||||
}, data ? 2 : 1);
|
}, data ? 2 : 1);
|
||||||
|
lfs_entry_fromle32(&entry->d);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
|
static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
|
||||||
@@ -597,10 +646,14 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
|
|||||||
while (true) {
|
while (true) {
|
||||||
if (dir->d.size + lfs_entry_size(entry) <= lfs->cfg->block_size) {
|
if (dir->d.size + lfs_entry_size(entry) <= lfs->cfg->block_size) {
|
||||||
entry->off = dir->d.size - 4;
|
entry->off = dir->d.size - 4;
|
||||||
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
|
||||||
|
lfs_entry_tole32(&entry->d);
|
||||||
|
int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
||||||
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
||||||
{entry->off, 0, data, entry->d.nlen}
|
{entry->off, 0, data, entry->d.nlen}
|
||||||
}, 2);
|
}, 2);
|
||||||
|
lfs_entry_fromle32(&entry->d);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to allocate a new dir block
|
// we need to allocate a new dir block
|
||||||
@@ -614,10 +667,12 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
|
|||||||
newdir.d.tail[0] = dir->d.tail[0];
|
newdir.d.tail[0] = dir->d.tail[0];
|
||||||
newdir.d.tail[1] = dir->d.tail[1];
|
newdir.d.tail[1] = dir->d.tail[1];
|
||||||
entry->off = newdir.d.size - 4;
|
entry->off = newdir.d.size - 4;
|
||||||
|
lfs_entry_tole32(&entry->d);
|
||||||
err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){
|
err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){
|
||||||
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
||||||
{entry->off, 0, data, entry->d.nlen}
|
{entry->off, 0, data, entry->d.nlen}
|
||||||
}, 2);
|
}, 2);
|
||||||
|
lfs_entry_fromle32(&entry->d);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -703,6 +758,7 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
|
|||||||
|
|
||||||
int err = lfs_bd_read(lfs, dir->pair[0], dir->off,
|
int err = lfs_bd_read(lfs, dir->pair[0], dir->off,
|
||||||
&entry->d, sizeof(entry->d));
|
&entry->d, sizeof(entry->d));
|
||||||
|
lfs_entry_fromle32(&entry->d);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1065,11 +1121,12 @@ static int lfs_ctz_find(lfs_t *lfs,
|
|||||||
lfs_ctz(current));
|
lfs_ctz(current));
|
||||||
|
|
||||||
int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4);
|
int err = lfs_cache_read(lfs, rcache, pcache, head, 4*skip, &head, 4);
|
||||||
|
head = lfs_fromle32(head);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(head >= 2 && head <= lfs->cfg->block_count);
|
LFS_ASSERT(head >= 2 && head <= lfs->cfg->block_count);
|
||||||
current -= 1 << skip;
|
current -= 1 << skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1089,7 +1146,7 @@ static int lfs_ctz_extend(lfs_t *lfs,
|
|||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
assert(nblock >= 2 && nblock <= lfs->cfg->block_count);
|
LFS_ASSERT(nblock >= 2 && nblock <= lfs->cfg->block_count);
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
err = lfs_bd_erase(lfs, nblock);
|
err = lfs_bd_erase(lfs, nblock);
|
||||||
@@ -1140,8 +1197,10 @@ static int lfs_ctz_extend(lfs_t *lfs,
|
|||||||
lfs_size_t skips = lfs_ctz(index) + 1;
|
lfs_size_t skips = lfs_ctz(index) + 1;
|
||||||
|
|
||||||
for (lfs_off_t i = 0; i < skips; i++) {
|
for (lfs_off_t i = 0; i < skips; i++) {
|
||||||
|
head = lfs_tole32(head);
|
||||||
err = lfs_cache_prog(lfs, pcache, rcache,
|
err = lfs_cache_prog(lfs, pcache, rcache,
|
||||||
nblock, 4*i, &head, 4);
|
nblock, 4*i, &head, 4);
|
||||||
|
head = lfs_fromle32(head);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
goto relocate;
|
goto relocate;
|
||||||
@@ -1152,12 +1211,13 @@ static int lfs_ctz_extend(lfs_t *lfs,
|
|||||||
if (i != skips-1) {
|
if (i != skips-1) {
|
||||||
err = lfs_cache_read(lfs, rcache, NULL,
|
err = lfs_cache_read(lfs, rcache, NULL,
|
||||||
head, 4*i, &head, 4);
|
head, 4*i, &head, 4);
|
||||||
|
head = lfs_fromle32(head);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(head >= 2 && head <= lfs->cfg->block_count);
|
LFS_ASSERT(head >= 2 && head <= lfs->cfg->block_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
*block = nblock;
|
*block = nblock;
|
||||||
@@ -1196,6 +1256,8 @@ static int lfs_ctz_traverse(lfs_t *lfs,
|
|||||||
lfs_block_t heads[2];
|
lfs_block_t heads[2];
|
||||||
int count = 2 - (index & 1);
|
int count = 2 - (index & 1);
|
||||||
err = lfs_cache_read(lfs, rcache, pcache, head, 0, &heads, count*4);
|
err = lfs_cache_read(lfs, rcache, pcache, head, 0, &heads, count*4);
|
||||||
|
heads[0] = lfs_fromle32(heads[0]);
|
||||||
|
heads[1] = lfs_fromle32(heads[1]);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1281,12 +1343,12 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
|||||||
if (lfs->cfg->file_buffer) {
|
if (lfs->cfg->file_buffer) {
|
||||||
file->cache.buffer = lfs->cfg->file_buffer;
|
file->cache.buffer = lfs->cfg->file_buffer;
|
||||||
} else if ((file->flags & 3) == LFS_O_RDONLY) {
|
} else if ((file->flags & 3) == LFS_O_RDONLY) {
|
||||||
file->cache.buffer = malloc(lfs->cfg->read_size);
|
file->cache.buffer = lfs_malloc(lfs->cfg->read_size);
|
||||||
if (!file->cache.buffer) {
|
if (!file->cache.buffer) {
|
||||||
return LFS_ERR_NOMEM;
|
return LFS_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file->cache.buffer = malloc(lfs->cfg->prog_size);
|
file->cache.buffer = lfs_malloc(lfs->cfg->prog_size);
|
||||||
if (!file->cache.buffer) {
|
if (!file->cache.buffer) {
|
||||||
return LFS_ERR_NOMEM;
|
return LFS_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
@@ -1312,7 +1374,7 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
|
|||||||
|
|
||||||
// clean up memory
|
// clean up memory
|
||||||
if (!lfs->cfg->file_buffer) {
|
if (!lfs->cfg->file_buffer) {
|
||||||
free(file->cache.buffer);
|
lfs_free(file->cache.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@@ -1456,11 +1518,12 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
|
|||||||
lfs_entry_t entry = {.off = file->poff};
|
lfs_entry_t entry = {.off = file->poff};
|
||||||
err = lfs_bd_read(lfs, cwd.pair[0], entry.off,
|
err = lfs_bd_read(lfs, cwd.pair[0], entry.off,
|
||||||
&entry.d, sizeof(entry.d));
|
&entry.d, sizeof(entry.d));
|
||||||
|
lfs_entry_fromle32(&entry.d);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(entry.d.type == LFS_TYPE_REG);
|
LFS_ASSERT(entry.d.type == LFS_TYPE_REG);
|
||||||
entry.d.u.file.head = file->head;
|
entry.d.u.file.head = file->head;
|
||||||
entry.d.u.file.size = file->size;
|
entry.d.u.file.size = file->size;
|
||||||
|
|
||||||
@@ -1686,7 +1749,7 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
|||||||
|
|
||||||
// flush+seek if not already at end
|
// flush+seek if not already at end
|
||||||
if (file->pos != oldsize) {
|
if (file->pos != oldsize) {
|
||||||
int err = lfs_file_seek(lfs, file, 0, SEEK_END);
|
int err = lfs_file_seek(lfs, file, 0, LFS_SEEK_END);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1819,7 +1882,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(res); // must have pred
|
LFS_ASSERT(res); // must have pred
|
||||||
cwd.d.tail[0] = dir.d.tail[0];
|
cwd.d.tail[0] = dir.d.tail[0];
|
||||||
cwd.d.tail[1] = dir.d.tail[1];
|
cwd.d.tail[1] = dir.d.tail[1];
|
||||||
|
|
||||||
@@ -1936,7 +1999,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(res); // must have pred
|
LFS_ASSERT(res); // must have pred
|
||||||
newcwd.d.tail[0] = dir.d.tail[0];
|
newcwd.d.tail[0] = dir.d.tail[0];
|
||||||
newcwd.d.tail[1] = dir.d.tail[1];
|
newcwd.d.tail[1] = dir.d.tail[1];
|
||||||
|
|
||||||
@@ -1959,7 +2022,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
if (lfs->cfg->read_buffer) {
|
if (lfs->cfg->read_buffer) {
|
||||||
lfs->rcache.buffer = lfs->cfg->read_buffer;
|
lfs->rcache.buffer = lfs->cfg->read_buffer;
|
||||||
} else {
|
} else {
|
||||||
lfs->rcache.buffer = malloc(lfs->cfg->read_size);
|
lfs->rcache.buffer = lfs_malloc(lfs->cfg->read_size);
|
||||||
if (!lfs->rcache.buffer) {
|
if (!lfs->rcache.buffer) {
|
||||||
return LFS_ERR_NOMEM;
|
return LFS_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
@@ -1970,30 +2033,30 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
if (lfs->cfg->prog_buffer) {
|
if (lfs->cfg->prog_buffer) {
|
||||||
lfs->pcache.buffer = lfs->cfg->prog_buffer;
|
lfs->pcache.buffer = lfs->cfg->prog_buffer;
|
||||||
} else {
|
} else {
|
||||||
lfs->pcache.buffer = malloc(lfs->cfg->prog_size);
|
lfs->pcache.buffer = lfs_malloc(lfs->cfg->prog_size);
|
||||||
if (!lfs->pcache.buffer) {
|
if (!lfs->pcache.buffer) {
|
||||||
return LFS_ERR_NOMEM;
|
return LFS_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup lookahead, round down to nearest 32-bits
|
// setup lookahead, round down to nearest 32-bits
|
||||||
assert(lfs->cfg->lookahead % 32 == 0);
|
LFS_ASSERT(lfs->cfg->lookahead % 32 == 0);
|
||||||
assert(lfs->cfg->lookahead > 0);
|
LFS_ASSERT(lfs->cfg->lookahead > 0);
|
||||||
if (lfs->cfg->lookahead_buffer) {
|
if (lfs->cfg->lookahead_buffer) {
|
||||||
lfs->free.buffer = lfs->cfg->lookahead_buffer;
|
lfs->free.buffer = lfs->cfg->lookahead_buffer;
|
||||||
} else {
|
} else {
|
||||||
lfs->free.buffer = malloc(lfs->cfg->lookahead/8);
|
lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8);
|
||||||
if (!lfs->free.buffer) {
|
if (!lfs->free.buffer) {
|
||||||
return LFS_ERR_NOMEM;
|
return LFS_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that program and read sizes are multiples of the block size
|
// check that program and read sizes are multiples of the block size
|
||||||
assert(lfs->cfg->prog_size % lfs->cfg->read_size == 0);
|
LFS_ASSERT(lfs->cfg->prog_size % lfs->cfg->read_size == 0);
|
||||||
assert(lfs->cfg->block_size % lfs->cfg->prog_size == 0);
|
LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->prog_size == 0);
|
||||||
|
|
||||||
// check that the block size is large enough to fit ctz pointers
|
// check that the block size is large enough to fit ctz pointers
|
||||||
assert(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))
|
LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))
|
||||||
<= lfs->cfg->block_size);
|
<= lfs->cfg->block_size);
|
||||||
|
|
||||||
// setup default state
|
// setup default state
|
||||||
@@ -2009,15 +2072,15 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
static int lfs_deinit(lfs_t *lfs) {
|
static int lfs_deinit(lfs_t *lfs) {
|
||||||
// free allocated memory
|
// free allocated memory
|
||||||
if (!lfs->cfg->read_buffer) {
|
if (!lfs->cfg->read_buffer) {
|
||||||
free(lfs->rcache.buffer);
|
lfs_free(lfs->rcache.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lfs->cfg->prog_buffer) {
|
if (!lfs->cfg->prog_buffer) {
|
||||||
free(lfs->pcache.buffer);
|
lfs_free(lfs->pcache.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lfs->cfg->lookahead_buffer) {
|
if (!lfs->cfg->lookahead_buffer) {
|
||||||
free(lfs->free.buffer);
|
lfs_free(lfs->free.buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2075,6 +2138,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4;
|
superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4;
|
||||||
|
|
||||||
// write both pairs to be safe
|
// write both pairs to be safe
|
||||||
|
lfs_superblock_tole32(&superblock.d);
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){
|
err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){
|
||||||
@@ -2125,6 +2189,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
if (!err) {
|
if (!err) {
|
||||||
err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d),
|
err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d),
|
||||||
&superblock.d, sizeof(superblock.d));
|
&superblock.d, sizeof(superblock.d));
|
||||||
|
lfs_superblock_fromle32(&superblock.d);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -2182,6 +2247,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
|
|||||||
while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) {
|
while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) {
|
||||||
err = lfs_bd_read(lfs, dir.pair[0], dir.off,
|
err = lfs_bd_read(lfs, dir.pair[0], dir.off,
|
||||||
&entry.d, sizeof(entry.d));
|
&entry.d, sizeof(entry.d));
|
||||||
|
lfs_entry_fromle32(&entry.d);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
2
lfs.h
2
lfs.h
@@ -27,7 +27,7 @@
|
|||||||
// 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 0x00010002
|
#define LFS_VERSION 0x00010003
|
||||||
#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))
|
||||||
|
|
||||||
|
|||||||
134
lfs_util.h
134
lfs_util.h
@@ -18,13 +18,60 @@
|
|||||||
#ifndef LFS_UTIL_H
|
#ifndef LFS_UTIL_H
|
||||||
#define LFS_UTIL_H
|
#define LFS_UTIL_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifndef LFS_NO_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#endif
|
||||||
|
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Builtin functions, these may be replaced by more
|
// Macros, may be replaced by system specific wrappers. Arguments to these
|
||||||
// efficient implementations in the system
|
// macros must not have side-effects as the macros can be removed for a smaller
|
||||||
|
// code footprint
|
||||||
|
|
||||||
|
// Logging functions
|
||||||
|
#ifndef LFS_NO_DEBUG
|
||||||
|
#define LFS_DEBUG(fmt, ...) \
|
||||||
|
printf("lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_DEBUG(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LFS_NO_WARN
|
||||||
|
#define LFS_WARN(fmt, ...) \
|
||||||
|
printf("lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_WARN(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LFS_NO_ERROR
|
||||||
|
#define LFS_ERROR(fmt, ...) \
|
||||||
|
printf("lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_ERROR(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Runtime assertions
|
||||||
|
#ifndef LFS_NO_ASSERT
|
||||||
|
#define LFS_ASSERT(test) assert(test)
|
||||||
|
#else
|
||||||
|
#define LFS_ASSERT(test)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Builtin functions, these may be replaced by more efficient
|
||||||
|
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||||
|
// expensive basic C implementation for debugging purposes
|
||||||
|
|
||||||
|
// Min/max functions for unsigned 32-bit numbers
|
||||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
|
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
|
||||||
return (a > b) ? a : b;
|
return (a > b) ? a : b;
|
||||||
}
|
}
|
||||||
@@ -33,31 +80,92 @@ static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
|
|||||||
return (a < b) ? a : b;
|
return (a < b) ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t lfs_ctz(uint32_t a) {
|
// Find the next smallest power of 2 less than or equal to a
|
||||||
return __builtin_ctz(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t lfs_npw2(uint32_t a) {
|
static inline uint32_t lfs_npw2(uint32_t a) {
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||||
return 32 - __builtin_clz(a-1);
|
return 32 - __builtin_clz(a-1);
|
||||||
|
#else
|
||||||
|
uint32_t r = 0;
|
||||||
|
uint32_t s;
|
||||||
|
a -= 1;
|
||||||
|
s = (a > 0xffff) << 4; a >>= s; r |= s;
|
||||||
|
s = (a > 0xff ) << 3; a >>= s; r |= s;
|
||||||
|
s = (a > 0xf ) << 2; a >>= s; r |= s;
|
||||||
|
s = (a > 0x3 ) << 1; a >>= s; r |= s;
|
||||||
|
return (r | (a >> 1)) + 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count the number of trailing binary zeros in a
|
||||||
|
// lfs_ctz(0) may be undefined
|
||||||
|
static inline uint32_t lfs_ctz(uint32_t a) {
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
||||||
|
return __builtin_ctz(a);
|
||||||
|
#else
|
||||||
|
return lfs_npw2((a & -a) + 1) - 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of binary ones in a
|
||||||
static inline uint32_t lfs_popc(uint32_t a) {
|
static inline uint32_t lfs_popc(uint32_t a) {
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||||
return __builtin_popcount(a);
|
return __builtin_popcount(a);
|
||||||
|
#else
|
||||||
|
a = a - ((a >> 1) & 0x55555555);
|
||||||
|
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||||
|
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the sequence comparison of a and b, this is the distance
|
||||||
|
// between a and b ignoring overflow
|
||||||
static inline int lfs_scmp(uint32_t a, uint32_t b) {
|
static inline int lfs_scmp(uint32_t a, uint32_t b) {
|
||||||
return (int)(unsigned)(a - b);
|
return (int)(unsigned)(a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRC-32 with polynomial = 0x04c11db7
|
// Convert from 32-bit little-endian to native order
|
||||||
|
static inline uint32_t lfs_fromle32(uint32_t a) {
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && ( \
|
||||||
|
(defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||||
|
(defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||||
|
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||||
|
return a;
|
||||||
|
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
||||||
|
(defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||||
|
(defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||||
|
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||||
|
return __builtin_bswap32(a);
|
||||||
|
#else
|
||||||
|
return (((uint8_t*)&a)[0] << 0) |
|
||||||
|
(((uint8_t*)&a)[1] << 8) |
|
||||||
|
(((uint8_t*)&a)[2] << 16) |
|
||||||
|
(((uint8_t*)&a)[3] << 24);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to 32-bit little-endian from native order
|
||||||
|
static inline uint32_t lfs_tole32(uint32_t a) {
|
||||||
|
return lfs_fromle32(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||||
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
|
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
|
||||||
|
|
||||||
|
// Allocate memory, only used if buffers are not provided to littlefs
|
||||||
|
static inline void *lfs_malloc(size_t size) {
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
return malloc(size);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Logging functions, these may be replaced by system-specific
|
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||||
// logging functions
|
static inline void lfs_free(void *p) {
|
||||||
#define LFS_DEBUG(fmt, ...) printf("lfs debug: " fmt "\n", __VA_ARGS__)
|
#ifndef LFS_NO_MALLOC
|
||||||
#define LFS_WARN(fmt, ...) printf("lfs warn: " fmt "\n", __VA_ARGS__)
|
free(p);
|
||||||
#define LFS_ERROR(fmt, ...) printf("lfs error: " fmt "\n", __VA_ARGS__)
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -33,10 +33,15 @@ def generate(test):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def compile():
|
def compile():
|
||||||
subprocess.check_call(['make', '--no-print-directory', '-s'])
|
subprocess.check_call([
|
||||||
|
os.environ.get('MAKE', 'make'),
|
||||||
|
'--no-print-directory', '-s'])
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
subprocess.check_call(["./lfs"])
|
if 'EXEC' in os.environ:
|
||||||
|
subprocess.check_call([os.environ['EXEC'], "./lfs"])
|
||||||
|
else:
|
||||||
|
subprocess.check_call(["./lfs"])
|
||||||
|
|
||||||
def main(test=None):
|
def main(test=None):
|
||||||
if test and not test.startswith('-'):
|
if test and not test.startswith('-'):
|
||||||
|
|||||||
Reference in New Issue
Block a user