Generated v2 prefixes

This commit is contained in:
geky-bot
2024-12-11 23:20:07 +00:00
15 changed files with 7693 additions and 361 deletions
+16 -13
View File
@@ -20,7 +20,7 @@ jobs:
github.event.workflow_run.head_sha == github.sha}} github.event.workflow_run.head_sha == github.sha}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
ref: ${{github.event.workflow_run.head_sha}} ref: ${{github.event.workflow_run.head_sha}}
# need workflow access since we push branches # need workflow access since we push branches
@@ -30,26 +30,29 @@ jobs:
fetch-depth: 0 fetch-depth: 0
# try to get results from tests # try to get results from tests
- uses: dawidd6/action-download-artifact@v2 - uses: actions/download-artifact@v4
continue-on-error: true continue-on-error: true
with: with:
workflow: ${{github.event.workflow_run.name}} github-token: ${{secrets.GITHUB_TOKEN}}
run_id: ${{github.event.workflow_run.id}} run-id: ${{github.event.workflow_run.id}}
name: sizes pattern: '{sizes,sizes-*}'
merge-multiple: true
path: sizes path: sizes
- uses: dawidd6/action-download-artifact@v2 - uses: actions/download-artifact@v4
continue-on-error: true continue-on-error: true
with: with:
workflow: ${{github.event.workflow_run.name}} github-token: ${{secrets.GITHUB_TOKEN}}
run_id: ${{github.event.workflow_run.id}} run-id: ${{github.event.workflow_run.id}}
name: cov pattern: '{cov,cov-*}'
merge-multiple: true
path: cov path: cov
- uses: dawidd6/action-download-artifact@v2 - uses: actions/download-artifact@v4
continue-on-error: true continue-on-error: true
with: with:
workflow: ${{github.event.workflow_run.name}} github-token: ${{secrets.GITHUB_TOKEN}}
run_id: ${{github.event.workflow_run.id}} run-id: ${{github.event.workflow_run.id}}
name: bench pattern: '{bench,bench-*}'
merge-multiple: true
path: bench path: bench
- name: find-version - name: find-version
+10 -8
View File
@@ -13,12 +13,13 @@ jobs:
status: status:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dawidd6/action-download-artifact@v2 - uses: actions/download-artifact@v4
continue-on-error: true continue-on-error: true
with: with:
workflow: ${{github.event.workflow_run.name}} github-token: ${{secrets.GITHUB_TOKEN}}
run_id: ${{github.event.workflow_run.id}} run-id: ${{github.event.workflow_run.id}}
name: status pattern: '{status,status-*}'
merge-multiple: true
path: status path: status
- name: update-status - name: update-status
continue-on-error: true continue-on-error: true
@@ -67,12 +68,13 @@ jobs:
steps: steps:
# generated comment? # generated comment?
- uses: dawidd6/action-download-artifact@v2 - uses: actions/download-artifact@v4
continue-on-error: true continue-on-error: true
with: with:
workflow: ${{github.event.workflow_run.name}} github-token: ${{secrets.GITHUB_TOKEN}}
run_id: ${{github.event.workflow_run.id}} run-id: ${{github.event.workflow_run.id}}
name: comment pattern: '{comment,comment-*}'
merge-multiple: true
path: comment path: comment
- name: update-comment - name: update-comment
continue-on-error: true continue-on-error: true
+37 -34
View File
@@ -21,7 +21,7 @@ jobs:
arch: [x86_64, thumb, mips, powerpc] arch: [x86_64, thumb, mips, powerpc]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -235,9 +235,9 @@ jobs:
# create size statuses # create size statuses
- name: upload-sizes - name: upload-sizes
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: sizes name: sizes-${{matrix.arch}}
path: sizes path: sizes
- name: status-sizes - name: status-sizes
run: | run: |
@@ -273,16 +273,16 @@ jobs:
}' | tee status/$(basename $f .csv).json }' | tee status/$(basename $f .csv).json
done done
- name: upload-status-sizes - name: upload-status-sizes
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: status name: status-sizes-${{matrix.arch}}
path: status path: status
retention-days: 1 retention-days: 1
# create cov statuses # create cov statuses
- name: upload-cov - name: upload-cov
if: ${{matrix.arch == 'x86_64'}} if: ${{matrix.arch == 'x86_64'}}
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: cov name: cov
path: cov path: cov
@@ -317,11 +317,11 @@ jobs:
target_step: env.STEP, target_step: env.STEP,
}' | tee status/$(basename $f .csv)-$s.json }' | tee status/$(basename $f .csv)-$s.json
done done
- name: upload-status-sizes - name: upload-status-cov
if: ${{matrix.arch == 'x86_64'}} if: ${{matrix.arch == 'x86_64'}}
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: status name: status-cov
path: status path: status
retention-days: 1 retention-days: 1
@@ -336,7 +336,7 @@ jobs:
pls: [1, 2] pls: [1, 2]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -361,7 +361,7 @@ jobs:
test-no-intrinsics: test-no-intrinsics:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -378,7 +378,7 @@ jobs:
test-multiversion: test-multiversion:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -395,7 +395,7 @@ jobs:
test-lfs22_0: test-lfs22_0:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -414,7 +414,7 @@ jobs:
test-valgrind: test-valgrind:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -436,7 +436,7 @@ jobs:
test-clang: test-clang:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -459,7 +459,7 @@ jobs:
bench: bench:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -491,7 +491,7 @@ jobs:
# create bench statuses # create bench statuses
- name: upload-bench - name: upload-bench
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: bench name: bench
path: bench path: bench
@@ -525,9 +525,9 @@ jobs:
}' | tee status/$(basename $f .csv)-$s.json }' | tee status/$(basename $f .csv)-$s.json
done done
- name: upload-status-bench - name: upload-status-bench
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: status name: status-bench
path: status path: status
retention-days: 1 retention-days: 1
@@ -535,10 +535,10 @@ jobs:
test-compat: test-compat:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
if: ${{github.event_name == 'pull_request'}} if: ${{github.event_name == 'pull_request'}}
# checkout the current pr target into lfs2p # checkout the current pr target into lfs2p
- uses: actions/checkout@v2 - uses: actions/checkout@v4
if: ${{github.event_name == 'pull_request'}} if: ${{github.event_name == 'pull_request'}}
with: with:
ref: ${{github.event.pull_request.base.ref}} ref: ${{github.event.pull_request.base.ref}}
@@ -572,7 +572,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{!endsWith(github.ref, '-prefix')}} if: ${{!endsWith(github.ref, '-prefix')}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -582,7 +582,7 @@ jobs:
gcc --version gcc --version
python3 --version python3 --version
fusermount -V fusermount -V
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
repository: littlefs-project/littlefs-fuse repository: littlefs-project/littlefs-fuse
ref: v2 ref: v2
@@ -622,7 +622,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{!endsWith(github.ref, '-prefix')}} if: ${{!endsWith(github.ref, '-prefix')}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: install - name: install
run: | run: |
# need a few things # need a few things
@@ -632,12 +632,12 @@ jobs:
gcc --version gcc --version
python3 --version python3 --version
fusermount -V fusermount -V
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
repository: littlefs-project/littlefs-fuse repository: littlefs-project/littlefs-fuse
ref: v2 ref: v2
path: v2 path: v2
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
repository: littlefs-project/littlefs-fuse repository: littlefs-project/littlefs-fuse
ref: v1 ref: v1
@@ -694,7 +694,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [test, bench] needs: [test, bench]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
if: ${{github.event_name == 'pull_request'}} if: ${{github.event_name == 'pull_request'}}
- name: install - name: install
if: ${{github.event_name == 'pull_request'}} if: ${{github.event_name == 'pull_request'}}
@@ -704,23 +704,26 @@ jobs:
pip3 install toml pip3 install toml
gcc --version gcc --version
python3 --version python3 --version
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v4
if: ${{github.event_name == 'pull_request'}} if: ${{github.event_name == 'pull_request'}}
continue-on-error: true continue-on-error: true
with: with:
name: sizes pattern: '{sizes,sizes-*}'
merge-multiple: true
path: sizes path: sizes
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v4
if: ${{github.event_name == 'pull_request'}} if: ${{github.event_name == 'pull_request'}}
continue-on-error: true continue-on-error: true
with: with:
name: cov pattern: '{cov,cov-*}'
merge-multiple: true
path: cov path: cov
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v4
if: ${{github.event_name == 'pull_request'}} if: ${{github.event_name == 'pull_request'}}
continue-on-error: true continue-on-error: true
with: with:
name: bench pattern: '{bench,bench-*}'
merge-multiple: true
path: bench path: bench
# try to find results from tests # try to find results from tests
@@ -862,7 +865,7 @@ jobs:
body: $comment, body: $comment,
}' | tee comment/comment.json }' | tee comment/comment.json
- name: upload-comment - name: upload-comment
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: comment name: comment
path: comment path: comment
+8
View File
@@ -251,6 +251,12 @@ License Identifiers that are here available: http://spdx.org/licenses/
filesystem over USB. Allows mounting littlefs on a host PC without additional filesystem over USB. Allows mounting littlefs on a host PC without additional
drivers. drivers.
- [ramcrc32bd] - An example block device using littlefs's 32-bit CRC for
error-correction.
- [ramrsbd] - An example block device using Reed-Solomon codes for
error-correction.
- [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed - [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed
which already has block device drivers for most forms of embedded storage. which already has block device drivers for most forms of embedded storage.
littlefs is available in Mbed OS as the [LittleFileSystem] class. littlefs is available in Mbed OS as the [LittleFileSystem] class.
@@ -281,6 +287,8 @@ License Identifiers that are here available: http://spdx.org/licenses/
[mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src [mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src
[mklittlefs]: https://github.com/earlephilhower/mklittlefs [mklittlefs]: https://github.com/earlephilhower/mklittlefs
[pico-littlefs-usb]: https://github.com/oyama/pico-littlefs-usb [pico-littlefs-usb]: https://github.com/oyama/pico-littlefs-usb
[ramcrc32bd]: https://github.com/geky/ramcrc32bd
[ramrsbd]: https://github.com/geky/ramrsbd
[Mbed OS]: https://github.com/armmbed/mbed-os [Mbed OS]: https://github.com/armmbed/mbed-os
[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/latest/apis/littlefilesystem.html [LittleFileSystem]: https://os.mbed.com/docs/mbed-os/latest/apis/littlefilesystem.html
[SPIFFS]: https://github.com/pellepl/spiffs [SPIFFS]: https://github.com/pellepl/spiffs
+157 -94
View File
@@ -282,6 +282,21 @@ static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) {
/// Small type-level utilities /// /// Small type-level utilities ///
// some operations on paths
static inline lfs2_size_t lfs2_path_namelen(const char *path) {
return strcspn(path, "/");
}
static inline bool lfs2_path_islast(const char *path) {
lfs2_size_t namelen = lfs2_path_namelen(path);
return path[namelen + strspn(path + namelen, "/")] == '\0';
}
static inline bool lfs2_path_isdir(const char *path) {
return path[lfs2_path_namelen(path)] != '\0';
}
// operations on block pairs // operations on block pairs
static inline void lfs2_pair_swap(lfs2_block_t pair[2]) { static inline void lfs2_pair_swap(lfs2_block_t pair[2]) {
lfs2_block_t t = pair[0]; lfs2_block_t t = pair[0];
@@ -1461,32 +1476,46 @@ static int lfs2_dir_find_match(void *data,
return LFS2_CMP_EQ; return LFS2_CMP_EQ;
} }
// lfs2_dir_find tries to set path and id even if file is not found
//
// returns:
// - 0 if file is found
// - LFS2_ERR_NOENT if file or parent is not found
// - LFS2_ERR_NOTDIR if parent is not a dir
static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir,
const char **path, uint16_t *id) { const char **path, uint16_t *id) {
// we reduce path to a single name if we can find it // we reduce path to a single name if we can find it
const char *name = *path; const char *name = *path;
if (id) {
*id = 0x3ff;
}
// default to root dir // default to root dir
lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0); lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0);
dir->tail[0] = lfs2->root[0]; dir->tail[0] = lfs2->root[0];
dir->tail[1] = lfs2->root[1]; dir->tail[1] = lfs2->root[1];
// empty paths are not allowed
if (*name == '\0') {
return LFS2_ERR_INVAL;
}
while (true) { while (true) {
nextname: nextname:
// skip slashes // skip slashes if we're a directory
name += strspn(name, "/"); if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) {
name += strspn(name, "/");
}
lfs2_size_t namelen = strcspn(name, "/"); lfs2_size_t namelen = strcspn(name, "/");
// skip '.' and root '..' // skip '.'
if ((namelen == 1 && memcmp(name, ".", 1) == 0) || if (namelen == 1 && memcmp(name, ".", 1) == 0) {
(namelen == 2 && memcmp(name, "..", 2) == 0)) {
name += namelen; name += namelen;
goto nextname; goto nextname;
} }
// error on unmatched '..', trying to go above root?
if (namelen == 2 && memcmp(name, "..", 2) == 0) {
return LFS2_ERR_INVAL;
}
// skip if matched by '..' in name // skip if matched by '..' in name
const char *suffix = name + namelen; const char *suffix = name + namelen;
lfs2_size_t sufflen; lfs2_size_t sufflen;
@@ -1498,7 +1527,9 @@ nextname:
break; break;
} }
if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { if (sufflen == 1 && memcmp(suffix, ".", 1) == 0) {
// noop
} else if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
depth -= 1; depth -= 1;
if (depth == 0) { if (depth == 0) {
name = suffix + sufflen; name = suffix + sufflen;
@@ -1512,14 +1543,14 @@ nextname:
} }
// found path // found path
if (name[0] == '\0') { if (*name == '\0') {
return tag; return tag;
} }
// update what we've found so far // update what we've found so far
*path = name; *path = name;
// only continue if we hit a directory // only continue if we're a directory
if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) {
return LFS2_ERR_NOTDIR; return LFS2_ERR_NOTDIR;
} }
@@ -1539,8 +1570,7 @@ nextname:
tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail, tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail,
LFS2_MKTAG(0x780, 0, 0), LFS2_MKTAG(0x780, 0, 0),
LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen), LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen),
// are we last name? id,
(strchr(name, '/') == NULL) ? id : NULL,
lfs2_dir_find_match, &(struct lfs2_dir_find_match){ lfs2_dir_find_match, &(struct lfs2_dir_find_match){
lfs2, name, namelen}); lfs2, name, namelen});
if (tag < 0) { if (tag < 0) {
@@ -2128,13 +2158,14 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir,
// And we cap at half a block to avoid degenerate cases with // And we cap at half a block to avoid degenerate cases with
// nearly-full metadata blocks. // nearly-full metadata blocks.
// //
lfs2_size_t metadata_max = (lfs2->cfg->metadata_max)
? lfs2->cfg->metadata_max
: lfs2->cfg->block_size;
if (end - split < 0xff if (end - split < 0xff
&& size <= lfs2_min( && size <= lfs2_min(
lfs2->cfg->block_size - 40, metadata_max - 40,
lfs2_alignup( lfs2_alignup(
(lfs2->cfg->metadata_max metadata_max/2,
? lfs2->cfg->metadata_max
: lfs2->cfg->block_size)/2,
lfs2->cfg->prog_size))) { lfs2->cfg->prog_size))) {
break; break;
} }
@@ -2603,12 +2634,12 @@ static int lfs2_mkdir_(lfs2_t *lfs2, const char *path) {
cwd.next = lfs2->mlist; cwd.next = lfs2->mlist;
uint16_t id; uint16_t id;
err = lfs2_dir_find(lfs2, &cwd.m, &path, &id); err = lfs2_dir_find(lfs2, &cwd.m, &path, &id);
if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) { if (!(err == LFS2_ERR_NOENT && lfs2_path_islast(path))) {
return (err < 0) ? err : LFS2_ERR_EXIST; return (err < 0) ? err : LFS2_ERR_EXIST;
} }
// check that name fits // check that name fits
lfs2_size_t nlen = strlen(path); lfs2_size_t nlen = lfs2_path_namelen(path);
if (nlen > lfs2->name_max) { if (nlen > lfs2->name_max) {
return LFS2_ERR_NAMETOOLONG; return LFS2_ERR_NAMETOOLONG;
} }
@@ -3057,7 +3088,7 @@ static int lfs2_file_opencfg_(lfs2_t *lfs2, lfs2_file_t *file,
// allocate entry for file if it doesn't exist // allocate entry for file if it doesn't exist
lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id); lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id);
if (tag < 0 && !(tag == LFS2_ERR_NOENT && file->id != 0x3ff)) { if (tag < 0 && !(tag == LFS2_ERR_NOENT && lfs2_path_islast(path))) {
err = tag; err = tag;
goto cleanup; goto cleanup;
} }
@@ -3077,8 +3108,14 @@ static int lfs2_file_opencfg_(lfs2_t *lfs2, lfs2_file_t *file,
goto cleanup; goto cleanup;
} }
// don't allow trailing slashes
if (lfs2_path_isdir(path)) {
err = LFS2_ERR_NOTDIR;
goto cleanup;
}
// check that name fits // check that name fits
lfs2_size_t nlen = strlen(path); lfs2_size_t nlen = lfs2_path_namelen(path);
if (nlen > lfs2->name_max) { if (nlen > lfs2->name_max) {
err = LFS2_ERR_NAMETOOLONG; err = LFS2_ERR_NAMETOOLONG;
goto cleanup; goto cleanup;
@@ -3664,22 +3701,16 @@ static lfs2_ssize_t lfs2_file_write_(lfs2_t *lfs2, lfs2_file_t *file,
static lfs2_soff_t lfs2_file_seek_(lfs2_t *lfs2, lfs2_file_t *file, static lfs2_soff_t lfs2_file_seek_(lfs2_t *lfs2, lfs2_file_t *file,
lfs2_soff_t off, int whence) { lfs2_soff_t off, int whence) {
// find new pos // find new pos
//
// fortunately for us, littlefs is limited to 31-bit file sizes, so we
// don't have to worry too much about integer overflow
lfs2_off_t npos = file->pos; lfs2_off_t npos = file->pos;
if (whence == LFS2_SEEK_SET) { if (whence == LFS2_SEEK_SET) {
npos = off; npos = off;
} else if (whence == LFS2_SEEK_CUR) { } else if (whence == LFS2_SEEK_CUR) {
if ((lfs2_soff_t)file->pos + off < 0) { npos = file->pos + (lfs2_off_t)off;
return LFS2_ERR_INVAL;
} else {
npos = file->pos + off;
}
} else if (whence == LFS2_SEEK_END) { } else if (whence == LFS2_SEEK_END) {
lfs2_soff_t res = lfs2_file_size_(lfs2, file) + off; npos = (lfs2_off_t)lfs2_file_size_(lfs2, file) + (lfs2_off_t)off;
if (res < 0) {
return LFS2_ERR_INVAL;
} else {
npos = res;
}
} }
if (npos > lfs2->file_max) { if (npos > lfs2->file_max) {
@@ -3842,6 +3873,12 @@ static int lfs2_stat_(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
return (int)tag; return (int)tag;
} }
// only allow trailing slashes on dirs
if (strchr(path, '/') != NULL
&& lfs2_tag_type3(tag) != LFS2_TYPE_DIR) {
return LFS2_ERR_NOTDIR;
}
return lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info); return lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info);
} }
@@ -3944,7 +3981,7 @@ static int lfs2_rename_(lfs2_t *lfs2, const char *oldpath, const char *newpath)
uint16_t newid; uint16_t newid;
lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid); lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid);
if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) && if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) &&
!(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) { !(prevtag == LFS2_ERR_NOENT && lfs2_path_islast(newpath))) {
return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL; return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL;
} }
@@ -3955,8 +3992,14 @@ static int lfs2_rename_(lfs2_t *lfs2, const char *oldpath, const char *newpath)
struct lfs2_mlist prevdir; struct lfs2_mlist prevdir;
prevdir.next = lfs2->mlist; prevdir.next = lfs2->mlist;
if (prevtag == LFS2_ERR_NOENT) { if (prevtag == LFS2_ERR_NOENT) {
// if we're a file, don't allow trailing slashes
if (lfs2_path_isdir(newpath)
&& lfs2_tag_type3(oldtag) != LFS2_TYPE_DIR) {
return LFS2_ERR_NOTDIR;
}
// check that name fits // check that name fits
lfs2_size_t nlen = strlen(newpath); lfs2_size_t nlen = lfs2_path_namelen(newpath);
if (nlen > lfs2->name_max) { if (nlen > lfs2->name_max) {
return LFS2_ERR_NAMETOOLONG; return LFS2_ERR_NAMETOOLONG;
} }
@@ -4016,7 +4059,8 @@ static int lfs2_rename_(lfs2_t *lfs2, const char *oldpath, const char *newpath)
{LFS2_MKTAG_IF(prevtag != LFS2_ERR_NOENT, {LFS2_MKTAG_IF(prevtag != LFS2_ERR_NOENT,
LFS2_TYPE_DELETE, newid, 0), NULL}, LFS2_TYPE_DELETE, newid, 0), NULL},
{LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL},
{LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), newpath}, {LFS2_MKTAG(lfs2_tag_type3(oldtag),
newid, lfs2_path_namelen(newpath)), newpath},
{LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd}, {LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd},
{LFS2_MKTAG_IF(samepair, {LFS2_MKTAG_IF(samepair,
LFS2_TYPE_DELETE, newoldid, 0), NULL})); LFS2_TYPE_DELETE, newoldid, 0), NULL}));
@@ -4173,6 +4217,14 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
// which littlefs currently does not support // which littlefs currently does not support
LFS2_ASSERT((bool)0x80000000); LFS2_ASSERT((bool)0x80000000);
// check that the required io functions are provided
LFS2_ASSERT(lfs2->cfg->read != NULL);
#ifndef LFS2_READONLY
LFS2_ASSERT(lfs2->cfg->prog != NULL);
LFS2_ASSERT(lfs2->cfg->erase != NULL);
LFS2_ASSERT(lfs2->cfg->sync != NULL);
#endif
// validate that the lfs2-cfg sizes were initiated properly before // validate that the lfs2-cfg sizes were initiated properly before
// performing any arithmetic logics with them // performing any arithmetic logics with them
LFS2_ASSERT(lfs2->cfg->read_size != 0); LFS2_ASSERT(lfs2->cfg->read_size != 0);
@@ -4209,6 +4261,15 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
LFS2_ASSERT(lfs2->cfg->compact_thresh == (lfs2_size_t)-1 LFS2_ASSERT(lfs2->cfg->compact_thresh == (lfs2_size_t)-1
|| lfs2->cfg->compact_thresh <= lfs2->cfg->block_size); || lfs2->cfg->compact_thresh <= lfs2->cfg->block_size);
// check that metadata_max is a multiple of read_size and prog_size,
// and a factor of the block_size
LFS2_ASSERT(!lfs2->cfg->metadata_max
|| lfs2->cfg->metadata_max % lfs2->cfg->read_size == 0);
LFS2_ASSERT(!lfs2->cfg->metadata_max
|| lfs2->cfg->metadata_max % lfs2->cfg->prog_size == 0);
LFS2_ASSERT(!lfs2->cfg->metadata_max
|| lfs2->cfg->block_size % lfs2->cfg->metadata_max == 0);
// setup read cache // setup read cache
if (lfs2->cfg->read_buffer) { if (lfs2->cfg->read_buffer) {
lfs2->rcache.buffer = lfs2->cfg->read_buffer; lfs2->rcache.buffer = lfs2->cfg->read_buffer;
@@ -4396,6 +4457,30 @@ cleanup:
} }
#endif #endif
struct lfs2_tortoise_t {
lfs2_block_t pair[2];
lfs2_size_t i;
lfs2_size_t period;
};
static int lfs2_tortoise_detectcycles(
const lfs2_mdir_t *dir, struct lfs2_tortoise_t *tortoise) {
// detect cycles with Brent's algorithm
if (lfs2_pair_issync(dir->tail, tortoise->pair)) {
LFS2_WARN("Cycle detected in tail list");
return LFS2_ERR_CORRUPT;
}
if (tortoise->i == tortoise->period) {
tortoise->pair[0] = dir->tail[0];
tortoise->pair[1] = dir->tail[1];
tortoise->i = 0;
tortoise->period *= 2;
}
tortoise->i += 1;
return LFS2_ERR_OK;
}
static int lfs2_mount_(lfs2_t *lfs2, const struct lfs2_config *cfg) { static int lfs2_mount_(lfs2_t *lfs2, const struct lfs2_config *cfg) {
int err = lfs2_init(lfs2, cfg); int err = lfs2_init(lfs2, cfg);
if (err) { if (err) {
@@ -4404,23 +4489,16 @@ static int lfs2_mount_(lfs2_t *lfs2, const struct lfs2_config *cfg) {
// scan directory blocks for superblock and any global updates // scan directory blocks for superblock and any global updates
lfs2_mdir_t dir = {.tail = {0, 1}}; lfs2_mdir_t dir = {.tail = {0, 1}};
lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; struct lfs2_tortoise_t tortoise = {
lfs2_size_t tortoise_i = 1; .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
lfs2_size_t tortoise_period = 1; .i = 1,
.period = 1,
};
while (!lfs2_pair_isnull(dir.tail)) { while (!lfs2_pair_isnull(dir.tail)) {
// detect cycles with Brent's algorithm err = lfs2_tortoise_detectcycles(&dir, &tortoise);
if (lfs2_pair_issync(dir.tail, tortoise)) { if (err < 0) {
LFS2_WARN("Cycle detected in tail list");
err = LFS2_ERR_CORRUPT;
goto cleanup; goto cleanup;
} }
if (tortoise_i == tortoise_period) {
tortoise[0] = dir.tail[0];
tortoise[1] = dir.tail[1];
tortoise_i = 0;
tortoise_period *= 2;
}
tortoise_i += 1;
// fetch next block in tail list // fetch next block in tail list
lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail, lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail,
@@ -4633,22 +4711,17 @@ int lfs2_fs_traverse_(lfs2_t *lfs2,
} }
#endif #endif
lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; struct lfs2_tortoise_t tortoise = {
lfs2_size_t tortoise_i = 1; .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
lfs2_size_t tortoise_period = 1; .i = 1,
.period = 1,
};
int err = LFS2_ERR_OK;
while (!lfs2_pair_isnull(dir.tail)) { while (!lfs2_pair_isnull(dir.tail)) {
// detect cycles with Brent's algorithm err = lfs2_tortoise_detectcycles(&dir, &tortoise);
if (lfs2_pair_issync(dir.tail, tortoise)) { if (err < 0) {
LFS2_WARN("Cycle detected in tail list");
return LFS2_ERR_CORRUPT; return LFS2_ERR_CORRUPT;
} }
if (tortoise_i == tortoise_period) {
tortoise[0] = dir.tail[0];
tortoise[1] = dir.tail[1];
tortoise_i = 0;
tortoise_period *= 2;
}
tortoise_i += 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
int err = cb(data, dir.tail[i]); int err = cb(data, dir.tail[i]);
@@ -4727,22 +4800,17 @@ static int lfs2_fs_pred(lfs2_t *lfs2,
// iterate over all directory directory entries // iterate over all directory directory entries
pdir->tail[0] = 0; pdir->tail[0] = 0;
pdir->tail[1] = 1; pdir->tail[1] = 1;
lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; struct lfs2_tortoise_t tortoise = {
lfs2_size_t tortoise_i = 1; .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
lfs2_size_t tortoise_period = 1; .i = 1,
.period = 1,
};
int err = LFS2_ERR_OK;
while (!lfs2_pair_isnull(pdir->tail)) { while (!lfs2_pair_isnull(pdir->tail)) {
// detect cycles with Brent's algorithm err = lfs2_tortoise_detectcycles(pdir, &tortoise);
if (lfs2_pair_issync(pdir->tail, tortoise)) { if (err < 0) {
LFS2_WARN("Cycle detected in tail list");
return LFS2_ERR_CORRUPT; return LFS2_ERR_CORRUPT;
} }
if (tortoise_i == tortoise_period) {
tortoise[0] = pdir->tail[0];
tortoise[1] = pdir->tail[1];
tortoise_i = 0;
tortoise_period *= 2;
}
tortoise_i += 1;
if (lfs2_pair_cmp(pdir->tail, pair) == 0) { if (lfs2_pair_cmp(pdir->tail, pair) == 0) {
return 0; return 0;
@@ -4792,22 +4860,17 @@ static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2],
// use fetchmatch with callback to find pairs // use fetchmatch with callback to find pairs
parent->tail[0] = 0; parent->tail[0] = 0;
parent->tail[1] = 1; parent->tail[1] = 1;
lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; struct lfs2_tortoise_t tortoise = {
lfs2_size_t tortoise_i = 1; .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
lfs2_size_t tortoise_period = 1; .i = 1,
.period = 1,
};
int err = LFS2_ERR_OK;
while (!lfs2_pair_isnull(parent->tail)) { while (!lfs2_pair_isnull(parent->tail)) {
// detect cycles with Brent's algorithm err = lfs2_tortoise_detectcycles(parent, &tortoise);
if (lfs2_pair_issync(parent->tail, tortoise)) { if (err < 0) {
LFS2_WARN("Cycle detected in tail list"); return err;
return LFS2_ERR_CORRUPT;
} }
if (tortoise_i == tortoise_period) {
tortoise[0] = parent->tail[0];
tortoise[1] = parent->tail[1];
tortoise_i = 0;
tortoise_period *= 2;
}
tortoise_i += 1;
lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail, lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail,
LFS2_MKTAG(0x7ff, 0, 0x3ff), LFS2_MKTAG(0x7ff, 0, 0x3ff),
@@ -5890,7 +5953,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", "
".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " ".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
".lookahead_size=%"PRIu32", .read_buffer=%p, " ".lookahead_size=%"PRIu32", .read_buffer=%p, "
".prog_buffer=%p, .lookahead_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, "
".name_max=%"PRIu32", .file_max=%"PRIu32", " ".name_max=%"PRIu32", .file_max=%"PRIu32", "
@@ -5920,7 +5983,7 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", "
".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " ".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
".lookahead_size=%"PRIu32", .read_buffer=%p, " ".lookahead_size=%"PRIu32", .read_buffer=%p, "
".prog_buffer=%p, .lookahead_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, "
".name_max=%"PRIu32", .file_max=%"PRIu32", " ".name_max=%"PRIu32", .file_max=%"PRIu32", "
@@ -6057,7 +6120,7 @@ int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags)
return err; return err;
} }
LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)", LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)",
(void*)lfs2, (void*)file, path, flags); (void*)lfs2, (void*)file, path, (unsigned)flags);
LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
err = lfs2_file_open_(lfs2, file, path, flags); err = lfs2_file_open_(lfs2, file, path, flags);
@@ -6077,7 +6140,7 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
} }
LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {" LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {"
".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})", ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
(void*)lfs2, (void*)file, path, flags, (void*)lfs2, (void*)file, path, (unsigned)flags,
(void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
@@ -6439,7 +6502,7 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", "
".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " ".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
".lookahead_size=%"PRIu32", .read_buffer=%p, " ".lookahead_size=%"PRIu32", .read_buffer=%p, "
".prog_buffer=%p, .lookahead_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, "
".name_max=%"PRIu32", .file_max=%"PRIu32", " ".name_max=%"PRIu32", .file_max=%"PRIu32", "
+1 -1
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 LFS2_VERSION 0x00020009 #define LFS2_VERSION 0x0002000a
#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16)) #define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16))
#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0)) #define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0))
+20 -2
View File
@@ -8,6 +8,9 @@
#ifndef LFS2_UTIL_H #ifndef LFS2_UTIL_H
#define LFS2_UTIL_H #define LFS2_UTIL_H
#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x)
#define LFS2_STRINGIZE2(x) #x
// Users can override lfs2_util.h with their own configuration by defining // Users can override lfs2_util.h with their own configuration by defining
// LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h). // LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h).
// //
@@ -15,11 +18,26 @@
// provided by the config file. To start, I would suggest copying lfs2_util.h // provided by the config file. To start, I would suggest copying lfs2_util.h
// and modifying as needed. // and modifying as needed.
#ifdef LFS2_CONFIG #ifdef LFS2_CONFIG
#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x)
#define LFS2_STRINGIZE2(x) #x
#include LFS2_STRINGIZE(LFS2_CONFIG) #include LFS2_STRINGIZE(LFS2_CONFIG)
#else #else
// Alternatively, users can provide a header file which defines
// macros and other things consumed by littlefs.
//
// For example, provide my_defines.h, which contains
// something like:
//
// #include <stddef.h>
// extern void *my_malloc(size_t sz);
// #define LFS2_MALLOC(sz) my_malloc(sz)
//
// And build littlefs with the header by defining LFS2_DEFINES.
// (-DLFS2_DEFINES=my_defines.h)
#ifdef LFS2_DEFINES
#include LFS2_STRINGIZE(LFS2_DEFINES)
#endif
// System includes // System includes
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
+1
View File
@@ -1322,6 +1322,7 @@ void perm_run(
.cache_size = CACHE_SIZE, .cache_size = CACHE_SIZE,
.lookahead_size = LOOKAHEAD_SIZE, .lookahead_size = LOOKAHEAD_SIZE,
.compact_thresh = COMPACT_THRESH, .compact_thresh = COMPACT_THRESH,
.metadata_max = METADATA_MAX,
.inline_max = INLINE_MAX, .inline_max = INLINE_MAX,
}; };
+10 -7
View File
@@ -96,12 +96,13 @@ intmax_t bench_define(size_t define);
#define CACHE_SIZE_i 6 #define CACHE_SIZE_i 6
#define LOOKAHEAD_SIZE_i 7 #define LOOKAHEAD_SIZE_i 7
#define COMPACT_THRESH_i 8 #define COMPACT_THRESH_i 8
#define INLINE_MAX_i 9 #define METADATA_MAX_i 9
#define BLOCK_CYCLES_i 10 #define INLINE_MAX_i 10
#define ERASE_VALUE_i 11 #define BLOCK_CYCLES_i 11
#define ERASE_CYCLES_i 12 #define ERASE_VALUE_i 12
#define BADBLOCK_BEHAVIOR_i 13 #define ERASE_CYCLES_i 13
#define POWERLOSS_BEHAVIOR_i 14 #define BADBLOCK_BEHAVIOR_i 14
#define POWERLOSS_BEHAVIOR_i 15
#define READ_SIZE bench_define(READ_SIZE_i) #define READ_SIZE bench_define(READ_SIZE_i)
#define PROG_SIZE bench_define(PROG_SIZE_i) #define PROG_SIZE bench_define(PROG_SIZE_i)
@@ -112,6 +113,7 @@ intmax_t bench_define(size_t define);
#define CACHE_SIZE bench_define(CACHE_SIZE_i) #define CACHE_SIZE bench_define(CACHE_SIZE_i)
#define LOOKAHEAD_SIZE bench_define(LOOKAHEAD_SIZE_i) #define LOOKAHEAD_SIZE bench_define(LOOKAHEAD_SIZE_i)
#define COMPACT_THRESH bench_define(COMPACT_THRESH_i) #define COMPACT_THRESH bench_define(COMPACT_THRESH_i)
#define METADATA_MAX bench_define(METADATA_MAX_i)
#define INLINE_MAX bench_define(INLINE_MAX_i) #define INLINE_MAX bench_define(INLINE_MAX_i)
#define BLOCK_CYCLES bench_define(BLOCK_CYCLES_i) #define BLOCK_CYCLES bench_define(BLOCK_CYCLES_i)
#define ERASE_VALUE bench_define(ERASE_VALUE_i) #define ERASE_VALUE bench_define(ERASE_VALUE_i)
@@ -129,6 +131,7 @@ intmax_t bench_define(size_t define);
BENCH_DEF(CACHE_SIZE, lfs2_max(64,lfs2_max(READ_SIZE,PROG_SIZE))) \ BENCH_DEF(CACHE_SIZE, lfs2_max(64,lfs2_max(READ_SIZE,PROG_SIZE))) \
BENCH_DEF(LOOKAHEAD_SIZE, 16) \ BENCH_DEF(LOOKAHEAD_SIZE, 16) \
BENCH_DEF(COMPACT_THRESH, 0) \ BENCH_DEF(COMPACT_THRESH, 0) \
BENCH_DEF(METADATA_MAX, 0) \
BENCH_DEF(INLINE_MAX, 0) \ BENCH_DEF(INLINE_MAX, 0) \
BENCH_DEF(BLOCK_CYCLES, -1) \ BENCH_DEF(BLOCK_CYCLES, -1) \
BENCH_DEF(ERASE_VALUE, 0xff) \ BENCH_DEF(ERASE_VALUE, 0xff) \
@@ -137,7 +140,7 @@ intmax_t bench_define(size_t define);
BENCH_DEF(POWERLOSS_BEHAVIOR, LFS2_EMUBD_POWERLOSS_NOOP) BENCH_DEF(POWERLOSS_BEHAVIOR, LFS2_EMUBD_POWERLOSS_NOOP)
#define BENCH_GEOMETRY_DEFINE_COUNT 4 #define BENCH_GEOMETRY_DEFINE_COUNT 4
#define BENCH_IMPLICIT_DEFINE_COUNT 15 #define BENCH_IMPLICIT_DEFINE_COUNT 16
#endif #endif
+5
View File
@@ -1347,6 +1347,7 @@ static void run_powerloss_none(
.cache_size = CACHE_SIZE, .cache_size = CACHE_SIZE,
.lookahead_size = LOOKAHEAD_SIZE, .lookahead_size = LOOKAHEAD_SIZE,
.compact_thresh = COMPACT_THRESH, .compact_thresh = COMPACT_THRESH,
.metadata_max = METADATA_MAX,
.inline_max = INLINE_MAX, .inline_max = INLINE_MAX,
#ifdef LFS2_MULTIVERSION #ifdef LFS2_MULTIVERSION
.disk_version = DISK_VERSION, .disk_version = DISK_VERSION,
@@ -1425,6 +1426,7 @@ static void run_powerloss_linear(
.cache_size = CACHE_SIZE, .cache_size = CACHE_SIZE,
.lookahead_size = LOOKAHEAD_SIZE, .lookahead_size = LOOKAHEAD_SIZE,
.compact_thresh = COMPACT_THRESH, .compact_thresh = COMPACT_THRESH,
.metadata_max = METADATA_MAX,
.inline_max = INLINE_MAX, .inline_max = INLINE_MAX,
#ifdef LFS2_MULTIVERSION #ifdef LFS2_MULTIVERSION
.disk_version = DISK_VERSION, .disk_version = DISK_VERSION,
@@ -1520,6 +1522,7 @@ static void run_powerloss_log(
.cache_size = CACHE_SIZE, .cache_size = CACHE_SIZE,
.lookahead_size = LOOKAHEAD_SIZE, .lookahead_size = LOOKAHEAD_SIZE,
.compact_thresh = COMPACT_THRESH, .compact_thresh = COMPACT_THRESH,
.metadata_max = METADATA_MAX,
.inline_max = INLINE_MAX, .inline_max = INLINE_MAX,
#ifdef LFS2_MULTIVERSION #ifdef LFS2_MULTIVERSION
.disk_version = DISK_VERSION, .disk_version = DISK_VERSION,
@@ -1613,6 +1616,7 @@ static void run_powerloss_cycles(
.cache_size = CACHE_SIZE, .cache_size = CACHE_SIZE,
.lookahead_size = LOOKAHEAD_SIZE, .lookahead_size = LOOKAHEAD_SIZE,
.compact_thresh = COMPACT_THRESH, .compact_thresh = COMPACT_THRESH,
.metadata_max = METADATA_MAX,
.inline_max = INLINE_MAX, .inline_max = INLINE_MAX,
#ifdef LFS2_MULTIVERSION #ifdef LFS2_MULTIVERSION
.disk_version = DISK_VERSION, .disk_version = DISK_VERSION,
@@ -1804,6 +1808,7 @@ static void run_powerloss_exhaustive(
.cache_size = CACHE_SIZE, .cache_size = CACHE_SIZE,
.lookahead_size = LOOKAHEAD_SIZE, .lookahead_size = LOOKAHEAD_SIZE,
.compact_thresh = COMPACT_THRESH, .compact_thresh = COMPACT_THRESH,
.metadata_max = METADATA_MAX,
.inline_max = INLINE_MAX, .inline_max = INLINE_MAX,
#ifdef LFS2_MULTIVERSION #ifdef LFS2_MULTIVERSION
.disk_version = DISK_VERSION, .disk_version = DISK_VERSION,
+11 -8
View File
@@ -89,13 +89,14 @@ intmax_t test_define(size_t define);
#define CACHE_SIZE_i 6 #define CACHE_SIZE_i 6
#define LOOKAHEAD_SIZE_i 7 #define LOOKAHEAD_SIZE_i 7
#define COMPACT_THRESH_i 8 #define COMPACT_THRESH_i 8
#define INLINE_MAX_i 9 #define METADATA_MAX_i 9
#define BLOCK_CYCLES_i 10 #define INLINE_MAX_i 10
#define ERASE_VALUE_i 11 #define BLOCK_CYCLES_i 11
#define ERASE_CYCLES_i 12 #define ERASE_VALUE_i 12
#define BADBLOCK_BEHAVIOR_i 13 #define ERASE_CYCLES_i 13
#define POWERLOSS_BEHAVIOR_i 14 #define BADBLOCK_BEHAVIOR_i 14
#define DISK_VERSION_i 15 #define POWERLOSS_BEHAVIOR_i 15
#define DISK_VERSION_i 16
#define READ_SIZE TEST_DEFINE(READ_SIZE_i) #define READ_SIZE TEST_DEFINE(READ_SIZE_i)
#define PROG_SIZE TEST_DEFINE(PROG_SIZE_i) #define PROG_SIZE TEST_DEFINE(PROG_SIZE_i)
@@ -106,6 +107,7 @@ intmax_t test_define(size_t define);
#define CACHE_SIZE TEST_DEFINE(CACHE_SIZE_i) #define CACHE_SIZE TEST_DEFINE(CACHE_SIZE_i)
#define LOOKAHEAD_SIZE TEST_DEFINE(LOOKAHEAD_SIZE_i) #define LOOKAHEAD_SIZE TEST_DEFINE(LOOKAHEAD_SIZE_i)
#define COMPACT_THRESH TEST_DEFINE(COMPACT_THRESH_i) #define COMPACT_THRESH TEST_DEFINE(COMPACT_THRESH_i)
#define METADATA_MAX TEST_DEFINE(METADATA_MAX_i)
#define INLINE_MAX TEST_DEFINE(INLINE_MAX_i) #define INLINE_MAX TEST_DEFINE(INLINE_MAX_i)
#define BLOCK_CYCLES TEST_DEFINE(BLOCK_CYCLES_i) #define BLOCK_CYCLES TEST_DEFINE(BLOCK_CYCLES_i)
#define ERASE_VALUE TEST_DEFINE(ERASE_VALUE_i) #define ERASE_VALUE TEST_DEFINE(ERASE_VALUE_i)
@@ -124,6 +126,7 @@ intmax_t test_define(size_t define);
TEST_DEF(CACHE_SIZE, lfs2_max(64,lfs2_max(READ_SIZE,PROG_SIZE))) \ TEST_DEF(CACHE_SIZE, lfs2_max(64,lfs2_max(READ_SIZE,PROG_SIZE))) \
TEST_DEF(LOOKAHEAD_SIZE, 16) \ TEST_DEF(LOOKAHEAD_SIZE, 16) \
TEST_DEF(COMPACT_THRESH, 0) \ TEST_DEF(COMPACT_THRESH, 0) \
TEST_DEF(METADATA_MAX, 0) \
TEST_DEF(INLINE_MAX, 0) \ TEST_DEF(INLINE_MAX, 0) \
TEST_DEF(BLOCK_CYCLES, -1) \ TEST_DEF(BLOCK_CYCLES, -1) \
TEST_DEF(ERASE_VALUE, 0xff) \ TEST_DEF(ERASE_VALUE, 0xff) \
@@ -133,7 +136,7 @@ intmax_t test_define(size_t define);
TEST_DEF(DISK_VERSION, 0) TEST_DEF(DISK_VERSION, 0)
#define TEST_GEOMETRY_DEFINE_COUNT 4 #define TEST_GEOMETRY_DEFINE_COUNT 4
#define TEST_IMPLICIT_DEFINE_COUNT 16 #define TEST_IMPLICIT_DEFINE_COUNT 17
#endif #endif
+26
View File
@@ -86,6 +86,13 @@ def write_header(f, limit=LIMIT):
f.writeln("}") f.writeln("}")
f.writeln() f.writeln()
f.writeln("__attribute__((unused))") f.writeln("__attribute__((unused))")
f.writeln("static void __pretty_assert_print_ptr(")
f.writeln(" const void *v, size_t size) {")
f.writeln(" (void)size;")
f.writeln(" printf(\"%p\", v);")
f.writeln("}")
f.writeln()
f.writeln("__attribute__((unused))")
f.writeln("static void __pretty_assert_print_mem(") f.writeln("static void __pretty_assert_print_mem(")
f.writeln(" const void *v, size_t size) {") f.writeln(" const void *v, size_t size) {")
f.writeln(" const uint8_t *v_ = v;") f.writeln(" const uint8_t *v_ = v;")
@@ -183,6 +190,23 @@ def write_header(f, limit=LIMIT):
f.writeln(" _rh, strlen(_rh)); \\") f.writeln(" _rh, strlen(_rh)); \\")
f.writeln(" } \\") f.writeln(" } \\")
f.writeln("} while (0)") f.writeln("} while (0)")
for op, cmp in sorted(CMP.items()):
# Only EQ and NE are supported when compared to NULL.
if cmp not in ['eq', 'ne']:
continue
f.writeln("#define __PRETTY_ASSERT_PTR_%s(lh, rh) do { \\"
% cmp.upper())
f.writeln(" const void *_lh = (const void*)(uintptr_t)lh; \\")
f.writeln(" const void *_rh = (const void*)(uintptr_t)rh; \\")
f.writeln(" if (!(_lh %s _rh)) { \\" % op)
f.writeln(" __pretty_assert_fail( \\")
f.writeln(" __FILE__, __LINE__, \\")
f.writeln(" __pretty_assert_print_ptr, \"%s\", \\"
% cmp)
f.writeln(" (const void*){_lh}, 0, \\")
f.writeln(" (const void*){_rh}, 0); \\")
f.writeln(" } \\")
f.writeln("} while (0)")
f.writeln() f.writeln()
f.writeln() f.writeln()
@@ -301,6 +325,8 @@ def p_assert(p):
cmp = p.expect('cmp') ; p.accept('ws') cmp = p.expect('cmp') ; p.accept('ws')
rh = p_expr(p) ; p.accept('ws') rh = p_expr(p) ; p.accept('ws')
p.expect(')') p.expect(')')
if rh == 'NULL' or lh == 'NULL':
return mkassert('ptr', CMP[cmp], lh, rh)
return mkassert('int', CMP[cmp], lh, rh) return mkassert('int', CMP[cmp], lh, rh)
except ParseFailure: except ParseFailure:
p.pop(state) p.pop(state)
+7256 -194
View File
File diff suppressed because it is too large Load Diff
+108
View File
@@ -405,3 +405,111 @@ code = '''
lfs2_file_close(&lfs2, &file) => 0; lfs2_file_close(&lfs2, &file) => 0;
lfs2_unmount(&lfs2) => 0; lfs2_unmount(&lfs2) => 0;
''' '''
# test possible overflow/underflow conditions
#
# note these need -fsanitize=undefined to consistently detect
# overflow/underflow conditions
[cases.test_seek_filemax]
code = '''
lfs2_t lfs2;
lfs2_format(&lfs2, cfg) => 0;
lfs2_mount(&lfs2, cfg) => 0;
lfs2_file_t file;
lfs2_file_open(&lfs2, &file, "kitty",
LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_APPEND) => 0;
uint8_t buffer[1024];
strcpy((char*)buffer, "kittycatcat");
size_t size = strlen((char*)buffer);
lfs2_file_write(&lfs2, &file, buffer, size) => size;
// seek with LFS2_SEEK_SET
lfs2_file_seek(&lfs2, &file, LFS2_FILE_MAX, LFS2_SEEK_SET) => LFS2_FILE_MAX;
// seek with LFS2_SEEK_CUR
lfs2_file_seek(&lfs2, &file, 0, LFS2_SEEK_CUR) => LFS2_FILE_MAX;
// the file hasn't changed size, so seek end takes us back to the offset=0
lfs2_file_seek(&lfs2, &file, +10, LFS2_SEEK_END) => size+10;
lfs2_file_close(&lfs2, &file) => 0;
lfs2_unmount(&lfs2) => 0;
'''
[cases.test_seek_underflow]
code = '''
lfs2_t lfs2;
lfs2_format(&lfs2, cfg) => 0;
lfs2_mount(&lfs2, cfg) => 0;
lfs2_file_t file;
lfs2_file_open(&lfs2, &file, "kitty",
LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_APPEND) => 0;
uint8_t buffer[1024];
strcpy((char*)buffer, "kittycatcat");
size_t size = strlen((char*)buffer);
lfs2_file_write(&lfs2, &file, buffer, size) => size;
// underflow with LFS2_SEEK_CUR, should error
lfs2_file_seek(&lfs2, &file, -(size+10), LFS2_SEEK_CUR) => LFS2_ERR_INVAL;
lfs2_file_seek(&lfs2, &file, -LFS2_FILE_MAX, LFS2_SEEK_CUR) => LFS2_ERR_INVAL;
lfs2_file_seek(&lfs2, &file, -(size+LFS2_FILE_MAX), LFS2_SEEK_CUR)
=> LFS2_ERR_INVAL;
// underflow with LFS2_SEEK_END, should error
lfs2_file_seek(&lfs2, &file, -(size+10), LFS2_SEEK_END) => LFS2_ERR_INVAL;
lfs2_file_seek(&lfs2, &file, -LFS2_FILE_MAX, LFS2_SEEK_END) => LFS2_ERR_INVAL;
lfs2_file_seek(&lfs2, &file, -(size+LFS2_FILE_MAX), LFS2_SEEK_END)
=> LFS2_ERR_INVAL;
// file pointer should not have changed
lfs2_file_tell(&lfs2, &file) => size;
lfs2_file_close(&lfs2, &file) => 0;
lfs2_unmount(&lfs2) => 0;
'''
[cases.test_seek_overflow]
code = '''
lfs2_t lfs2;
lfs2_format(&lfs2, cfg) => 0;
lfs2_mount(&lfs2, cfg) => 0;
lfs2_file_t file;
lfs2_file_open(&lfs2, &file, "kitty",
LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_APPEND) => 0;
uint8_t buffer[1024];
strcpy((char*)buffer, "kittycatcat");
size_t size = strlen((char*)buffer);
lfs2_file_write(&lfs2, &file, buffer, size) => size;
// seek to LFS2_FILE_MAX
lfs2_file_seek(&lfs2, &file, LFS2_FILE_MAX, LFS2_SEEK_SET) => LFS2_FILE_MAX;
// overflow with LFS2_SEEK_CUR, should error
lfs2_file_seek(&lfs2, &file, +10, LFS2_SEEK_CUR) => LFS2_ERR_INVAL;
lfs2_file_seek(&lfs2, &file, +LFS2_FILE_MAX, LFS2_SEEK_CUR) => LFS2_ERR_INVAL;
// LFS2_SEEK_SET/END don't care about the current file position, but we can
// still overflow with a large offset
// overflow with LFS2_SEEK_SET, should error
lfs2_file_seek(&lfs2, &file,
+((uint32_t)LFS2_FILE_MAX+10),
LFS2_SEEK_SET) => LFS2_ERR_INVAL;
lfs2_file_seek(&lfs2, &file,
+((uint32_t)LFS2_FILE_MAX+(uint32_t)LFS2_FILE_MAX),
LFS2_SEEK_SET) => LFS2_ERR_INVAL;
// overflow with LFS2_SEEK_END, should error
lfs2_file_seek(&lfs2, &file, +(LFS2_FILE_MAX-size+10), LFS2_SEEK_END)
=> LFS2_ERR_INVAL;
lfs2_file_seek(&lfs2, &file, +(LFS2_FILE_MAX-size+LFS2_FILE_MAX), LFS2_SEEK_END)
=> LFS2_ERR_INVAL;
// file pointer should not have changed
lfs2_file_tell(&lfs2, &file) => LFS2_FILE_MAX;
lfs2_file_close(&lfs2, &file) => 0;
lfs2_unmount(&lfs2) => 0;
'''
+27
View File
@@ -523,3 +523,30 @@ code = '''
assert(memcmp(buffer, "hello!", 6) == 0); assert(memcmp(buffer, "hello!", 6) == 0);
lfs2_unmount(&lfs2) => 0; lfs2_unmount(&lfs2) => 0;
''' '''
# test that metadata_max does not cause problems for superblock compaction
[cases.test_superblocks_metadata_max]
defines.METADATA_MAX = [
'lfs2_max(512, PROG_SIZE)',
'lfs2_max(BLOCK_SIZE/2, PROG_SIZE)',
'BLOCK_SIZE'
]
defines.N = [10, 100, 1000]
code = '''
lfs2_t lfs2;
lfs2_format(&lfs2, cfg) => 0;
lfs2_mount(&lfs2, cfg) => 0;
for (int i = 0; i < N; i++) {
lfs2_file_t file;
char name[256];
sprintf(name, "hello%03x", i);
lfs2_file_open(&lfs2, &file, name,
LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0;
lfs2_file_close(&lfs2, &file) => 0;
struct lfs2_info info;
lfs2_stat(&lfs2, name, &info) => 0;
assert(strcmp(info.name, name) == 0);
assert(info.type == LFS2_TYPE_REG);
}
lfs2_unmount(&lfs2) => 0;
'''