From ac207586bae9d086ccaa8ff71fc90509fa4f54bc Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 25 Jun 2024 15:59:43 -0500 Subject: [PATCH 01/28] Fixed some more LFS_TRACE format specifiers - block_cycles is signed and should use PRId32 - flags is signed (which is a bit weird) and should be cast for %x Unfortunately exactly what PRI* expands to is dependant on both the compiler and the underlying architecture, so I don't think it's possible for us to catch these mistakes with CI... Found by stefano-zanotti --- lfs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lfs.c b/lfs.c index d35d5d6d..e064c7c0 100644 --- a/lfs.c +++ b/lfs.c @@ -5890,7 +5890,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"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, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -5920,7 +5920,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"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, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -6057,7 +6057,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) { return err; } LFS_TRACE("lfs_file_open(%p, %p, \"%s\", %x)", - (void*)lfs, (void*)file, path, flags); + (void*)lfs, (void*)file, path, (unsigned)flags); LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file)); err = lfs_file_open_(lfs, file, path, flags); @@ -6077,7 +6077,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, } LFS_TRACE("lfs_file_opencfg(%p, %p, \"%s\", %x, %p {" ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})", - (void*)lfs, (void*)file, path, flags, + (void*)lfs, (void*)file, path, (unsigned)flags, (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file)); @@ -6439,7 +6439,7 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"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, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " From 6e7269890a29d8b3dc1e1783c98fdf6f84732190 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 18 Sep 2024 15:27:55 +0900 Subject: [PATCH 02/28] gha: Update github actions to the latest versions --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 52 +++++++++++++++++------------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 055b54a0..fe05897c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: github.event.workflow_run.head_sha == github.sha}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 with: ref: ${{github.event.workflow_run.head_sha}} # need workflow access since we push branches diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index db3413bb..b130795c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: arch: [x86_64, thumb, mips, powerpc] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -235,7 +235,7 @@ jobs: # create size statuses - name: upload-sizes - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.4.0 with: name: sizes path: sizes @@ -273,7 +273,7 @@ jobs: }' | tee status/$(basename $f .csv).json done - name: upload-status-sizes - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.4.0 with: name: status path: status @@ -282,7 +282,7 @@ jobs: # create cov statuses - name: upload-cov if: ${{matrix.arch == 'x86_64'}} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.4.0 with: name: cov path: cov @@ -319,7 +319,7 @@ jobs: done - name: upload-status-sizes if: ${{matrix.arch == 'x86_64'}} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.4.0 with: name: status path: status @@ -336,7 +336,7 @@ jobs: pls: [1, 2] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -361,7 +361,7 @@ jobs: test-no-intrinsics: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -378,7 +378,7 @@ jobs: test-multiversion: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -395,7 +395,7 @@ jobs: test-lfs2_0: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -414,7 +414,7 @@ jobs: test-valgrind: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -436,7 +436,7 @@ jobs: test-clang: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -459,7 +459,7 @@ jobs: bench: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -491,7 +491,7 @@ jobs: # create bench statuses - name: upload-bench - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.4.0 with: name: bench path: bench @@ -525,7 +525,7 @@ jobs: }' | tee status/$(basename $f .csv)-$s.json done - name: upload-status-bench - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.4.0 with: name: status path: status @@ -535,10 +535,10 @@ jobs: test-compat: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 if: ${{github.event_name == 'pull_request'}} # checkout the current pr target into lfsp - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 if: ${{github.event_name == 'pull_request'}} with: ref: ${{github.event.pull_request.base.ref}} @@ -572,7 +572,7 @@ jobs: runs-on: ubuntu-latest if: ${{!endsWith(github.ref, '-prefix')}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -582,7 +582,7 @@ jobs: gcc --version python3 --version fusermount -V - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 with: repository: littlefs-project/littlefs-fuse ref: v2 @@ -622,7 +622,7 @@ jobs: runs-on: ubuntu-latest if: ${{!endsWith(github.ref, '-prefix')}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 - name: install run: | # need a few things @@ -632,12 +632,12 @@ jobs: gcc --version python3 --version fusermount -V - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 with: repository: littlefs-project/littlefs-fuse ref: v2 path: v2 - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 with: repository: littlefs-project/littlefs-fuse ref: v1 @@ -694,7 +694,7 @@ jobs: runs-on: ubuntu-latest needs: [test, bench] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4.1.7 if: ${{github.event_name == 'pull_request'}} - name: install if: ${{github.event_name == 'pull_request'}} @@ -704,19 +704,19 @@ jobs: pip3 install toml gcc --version python3 --version - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4.1.8 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: name: sizes path: sizes - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4.1.8 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: name: cov path: cov - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4.1.8 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: @@ -862,7 +862,7 @@ jobs: body: $comment, }' | tee comment/comment.json - name: upload-comment - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.4.0 with: name: comment path: comment From 72a4b57f4e87c6796329e4c40a04b5b04c4b5186 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 18 Sep 2024 15:53:24 +0900 Subject: [PATCH 03/28] gha: Make the artifact names unique --- .github/workflows/test.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b130795c..4575351f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -237,7 +237,7 @@ jobs: - name: upload-sizes uses: actions/upload-artifact@v4.4.0 with: - name: sizes + name: sizes-${{matrix.arch}} path: sizes - name: status-sizes run: | @@ -273,9 +273,10 @@ jobs: }' | tee status/$(basename $f .csv).json done - name: upload-status-sizes + if: ${{matrix.arch == 'x86_64'}} uses: actions/upload-artifact@v4.4.0 with: - name: status + name: status-sizes-${{matrix.arch}} path: status retention-days: 1 @@ -317,11 +318,11 @@ jobs: target_step: env.STEP, }' | tee status/$(basename $f .csv)-$s.json done - - name: upload-status-sizes + - name: upload-status-cov if: ${{matrix.arch == 'x86_64'}} uses: actions/upload-artifact@v4.4.0 with: - name: status + name: status-cov path: status retention-days: 1 @@ -527,7 +528,7 @@ jobs: - name: upload-status-bench uses: actions/upload-artifact@v4.4.0 with: - name: status + name: status-bench path: status retention-days: 1 @@ -708,7 +709,7 @@ jobs: if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: - name: sizes + name: sizes-x86_64 path: sizes - uses: actions/download-artifact@v4.1.8 if: ${{github.event_name == 'pull_request'}} From 2c4b262c3549e4e700f9bb2c4ec76d775a6114bf Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 19 Sep 2024 12:36:20 -0500 Subject: [PATCH 04/28] gha: Merge artifacts on download Turns out major versions break things. Old behavior: Artifacts with same name are merged New behavior: Artifacts with same name error Using a pattern and merging on download should fix this at least on the job-side. Though I do wonder if we'll start running into artifact limit issues with the new way artifacts are handled... --- .github/workflows/release.yml | 15 +++++++++------ .github/workflows/status.yml | 10 ++++++---- .github/workflows/test.yml | 9 ++++++--- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fe05897c..b4588f32 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,26 +30,29 @@ jobs: fetch-depth: 0 # try to get results from tests - - uses: dawidd6/action-download-artifact@v2 + - uses: dawidd6/action-download-artifact@v6 continue-on-error: true with: workflow: ${{github.event.workflow_run.name}} run_id: ${{github.event.workflow_run.id}} - name: sizes + pattern: '{sizes,sizes-*}' + merge-multiple: true path: sizes - - uses: dawidd6/action-download-artifact@v2 + - uses: dawidd6/action-download-artifact@v6 continue-on-error: true with: workflow: ${{github.event.workflow_run.name}} run_id: ${{github.event.workflow_run.id}} - name: cov + pattern: '{cov,cov-*}' + merge-multiple: true path: cov - - uses: dawidd6/action-download-artifact@v2 + - uses: dawidd6/action-download-artifact@v6 continue-on-error: true with: workflow: ${{github.event.workflow_run.name}} run_id: ${{github.event.workflow_run.id}} - name: bench + pattern: '{bench,bench-*}' + merge-multiple: true path: bench - name: find-version diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml index e6e983a5..155040b7 100644 --- a/.github/workflows/status.yml +++ b/.github/workflows/status.yml @@ -13,12 +13,13 @@ jobs: status: runs-on: ubuntu-latest steps: - - uses: dawidd6/action-download-artifact@v2 + - uses: dawidd6/action-download-artifact@v6 continue-on-error: true with: workflow: ${{github.event.workflow_run.name}} run_id: ${{github.event.workflow_run.id}} - name: status + pattern: '{status,status-*}' + merge-multiple: true path: status - name: update-status continue-on-error: true @@ -67,12 +68,13 @@ jobs: steps: # generated comment? - - uses: dawidd6/action-download-artifact@v2 + - uses: dawidd6/action-download-artifact@v6 continue-on-error: true with: workflow: ${{github.event.workflow_run.name}} run_id: ${{github.event.workflow_run.id}} - name: comment + pattern: '{comment,comment-*}' + merge-multiple: true path: comment - name: update-comment continue-on-error: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4575351f..d80f4d79 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -709,19 +709,22 @@ jobs: if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: - name: sizes-x86_64 + pattern: '{sizes,sizes-*}' + merge-multiple: true path: sizes - uses: actions/download-artifact@v4.1.8 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: - name: cov + pattern: '{cov,cov-*}' + merge-multiple: true path: cov - uses: actions/download-artifact@v4.1.8 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: - name: bench + pattern: '{bench,bench-*}' + merge-multiple: true path: bench # try to find results from tests From 7db9e1663a3372988a5158c54775b8212e246a31 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 19 Sep 2024 14:30:43 -0500 Subject: [PATCH 05/28] gha: Switched to standard da for cross-workflow downloads Looks like cross-workflow downloads has finally been added to the standard download-artifact action, so we might as well switch to it to reduce dependencies. dawidd6's version was also missing the merge-multiple feature which is necessary to work around breaking changes in download-artifact's v4 bump. Weirdly it needs GITHUB_TOKEN for some reason? Not sure why this couldn't be implicit. --- .github/workflows/release.yml | 18 +++++++++--------- .github/workflows/status.yml | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b4588f32..f969b2f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,27 +30,27 @@ jobs: fetch-depth: 0 # try to get results from tests - - uses: dawidd6/action-download-artifact@v6 + - uses: actions/download-artifact@v4.1.8 continue-on-error: true with: - workflow: ${{github.event.workflow_run.name}} - run_id: ${{github.event.workflow_run.id}} + github-token: ${{secrets.GITHUB_TOKEN}} + run-id: ${{github.event.workflow_run.id}} pattern: '{sizes,sizes-*}' merge-multiple: true path: sizes - - uses: dawidd6/action-download-artifact@v6 + - uses: actions/download-artifact@v4.1.8 continue-on-error: true with: - workflow: ${{github.event.workflow_run.name}} - run_id: ${{github.event.workflow_run.id}} + github-token: ${{secrets.GITHUB_TOKEN}} + run-id: ${{github.event.workflow_run.id}} pattern: '{cov,cov-*}' merge-multiple: true path: cov - - uses: dawidd6/action-download-artifact@v6 + - uses: actions/download-artifact@v4.1.8 continue-on-error: true with: - workflow: ${{github.event.workflow_run.name}} - run_id: ${{github.event.workflow_run.id}} + github-token: ${{secrets.GITHUB_TOKEN}} + run-id: ${{github.event.workflow_run.id}} pattern: '{bench,bench-*}' merge-multiple: true path: bench diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml index 155040b7..198af98e 100644 --- a/.github/workflows/status.yml +++ b/.github/workflows/status.yml @@ -13,11 +13,11 @@ jobs: status: runs-on: ubuntu-latest steps: - - uses: dawidd6/action-download-artifact@v6 + - uses: actions/download-artifact@v4.1.8 continue-on-error: true with: - workflow: ${{github.event.workflow_run.name}} - run_id: ${{github.event.workflow_run.id}} + github-token: ${{secrets.GITHUB_TOKEN}} + run-id: ${{github.event.workflow_run.id}} pattern: '{status,status-*}' merge-multiple: true path: status @@ -68,11 +68,11 @@ jobs: steps: # generated comment? - - uses: dawidd6/action-download-artifact@v6 + - uses: actions/download-artifact@v4.1.8 continue-on-error: true with: - workflow: ${{github.event.workflow_run.name}} - run_id: ${{github.event.workflow_run.id}} + github-token: ${{secrets.GITHUB_TOKEN}} + run-id: ${{github.event.workflow_run.id}} pattern: '{comment,comment-*}' merge-multiple: true path: comment From 798073c2a7c7f10e2bb8711ff1b23931534b3db0 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 19 Sep 2024 17:13:03 -0500 Subject: [PATCH 06/28] gha: Dropped minor/patch version pinning of actions With GitHub forcibly deprecating old versions of actions, pinning the minor/patch version is more likely to cause breakage than not. --- .github/workflows/release.yml | 8 +++--- .github/workflows/status.yml | 4 +-- .github/workflows/test.yml | 52 +++++++++++++++++------------------ 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f969b2f1..2bbec095 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: github.event.workflow_run.head_sha == github.sha}} steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 with: ref: ${{github.event.workflow_run.head_sha}} # need workflow access since we push branches @@ -30,7 +30,7 @@ jobs: fetch-depth: 0 # try to get results from tests - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 continue-on-error: true with: github-token: ${{secrets.GITHUB_TOKEN}} @@ -38,7 +38,7 @@ jobs: pattern: '{sizes,sizes-*}' merge-multiple: true path: sizes - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 continue-on-error: true with: github-token: ${{secrets.GITHUB_TOKEN}} @@ -46,7 +46,7 @@ jobs: pattern: '{cov,cov-*}' merge-multiple: true path: cov - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 continue-on-error: true with: github-token: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/status.yml b/.github/workflows/status.yml index 198af98e..e631b07d 100644 --- a/.github/workflows/status.yml +++ b/.github/workflows/status.yml @@ -13,7 +13,7 @@ jobs: status: runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 continue-on-error: true with: github-token: ${{secrets.GITHUB_TOKEN}} @@ -68,7 +68,7 @@ jobs: steps: # generated comment? - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 continue-on-error: true with: github-token: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d80f4d79..48d00eff 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: arch: [x86_64, thumb, mips, powerpc] steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -235,7 +235,7 @@ jobs: # create size statuses - name: upload-sizes - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4 with: name: sizes-${{matrix.arch}} path: sizes @@ -274,7 +274,7 @@ jobs: done - name: upload-status-sizes if: ${{matrix.arch == 'x86_64'}} - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4 with: name: status-sizes-${{matrix.arch}} path: status @@ -283,7 +283,7 @@ jobs: # create cov statuses - name: upload-cov if: ${{matrix.arch == 'x86_64'}} - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4 with: name: cov path: cov @@ -320,7 +320,7 @@ jobs: done - name: upload-status-cov if: ${{matrix.arch == 'x86_64'}} - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4 with: name: status-cov path: status @@ -337,7 +337,7 @@ jobs: pls: [1, 2] steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -362,7 +362,7 @@ jobs: test-no-intrinsics: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -379,7 +379,7 @@ jobs: test-multiversion: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -396,7 +396,7 @@ jobs: test-lfs2_0: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -415,7 +415,7 @@ jobs: test-valgrind: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -437,7 +437,7 @@ jobs: test-clang: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -460,7 +460,7 @@ jobs: bench: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -492,7 +492,7 @@ jobs: # create bench statuses - name: upload-bench - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4 with: name: bench path: bench @@ -526,7 +526,7 @@ jobs: }' | tee status/$(basename $f .csv)-$s.json done - name: upload-status-bench - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4 with: name: status-bench path: status @@ -536,10 +536,10 @@ jobs: test-compat: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 if: ${{github.event_name == 'pull_request'}} # checkout the current pr target into lfsp - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 if: ${{github.event_name == 'pull_request'}} with: ref: ${{github.event.pull_request.base.ref}} @@ -573,7 +573,7 @@ jobs: runs-on: ubuntu-latest if: ${{!endsWith(github.ref, '-prefix')}} steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -583,7 +583,7 @@ jobs: gcc --version python3 --version fusermount -V - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 with: repository: littlefs-project/littlefs-fuse ref: v2 @@ -623,7 +623,7 @@ jobs: runs-on: ubuntu-latest if: ${{!endsWith(github.ref, '-prefix')}} steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 - name: install run: | # need a few things @@ -633,12 +633,12 @@ jobs: gcc --version python3 --version fusermount -V - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 with: repository: littlefs-project/littlefs-fuse ref: v2 path: v2 - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 with: repository: littlefs-project/littlefs-fuse ref: v1 @@ -695,7 +695,7 @@ jobs: runs-on: ubuntu-latest needs: [test, bench] steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4 if: ${{github.event_name == 'pull_request'}} - name: install if: ${{github.event_name == 'pull_request'}} @@ -705,21 +705,21 @@ jobs: pip3 install toml gcc --version python3 --version - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: pattern: '{sizes,sizes-*}' merge-multiple: true path: sizes - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: pattern: '{cov,cov-*}' merge-multiple: true path: cov - - uses: actions/download-artifact@v4.1.8 + - uses: actions/download-artifact@v4 if: ${{github.event_name == 'pull_request'}} continue-on-error: true with: @@ -866,7 +866,7 @@ jobs: body: $comment, }' | tee comment/comment.json - name: upload-comment - uses: actions/upload-artifact@v4.4.0 + uses: actions/upload-artifact@v4 with: name: comment path: comment From e1636d05ab281495511fef58ea1ec7776464bd0b Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 10 Jul 2024 14:52:08 +0900 Subject: [PATCH 07/28] Add an alternative way to override LFS_MALLOC etc With the existing method, (-DLFS_MALLOC=my_malloc) users often had to use compiler options like -include, which was not so portable. This change introduces another way to provide partial overrides of lfs_util.h using a user-provided header. --- lfs_util.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lfs_util.h b/lfs_util.h index 4e577009..91b740ef 100644 --- a/lfs_util.h +++ b/lfs_util.h @@ -8,6 +8,9 @@ #ifndef LFS_UTIL_H #define LFS_UTIL_H +#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) +#define LFS_STRINGIZE2(x) #x + // Users can override lfs_util.h with their own configuration by defining // LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h). // @@ -15,11 +18,26 @@ // provided by the config file. To start, I would suggest copying lfs_util.h // and modifying as needed. #ifdef LFS_CONFIG -#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) -#define LFS_STRINGIZE2(x) #x #include LFS_STRINGIZE(LFS_CONFIG) #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 +// extern void *my_malloc(size_t sz); +// #define LFS_MALLOC(sz) my_malloc(sz) +// +// And build littlefs with the header by defining LFS_USER_DEFINES. +// (-DLFS_USER_DEFINES=my_defines.h) + +#ifdef LFS_USER_DEFINES +#include LFS_STRINGIZE(LFS_USER_DEFINES) +#endif + // System includes #include #include From 4a845be0beccda3d9872eb4935f471e2eb245553 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 18 Sep 2024 15:17:17 +0900 Subject: [PATCH 08/28] Rename LFS_USER_DEFINES to LFS_DEFINES --- lfs_util.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lfs_util.h b/lfs_util.h index 91b740ef..0aec4885 100644 --- a/lfs_util.h +++ b/lfs_util.h @@ -31,11 +31,11 @@ // extern void *my_malloc(size_t sz); // #define LFS_MALLOC(sz) my_malloc(sz) // -// And build littlefs with the header by defining LFS_USER_DEFINES. -// (-DLFS_USER_DEFINES=my_defines.h) +// And build littlefs with the header by defining LFS_DEFINES. +// (-DLFS_DEFINES=my_defines.h) -#ifdef LFS_USER_DEFINES -#include LFS_STRINGIZE(LFS_USER_DEFINES) +#ifdef LFS_DEFINES +#include LFS_STRINGIZE(LFS_DEFINES) #endif // System includes From f1c430e779b81d891e9ce7fa7ea5acbcbc98d312 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 24 Sep 2024 13:31:23 -0500 Subject: [PATCH 09/28] Added some tests around seek integer overflow/underflow Original tests provided by m-kostrzewa, these identify signed overflow (undefined behavior) when compiled with -fsanitize=undefined. --- tests/test_seek.toml | 108 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/tests/test_seek.toml b/tests/test_seek.toml index 9b3768d7..33fb5785 100644 --- a/tests/test_seek.toml +++ b/tests/test_seek.toml @@ -405,3 +405,111 @@ code = ''' lfs_file_close(&lfs, &file) => 0; lfs_unmount(&lfs) => 0; ''' + + +# test possible overflow/underflow conditions +# +# note these need -fsanitize=undefined to consistently detect +# overflow/underflow conditions + +[cases.test_seek_filemax] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + lfs_file_t file; + lfs_file_open(&lfs, &file, "kitty", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; + uint8_t buffer[1024]; + strcpy((char*)buffer, "kittycatcat"); + size_t size = strlen((char*)buffer); + lfs_file_write(&lfs, &file, buffer, size) => size; + + // seek with LFS_SEEK_SET + lfs_file_seek(&lfs, &file, LFS_FILE_MAX, LFS_SEEK_SET) => LFS_FILE_MAX; + + // seek with LFS_SEEK_CUR + lfs_file_seek(&lfs, &file, 0, LFS_SEEK_CUR) => LFS_FILE_MAX; + + // the file hasn't changed size, so seek end takes us back to the offset=0 + lfs_file_seek(&lfs, &file, +10, LFS_SEEK_END) => size+10; + + lfs_file_close(&lfs, &file) => 0; + lfs_unmount(&lfs) => 0; +''' + +[cases.test_seek_underflow] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + lfs_file_t file; + lfs_file_open(&lfs, &file, "kitty", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; + uint8_t buffer[1024]; + strcpy((char*)buffer, "kittycatcat"); + size_t size = strlen((char*)buffer); + lfs_file_write(&lfs, &file, buffer, size) => size; + + // underflow with LFS_SEEK_CUR, should error + lfs_file_seek(&lfs, &file, -(size+10), LFS_SEEK_CUR) => LFS_ERR_INVAL; + lfs_file_seek(&lfs, &file, -LFS_FILE_MAX, LFS_SEEK_CUR) => LFS_ERR_INVAL; + lfs_file_seek(&lfs, &file, -(size+LFS_FILE_MAX), LFS_SEEK_CUR) + => LFS_ERR_INVAL; + + // underflow with LFS_SEEK_END, should error + lfs_file_seek(&lfs, &file, -(size+10), LFS_SEEK_END) => LFS_ERR_INVAL; + lfs_file_seek(&lfs, &file, -LFS_FILE_MAX, LFS_SEEK_END) => LFS_ERR_INVAL; + lfs_file_seek(&lfs, &file, -(size+LFS_FILE_MAX), LFS_SEEK_END) + => LFS_ERR_INVAL; + + // file pointer should not have changed + lfs_file_tell(&lfs, &file) => size; + + lfs_file_close(&lfs, &file) => 0; + lfs_unmount(&lfs) => 0; +''' + +[cases.test_seek_overflow] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + lfs_file_t file; + lfs_file_open(&lfs, &file, "kitty", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; + uint8_t buffer[1024]; + strcpy((char*)buffer, "kittycatcat"); + size_t size = strlen((char*)buffer); + lfs_file_write(&lfs, &file, buffer, size) => size; + + // seek to LFS_FILE_MAX + lfs_file_seek(&lfs, &file, LFS_FILE_MAX, LFS_SEEK_SET) => LFS_FILE_MAX; + + // overflow with LFS_SEEK_CUR, should error + lfs_file_seek(&lfs, &file, +10, LFS_SEEK_CUR) => LFS_ERR_INVAL; + lfs_file_seek(&lfs, &file, +LFS_FILE_MAX, LFS_SEEK_CUR) => LFS_ERR_INVAL; + + // LFS_SEEK_SET/END don't care about the current file position, but we can + // still overflow with a large offset + + // overflow with LFS_SEEK_SET, should error + lfs_file_seek(&lfs, &file, + +((uint32_t)LFS_FILE_MAX+10), + LFS_SEEK_SET) => LFS_ERR_INVAL; + lfs_file_seek(&lfs, &file, + +((uint32_t)LFS_FILE_MAX+(uint32_t)LFS_FILE_MAX), + LFS_SEEK_SET) => LFS_ERR_INVAL; + + // overflow with LFS_SEEK_END, should error + lfs_file_seek(&lfs, &file, +(LFS_FILE_MAX-size+10), LFS_SEEK_END) + => LFS_ERR_INVAL; + lfs_file_seek(&lfs, &file, +(LFS_FILE_MAX-size+LFS_FILE_MAX), LFS_SEEK_END) + => LFS_ERR_INVAL; + + // file pointer should not have changed + lfs_file_tell(&lfs, &file) => LFS_FILE_MAX; + + lfs_file_close(&lfs, &file) => 0; + lfs_unmount(&lfs) => 0; +''' From abaec45652a1e8c79f812c3e868f6c1063e06c51 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 24 Sep 2024 13:47:28 -0500 Subject: [PATCH 10/28] Fixed seek undefined behavior on signed integer overflow In the previous implementation of lfs_file_seek, we calculated the new offset using signed arithmetic before checking for possible overflow/underflow conditions. This results in undefined behavior in C. Fortunately for us, littlefs is now limited to 31-bit file sizes for API reasons, so we don't have to be too clever here. Doing the arithmetic with unsigned integers and just checking if we're in a valid range afterwards should work. Found by m-kostrzewa and lucic71 --- lfs.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/lfs.c b/lfs.c index d35d5d6d..933f69c7 100644 --- a/lfs.c +++ b/lfs.c @@ -3664,22 +3664,16 @@ static lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file, static lfs_soff_t lfs_file_seek_(lfs_t *lfs, lfs_file_t *file, lfs_soff_t off, int whence) { // 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 lfs_off_t npos = file->pos; if (whence == LFS_SEEK_SET) { npos = off; } else if (whence == LFS_SEEK_CUR) { - if ((lfs_soff_t)file->pos + off < 0) { - return LFS_ERR_INVAL; - } else { - npos = file->pos + off; - } + npos = file->pos + (lfs_off_t)off; } else if (whence == LFS_SEEK_END) { - lfs_soff_t res = lfs_file_size_(lfs, file) + off; - if (res < 0) { - return LFS_ERR_INVAL; - } else { - npos = res; - } + npos = (lfs_off_t)lfs_file_size_(lfs, file) + (lfs_off_t)off; } if (npos > lfs->file_max) { From a2c2e49e6b87c1871bba3b3b3c6fbaf48154fa3f Mon Sep 17 00:00:00 2001 From: wdfk-prog <1425075683@qq.com> Date: Fri, 4 Oct 2024 10:37:25 +0800 Subject: [PATCH 11/28] Write the detect cycles function as a function to optimize code --- lfs.c | 110 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/lfs.c b/lfs.c index d35d5d6d..b55b1e16 100644 --- a/lfs.c +++ b/lfs.c @@ -4396,6 +4396,30 @@ static int lfs_format_(lfs_t *lfs, const struct lfs_config *cfg) { } #endif +struct lfs_tortoise_t { + lfs_block_t pair[2]; + lfs_size_t i; + lfs_size_t period; +}; + +static int lfs_tortoise_detectcycles( + const lfs_mdir_t *dir, struct lfs_tortoise_t *tortoise) { + // detect cycles with Brent's algorithm + if (lfs_pair_issync(dir->tail, tortoise->pair)) { + LFS_WARN("Cycle detected in tail list"); + return LFS_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 LFS_ERR_OK; +} + static int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) { int err = lfs_init(lfs, cfg); if (err) { @@ -4404,23 +4428,16 @@ static int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) { // scan directory blocks for superblock and any global updates lfs_mdir_t dir = {.tail = {0, 1}}; - lfs_block_t tortoise[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}; - lfs_size_t tortoise_i = 1; - lfs_size_t tortoise_period = 1; + struct lfs_tortoise_t tortoise = { + .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}, + .i = 1, + .period = 1, + }; while (!lfs_pair_isnull(dir.tail)) { - // detect cycles with Brent's algorithm - if (lfs_pair_issync(dir.tail, tortoise)) { - LFS_WARN("Cycle detected in tail list"); - err = LFS_ERR_CORRUPT; + err = lfs_tortoise_detectcycles(&dir, &tortoise); + if (err < 0) { 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 lfs_stag_t tag = lfs_dir_fetchmatch(lfs, &dir, dir.tail, @@ -4633,22 +4650,17 @@ int lfs_fs_traverse_(lfs_t *lfs, } #endif - lfs_block_t tortoise[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}; - lfs_size_t tortoise_i = 1; - lfs_size_t tortoise_period = 1; + struct lfs_tortoise_t tortoise = { + .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS_ERR_OK; while (!lfs_pair_isnull(dir.tail)) { - // detect cycles with Brent's algorithm - if (lfs_pair_issync(dir.tail, tortoise)) { - LFS_WARN("Cycle detected in tail list"); + err = lfs_tortoise_detectcycles(&dir, &tortoise); + if (err < 0) { return LFS_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++) { int err = cb(data, dir.tail[i]); @@ -4727,22 +4739,17 @@ static int lfs_fs_pred(lfs_t *lfs, // iterate over all directory directory entries pdir->tail[0] = 0; pdir->tail[1] = 1; - lfs_block_t tortoise[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}; - lfs_size_t tortoise_i = 1; - lfs_size_t tortoise_period = 1; + struct lfs_tortoise_t tortoise = { + .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS_ERR_OK; while (!lfs_pair_isnull(pdir->tail)) { - // detect cycles with Brent's algorithm - if (lfs_pair_issync(pdir->tail, tortoise)) { - LFS_WARN("Cycle detected in tail list"); + err = lfs_tortoise_detectcycles(pdir, &tortoise); + if (err < 0) { return LFS_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 (lfs_pair_cmp(pdir->tail, pair) == 0) { return 0; @@ -4792,22 +4799,17 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2], // use fetchmatch with callback to find pairs parent->tail[0] = 0; parent->tail[1] = 1; - lfs_block_t tortoise[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}; - lfs_size_t tortoise_i = 1; - lfs_size_t tortoise_period = 1; + struct lfs_tortoise_t tortoise = { + .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS_ERR_OK; while (!lfs_pair_isnull(parent->tail)) { - // detect cycles with Brent's algorithm - if (lfs_pair_issync(parent->tail, tortoise)) { - LFS_WARN("Cycle detected in tail list"); - return LFS_ERR_CORRUPT; - } - if (tortoise_i == tortoise_period) { - tortoise[0] = parent->tail[0]; - tortoise[1] = parent->tail[1]; - tortoise_i = 0; - tortoise_period *= 2; + err = lfs_tortoise_detectcycles(parent, &tortoise); + if (err < 0) { + return err; } - tortoise_i += 1; lfs_stag_t tag = lfs_dir_fetchmatch(lfs, parent, parent->tail, LFS_MKTAG(0x7ff, 0, 0x3ff), From 1f82c0f27f8098f229106a95b09e6a97d0a24944 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 3 Oct 2024 16:34:45 -0500 Subject: [PATCH 12/28] Added some metadata_max testing - Added METADATA_MAX to test_runner. - Added METADATA_MAX to bench_runner. - Added a simple metadata_max test to test_superblocks, for lack of better location. There have been several issues floating around related to metadata_max and LFS_ERR_NOSPC which makes me think there's a bug in our metadata_max logic. metadata_max was a quick patch and is relatively untested, so an undetected bug isn't too surprising. This commit adds at least some testing over metadata_max. Sure enough, the new test_superblocks_metadata_max test reveals a curious LFS_ERR_NAMETOOLONG error that shouldn't be there. More investigation needed. --- runners/bench_runner.c | 1 + runners/bench_runner.h | 17 ++++++++++------- runners/test_runner.c | 5 +++++ runners/test_runner.h | 19 +++++++++++-------- tests/test_superblocks.toml | 27 +++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 15 deletions(-) diff --git a/runners/bench_runner.c b/runners/bench_runner.c index 387889d1..d49f9761 100644 --- a/runners/bench_runner.c +++ b/runners/bench_runner.c @@ -1322,6 +1322,7 @@ void perm_run( .cache_size = CACHE_SIZE, .lookahead_size = LOOKAHEAD_SIZE, .compact_thresh = COMPACT_THRESH, + .metadata_max = METADATA_MAX, .inline_max = INLINE_MAX, }; diff --git a/runners/bench_runner.h b/runners/bench_runner.h index 174733c1..848b5e8f 100644 --- a/runners/bench_runner.h +++ b/runners/bench_runner.h @@ -96,12 +96,13 @@ intmax_t bench_define(size_t define); #define CACHE_SIZE_i 6 #define LOOKAHEAD_SIZE_i 7 #define COMPACT_THRESH_i 8 -#define INLINE_MAX_i 9 -#define BLOCK_CYCLES_i 10 -#define ERASE_VALUE_i 11 -#define ERASE_CYCLES_i 12 -#define BADBLOCK_BEHAVIOR_i 13 -#define POWERLOSS_BEHAVIOR_i 14 +#define METADATA_MAX_i 9 +#define INLINE_MAX_i 10 +#define BLOCK_CYCLES_i 11 +#define ERASE_VALUE_i 12 +#define ERASE_CYCLES_i 13 +#define BADBLOCK_BEHAVIOR_i 14 +#define POWERLOSS_BEHAVIOR_i 15 #define READ_SIZE bench_define(READ_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 LOOKAHEAD_SIZE bench_define(LOOKAHEAD_SIZE_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 BLOCK_CYCLES bench_define(BLOCK_CYCLES_i) #define ERASE_VALUE bench_define(ERASE_VALUE_i) @@ -129,6 +131,7 @@ intmax_t bench_define(size_t define); BENCH_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \ BENCH_DEF(LOOKAHEAD_SIZE, 16) \ BENCH_DEF(COMPACT_THRESH, 0) \ + BENCH_DEF(METADATA_MAX, 0) \ BENCH_DEF(INLINE_MAX, 0) \ BENCH_DEF(BLOCK_CYCLES, -1) \ BENCH_DEF(ERASE_VALUE, 0xff) \ @@ -137,7 +140,7 @@ intmax_t bench_define(size_t define); BENCH_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP) #define BENCH_GEOMETRY_DEFINE_COUNT 4 -#define BENCH_IMPLICIT_DEFINE_COUNT 15 +#define BENCH_IMPLICIT_DEFINE_COUNT 16 #endif diff --git a/runners/test_runner.c b/runners/test_runner.c index ff526730..37cd1e7d 100644 --- a/runners/test_runner.c +++ b/runners/test_runner.c @@ -1347,6 +1347,7 @@ static void run_powerloss_none( .cache_size = CACHE_SIZE, .lookahead_size = LOOKAHEAD_SIZE, .compact_thresh = COMPACT_THRESH, + .metadata_max = METADATA_MAX, .inline_max = INLINE_MAX, #ifdef LFS_MULTIVERSION .disk_version = DISK_VERSION, @@ -1425,6 +1426,7 @@ static void run_powerloss_linear( .cache_size = CACHE_SIZE, .lookahead_size = LOOKAHEAD_SIZE, .compact_thresh = COMPACT_THRESH, + .metadata_max = METADATA_MAX, .inline_max = INLINE_MAX, #ifdef LFS_MULTIVERSION .disk_version = DISK_VERSION, @@ -1520,6 +1522,7 @@ static void run_powerloss_log( .cache_size = CACHE_SIZE, .lookahead_size = LOOKAHEAD_SIZE, .compact_thresh = COMPACT_THRESH, + .metadata_max = METADATA_MAX, .inline_max = INLINE_MAX, #ifdef LFS_MULTIVERSION .disk_version = DISK_VERSION, @@ -1613,6 +1616,7 @@ static void run_powerloss_cycles( .cache_size = CACHE_SIZE, .lookahead_size = LOOKAHEAD_SIZE, .compact_thresh = COMPACT_THRESH, + .metadata_max = METADATA_MAX, .inline_max = INLINE_MAX, #ifdef LFS_MULTIVERSION .disk_version = DISK_VERSION, @@ -1804,6 +1808,7 @@ static void run_powerloss_exhaustive( .cache_size = CACHE_SIZE, .lookahead_size = LOOKAHEAD_SIZE, .compact_thresh = COMPACT_THRESH, + .metadata_max = METADATA_MAX, .inline_max = INLINE_MAX, #ifdef LFS_MULTIVERSION .disk_version = DISK_VERSION, diff --git a/runners/test_runner.h b/runners/test_runner.h index 0f0e594e..ecdf9c11 100644 --- a/runners/test_runner.h +++ b/runners/test_runner.h @@ -89,13 +89,14 @@ intmax_t test_define(size_t define); #define CACHE_SIZE_i 6 #define LOOKAHEAD_SIZE_i 7 #define COMPACT_THRESH_i 8 -#define INLINE_MAX_i 9 -#define BLOCK_CYCLES_i 10 -#define ERASE_VALUE_i 11 -#define ERASE_CYCLES_i 12 -#define BADBLOCK_BEHAVIOR_i 13 -#define POWERLOSS_BEHAVIOR_i 14 -#define DISK_VERSION_i 15 +#define METADATA_MAX_i 9 +#define INLINE_MAX_i 10 +#define BLOCK_CYCLES_i 11 +#define ERASE_VALUE_i 12 +#define ERASE_CYCLES_i 13 +#define BADBLOCK_BEHAVIOR_i 14 +#define POWERLOSS_BEHAVIOR_i 15 +#define DISK_VERSION_i 16 #define READ_SIZE TEST_DEFINE(READ_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 LOOKAHEAD_SIZE TEST_DEFINE(LOOKAHEAD_SIZE_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 BLOCK_CYCLES TEST_DEFINE(BLOCK_CYCLES_i) #define ERASE_VALUE TEST_DEFINE(ERASE_VALUE_i) @@ -124,6 +126,7 @@ intmax_t test_define(size_t define); TEST_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \ TEST_DEF(LOOKAHEAD_SIZE, 16) \ TEST_DEF(COMPACT_THRESH, 0) \ + TEST_DEF(METADATA_MAX, 0) \ TEST_DEF(INLINE_MAX, 0) \ TEST_DEF(BLOCK_CYCLES, -1) \ TEST_DEF(ERASE_VALUE, 0xff) \ @@ -133,7 +136,7 @@ intmax_t test_define(size_t define); TEST_DEF(DISK_VERSION, 0) #define TEST_GEOMETRY_DEFINE_COUNT 4 -#define TEST_IMPLICIT_DEFINE_COUNT 16 +#define TEST_IMPLICIT_DEFINE_COUNT 17 #endif diff --git a/tests/test_superblocks.toml b/tests/test_superblocks.toml index e93f02eb..5911c9b0 100644 --- a/tests/test_superblocks.toml +++ b/tests/test_superblocks.toml @@ -523,3 +523,30 @@ code = ''' assert(memcmp(buffer, "hello!", 6) == 0); lfs_unmount(&lfs) => 0; ''' + +# test that metadata_max does not cause problems for superblock compaction +[cases.test_superblocks_metadata_max] +defines.METADATA_MAX = [ + 'lfs_max(512, PROG_SIZE)', + 'lfs_max(BLOCK_SIZE/2, PROG_SIZE)', + 'BLOCK_SIZE' +] +defines.N = [10, 100, 1000] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + for (int i = 0; i < N; i++) { + lfs_file_t file; + char name[256]; + sprintf(name, "hello%03x", i); + lfs_file_open(&lfs, &file, name, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + struct lfs_info info; + lfs_stat(&lfs, name, &info) => 0; + assert(strcmp(info.name, name) == 0); + assert(info.type == LFS_TYPE_REG); + } + lfs_unmount(&lfs) => 0; +''' From 2d62d2f4c9f4743e090ce503fd5d4f9eb104da70 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 4 Oct 2024 13:19:40 -0500 Subject: [PATCH 13/28] Fixed metadata_max==prog_size commit->end calculation The inconsistency here between the use of block_size vs metadata_max was suspicious. Turns out there's a bug when metadata_max == prog_size. We correctly use metadata_max for the block_size/2 check, but we weren't using it for the block_size-40 check. The second check seems unnecessary after the first, but it protects against running out of space in a commit for commit-related metadata (checksums, tail pointers, etc) when we can't program half-blocks. Turns out this is also needed when limiting metadata_max to a single prog, otherwise we risk erroring with LFS_ERR_NOSPC early. Found by ajheck, dpkristensen, NLLK, and likely others. --- lfs.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lfs.c b/lfs.c index d35d5d6d..1f8c9c65 100644 --- a/lfs.c +++ b/lfs.c @@ -2128,13 +2128,14 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir, // And we cap at half a block to avoid degenerate cases with // nearly-full metadata blocks. // + lfs_size_t metadata_max = (lfs->cfg->metadata_max) + ? lfs->cfg->metadata_max + : lfs->cfg->block_size; if (end - split < 0xff && size <= lfs_min( - lfs->cfg->block_size - 40, + metadata_max - 40, lfs_alignup( - (lfs->cfg->metadata_max - ? lfs->cfg->metadata_max - : lfs->cfg->block_size)/2, + metadata_max/2, lfs->cfg->prog_size))) { break; } From ea431bd6aefd6f4f2a00b1b90bb15bcb0c9a411d Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 4 Oct 2024 13:29:03 -0500 Subject: [PATCH 14/28] Added some checks that metadata_max makes sense Like the read/prog/block_size checks, these are just asserts. If these invariants are broken the filesystem will break in surprising ways. --- lfs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lfs.c b/lfs.c index 1f8c9c65..40daf759 100644 --- a/lfs.c +++ b/lfs.c @@ -4210,6 +4210,15 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { LFS_ASSERT(lfs->cfg->compact_thresh == (lfs_size_t)-1 || lfs->cfg->compact_thresh <= lfs->cfg->block_size); + // check that metadata_max is a multiple of read_size and prog_size, + // and a factor of the block_size + LFS_ASSERT(!lfs->cfg->metadata_max + || lfs->cfg->metadata_max % lfs->cfg->read_size == 0); + LFS_ASSERT(!lfs->cfg->metadata_max + || lfs->cfg->metadata_max % lfs->cfg->prog_size == 0); + LFS_ASSERT(!lfs->cfg->metadata_max + || lfs->cfg->block_size % lfs->cfg->metadata_max == 0); + // setup read cache if (lfs->cfg->read_buffer) { lfs->rcache.buffer = lfs->cfg->read_buffer; From 1407db95569ea3b4132b7801a702aa8e86bf416b Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 1 Nov 2024 16:56:08 -0500 Subject: [PATCH 15/28] Added links to ramcrc32bd and ramrsbd These two small libraries provide examples of error-correction compatible with littlefs (or any filesystem really). It would be nice to eventually provide these as drop-in solutions, but right now it's not really possible without breaking changes to littlefs's block device API. In the meantime, ramcrc32bd and ramrsbd at least provide example implementations that can be adapted to users' own block devices. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 5a75df3b..a1dc7437 100644 --- a/README.md +++ b/README.md @@ -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 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 which already has block device drivers for most forms of embedded storage. 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 [mklittlefs]: https://github.com/earlephilhower/mklittlefs [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 [LittleFileSystem]: https://os.mbed.com/docs/mbed-os/latest/apis/littlefilesystem.html [SPIFFS]: https://github.com/pellepl/spiffs From 0de0389c6f83860826c5a3340d41256966f3ac08 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 20 Nov 2024 17:30:18 -0600 Subject: [PATCH 16/28] paths: Reworked test_paths to cover more corner cases This should be a superset of the previous test_paths test suite, while covering a couple more things (more APIs, more path synonyms, utf8, non-printable ascii, non-utf8, etc). Not yet tested are some corner cases with known bugs, mainly around trailing slashes. --- tests/test_paths.toml | 4354 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 4179 insertions(+), 175 deletions(-) diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 97a519ea..89fb89e9 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -1,237 +1,2207 @@ # simple path test -[cases.test_paths_normal] +[cases.test_paths_simple] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "tea") => 0; - lfs_mkdir(&lfs, "tea/hottea") => 0; - lfs_mkdir(&lfs, "tea/warmtea") => 0; - lfs_mkdir(&lfs, "tea/coldtea") => 0; + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfs_stat(&lfs, "tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "/tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - - lfs_mkdir(&lfs, "/milk") => 0; - lfs_stat(&lfs, "/milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfs_stat(&lfs, "milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "coffee/drip", + "espresso/espresso") => 0; + lfs_rename(&lfs, + "coffee/coldbrew", + "espresso/americano") => 0; + lfs_rename(&lfs, + "coffee/turkish", + "espresso/macchiato") => 0; + lfs_rename(&lfs, + "coffee/tubruk", + "espresso/latte") => 0; + lfs_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino") => 0; + lfs_rename(&lfs, + "coffee/thai", + "espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "coffee/drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "espresso/espresso") => 0; + lfs_remove(&lfs, "espresso/americano") => 0; + lfs_remove(&lfs, "espresso/macchiato") => 0; + lfs_remove(&lfs, "espresso/latte") => 0; + lfs_remove(&lfs, "espresso/cappuccino") => 0; + lfs_remove(&lfs, "espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# absolute path test +# +# littlefs does not provide cd, so these are the same as relative paths +[cases.test_paths_absolute] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/coffee/drip") => 0; + lfs_mkdir(&lfs, "/coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "/coffee/turkish") => 0; + lfs_mkdir(&lfs, "/coffee/tubruk") => 0; + lfs_mkdir(&lfs, "/coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "/coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "/coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "coffee/drip", + "/espresso/espresso") => 0; + lfs_rename(&lfs, + "coffee/coldbrew", + "/espresso/americano") => 0; + lfs_rename(&lfs, + "/coffee/turkish", + "espresso/macchiato") => 0; + lfs_rename(&lfs, + "/coffee/tubruk", + "espresso/latte") => 0; + lfs_rename(&lfs, + "/coffee/vietnamese", + "/espresso/cappuccino") => 0; + lfs_rename(&lfs, + "/coffee/thai", + "/espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "/coffee/drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/espresso/espresso") => 0; + lfs_remove(&lfs, "/espresso/americano") => 0; + lfs_remove(&lfs, "/espresso/macchiato") => 0; + lfs_remove(&lfs, "/espresso/latte") => 0; + lfs_remove(&lfs, "/espresso/cappuccino") => 0; + lfs_remove(&lfs, "/espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' # redundant slashes [cases.test_paths_redundant_slashes] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "tea") => 0; - lfs_mkdir(&lfs, "tea/hottea") => 0; - lfs_mkdir(&lfs, "tea/warmtea") => 0; - lfs_mkdir(&lfs, "tea/coldtea") => 0; + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/coffee/drip") => 0; + lfs_mkdir(&lfs, "//coffee//coldbrew") => 0; + lfs_mkdir(&lfs, "///coffee///turkish") => 0; + lfs_mkdir(&lfs, "////coffee////tubruk") => 0; + lfs_mkdir(&lfs, "/////coffee/////vietnamese") => 0; + lfs_mkdir(&lfs, "//////coffee//////thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfs_stat(&lfs, "/tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "//tea//hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "///tea///hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - - lfs_mkdir(&lfs, "////milk") => 0; - lfs_stat(&lfs, "////milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfs_stat(&lfs, "milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); + lfs_stat(&lfs, "//////coffee//////drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/////coffee/////coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "////coffee////turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "///coffee///tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "//coffee//vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "//coffee//coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "///coffee///turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "////coffee////tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/////coffee/////vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "//////coffee//////thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "//coffee//coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "///coffee///turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "////coffee////tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/////coffee/////vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "//////coffee//////thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "//////coffee//////drip", + "/espresso/espresso") => 0; + lfs_rename(&lfs, + "/////coffee/////coldbrew", + "//espresso//americano") => 0; + lfs_rename(&lfs, + "////coffee////turkish", + "///espresso///macchiato") => 0; + lfs_rename(&lfs, + "///coffee///tubruk", + "////espresso////latte") => 0; + lfs_rename(&lfs, + "//coffee//vietnamese", + "/////espresso/////cappuccino") => 0; + lfs_rename(&lfs, + "/coffee/thai", + "//////espresso//////mocha") => 0; + + // stat paths + lfs_stat(&lfs, "//////espresso//////espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/////espresso/////americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "////espresso////macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "///espresso///latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "//espresso//cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "//////coffee//////drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/////coffee/////coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "////coffee////turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "///coffee///tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "//coffee//vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/espresso/espresso") => 0; + lfs_remove(&lfs, "//espresso//americano") => 0; + lfs_remove(&lfs, "///espresso///macchiato") => 0; + lfs_remove(&lfs, "////espresso////latte") => 0; + lfs_remove(&lfs, "/////espresso/////cappuccino") => 0; + lfs_remove(&lfs, "//////espresso//////mocha") => 0; + + // stat paths + lfs_stat(&lfs, "//////espresso//////espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/////espresso/////americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "////espresso////macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "///espresso///latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "//espresso//cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' -# dot path test -[cases.test_paths_dot] +# TODO test trailing slashes + +# dot path tests +[cases.test_paths_dots] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "tea") => 0; - lfs_mkdir(&lfs, "tea/hottea") => 0; - lfs_mkdir(&lfs, "tea/warmtea") => 0; - lfs_mkdir(&lfs, "tea/coldtea") => 0; + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/coffee/drip") => 0; + lfs_mkdir(&lfs, "/./coffee/./coldbrew") => 0; + lfs_mkdir(&lfs, "/././coffee/././turkish") => 0; + lfs_mkdir(&lfs, "/./././coffee/./././tubruk") => 0; + lfs_mkdir(&lfs, "/././././coffee/././././vietnamese") => 0; + lfs_mkdir(&lfs, "/./././././coffee/./././././thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfs_stat(&lfs, "./tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "/./tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "/././tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "/./tea/./hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - - lfs_mkdir(&lfs, "/./milk") => 0; - lfs_stat(&lfs, "/./milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfs_stat(&lfs, "milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); + lfs_stat(&lfs, "/./././././coffee/./././././drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/././././coffee/././././coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/./././coffee/./././turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/././coffee/././tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/./coffee/./vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/./coffee/./coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/././coffee/././turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/./././coffee/./././tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/././././coffee/././././vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/./././././coffee/./././././thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/./coffee/./coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/././coffee/././turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/./././coffee/./././tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/././././coffee/././././vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/./././././coffee/./././././thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "/./././././coffee/./././././drip", + "/espresso/espresso") => 0; + lfs_rename(&lfs, + "/././././coffee/././././coldbrew", + "/./espresso/./americano") => 0; + lfs_rename(&lfs, + "/./././coffee/./././turkish", + "/././espresso/././macchiato") => 0; + lfs_rename(&lfs, + "/././coffee/././tubruk", + "/./././espresso/./././latte") => 0; + lfs_rename(&lfs, + "/./coffee/./vietnamese", + "/././././espresso/././././cappuccino") => 0; + lfs_rename(&lfs, + "/coffee/thai", + "/./././././espresso/./././././mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/./././././espresso/./././././espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/././././espresso/././././americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/./././espresso/./././macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/././espresso/././latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/./espresso/./cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "/./././././coffee/./././././drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/././././coffee/././././coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/./././coffee/./././turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/././coffee/././tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/./coffee/./vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/espresso/espresso") => 0; + lfs_remove(&lfs, "/./espresso/./americano") => 0; + lfs_remove(&lfs, "/././espresso/././macchiato") => 0; + lfs_remove(&lfs, "/./././espresso/./././latte") => 0; + lfs_remove(&lfs, "/././././espresso/././././cappuccino") => 0; + lfs_remove(&lfs, "/./././././espresso/./././././mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/./././././espresso/./././././espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/././././espresso/././././americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/./././espresso/./././macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/././espresso/././latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/./espresso/./cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' -# dot dot path test -[cases.test_paths_dot_dot] +# TODO test trailing dots + +# dot dot path tests +[cases.test_paths_dotdots] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "tea") => 0; - lfs_mkdir(&lfs, "tea/hottea") => 0; - lfs_mkdir(&lfs, "tea/warmtea") => 0; - lfs_mkdir(&lfs, "tea/coldtea") => 0; + + // create paths + lfs_mkdir(&lfs, "no") => 0; + lfs_mkdir(&lfs, "no/no") => 0; lfs_mkdir(&lfs, "coffee") => 0; - lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; - lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; - lfs_mkdir(&lfs, "coffee/coldcoffee") => 0; + lfs_mkdir(&lfs, "coffee/no") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/coffee/drip") => 0; + lfs_mkdir(&lfs, "/no/../coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "/coffee/no/../turkish") => 0; + lfs_mkdir(&lfs, "/no/no/../../coffee/tubruk") => 0; + lfs_mkdir(&lfs, "/no/no/../../coffee/no/../vietnamese") => 0; + lfs_mkdir(&lfs, "/no/no/../../no/no/../../coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + // stat paths struct lfs_info info; - lfs_stat(&lfs, "coffee/../tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "tea/coldtea/../hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "coffee/coldcoffee/../../tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "coffee/../coffee/../tea/hottea", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - - lfs_mkdir(&lfs, "coffee/../milk") => 0; - lfs_stat(&lfs, "coffee/../milk", &info) => 0; - strcmp(info.name, "milk") => 0; - lfs_stat(&lfs, "milk", &info) => 0; - strcmp(info.name, "milk") => 0; + lfs_stat(&lfs, "/no/no/../../no/no/../../coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/../../coffee/no/../coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/../../coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/no/../tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/../coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/../coffee/coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/no/../turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/no/../../coffee/tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/no/../../coffee/no/../vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/no/../../no/no/../../coffee/thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/../coffee/coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/no/../turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/no/../../coffee/tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/no/../../coffee/no/../vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/no/../../no/no/../../coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "/no/no/../../no/no/../../coffee/drip", + "/espresso/espresso") => 0; + lfs_rename(&lfs, + "/no/no/../../coffee/no/../coldbrew", + "/no/../espresso/americano") => 0; + lfs_rename(&lfs, + "/no/no/../../coffee/turkish", + "/espresso/no/../macchiato") => 0; + lfs_rename(&lfs, + "/coffee/no/../tubruk", + "/no/no/../../espresso/latte") => 0; + lfs_rename(&lfs, + "/no/../coffee/vietnamese", + "/no/no/../../espresso/no/../cappuccino") => 0; + lfs_rename(&lfs, + "/coffee/thai", + "/no/no/../../no/no/../../espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/no/no/../../no/no/../../espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/../../espresso/no/../americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/../../espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/no/../latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/../espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "/no/no/../../no/no/../../coffee/drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/../../coffee/no/../coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/../../coffee/turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/no/../tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/../coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/espresso/espresso") => 0; + lfs_remove(&lfs, "/no/../espresso/americano") => 0; + lfs_remove(&lfs, "/espresso/no/../macchiato") => 0; + lfs_remove(&lfs, "/no/no/../../espresso/latte") => 0; + lfs_remove(&lfs, "/no/no/../../espresso/no/../cappuccino") => 0; + lfs_remove(&lfs, "/no/no/../../no/no/../../espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/no/no/../../no/no/../../espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/../../espresso/no/../americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/../../espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/no/../latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/../espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' -# trailing dot path test -[cases.test_paths_trailing_dot] +# TODO test trailing dotdots + +# dot dot dot path tests +[cases.test_paths_dotdotdots] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "tea") => 0; - lfs_mkdir(&lfs, "tea/hottea") => 0; - lfs_mkdir(&lfs, "tea/warmtea") => 0; - lfs_mkdir(&lfs, "tea/coldtea") => 0; + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + lfs_mkdir(&lfs, "coffee/...") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/coffee/.../drip") => 0; + lfs_mkdir(&lfs, "/coffee/.../coldbrew") => 0; + lfs_mkdir(&lfs, "/coffee/.../turkish") => 0; + lfs_mkdir(&lfs, "/coffee/.../tubruk") => 0; + lfs_mkdir(&lfs, "/coffee/.../vietnamese") => 0; + lfs_mkdir(&lfs, "/coffee/.../thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfs_stat(&lfs, "tea/hottea/", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "tea/hottea/.", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "tea/hottea/./.", &info) => 0; - assert(strcmp(info.name, "hottea") == 0); - lfs_stat(&lfs, "tea/hottea/..", &info) => 0; - assert(strcmp(info.name, "tea") == 0); - lfs_stat(&lfs, "tea/hottea/../.", &info) => 0; - assert(strcmp(info.name, "tea") == 0); + lfs_stat(&lfs, "/coffee/.../drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/.../coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/.../turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/.../tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/.../vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/.../thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/.../drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/.../coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/.../turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/.../tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/.../vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/.../thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/.../drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/.../coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/.../turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/.../tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/.../vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/.../thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_mkdir(&lfs, "espresso/...") => 0; + lfs_rename(&lfs, + "/coffee/.../drip", + "/espresso/.../espresso") => 0; + lfs_rename(&lfs, + "/coffee/.../coldbrew", + "/espresso/.../americano") => 0; + lfs_rename(&lfs, + "/coffee/.../turkish", + "/espresso/.../macchiato") => 0; + lfs_rename(&lfs, + "/coffee/.../tubruk", + "/espresso/.../latte") => 0; + lfs_rename(&lfs, + "/coffee/.../vietnamese", + "/espresso/.../cappuccino") => 0; + lfs_rename(&lfs, + "/coffee/.../thai", + "/espresso/.../mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/espresso/.../espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/.../americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/.../macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/.../latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/.../cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/.../mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "coffee/.../drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/.../coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/.../turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/.../tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/.../vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/.../thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/espresso/.../espresso") => 0; + lfs_remove(&lfs, "/espresso/.../americano") => 0; + lfs_remove(&lfs, "/espresso/.../macchiato") => 0; + lfs_remove(&lfs, "/espresso/.../latte") => 0; + lfs_remove(&lfs, "/espresso/.../cappuccino") => 0; + lfs_remove(&lfs, "/espresso/.../mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/espresso/.../espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/.../americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/.../macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/.../latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/.../cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/.../mocha", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' # leading dot path test -[cases.test_paths_leading_dot] +[cases.test_paths_leading_dots] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, ".milk") => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/coffee/.drip") => 0; + lfs_mkdir(&lfs, "/coffee/..coldbrew") => 0; + lfs_mkdir(&lfs, "/coffee/...turkish") => 0; + lfs_mkdir(&lfs, "/coffee/....tubruk") => 0; + lfs_mkdir(&lfs, "/coffee/.....vietnamese") => 0; + lfs_mkdir(&lfs, "/coffee/......thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfs_stat(&lfs, ".milk", &info) => 0; - strcmp(info.name, ".milk") => 0; - lfs_stat(&lfs, "tea/.././.milk", &info) => 0; - strcmp(info.name, ".milk") => 0; + lfs_stat(&lfs, "/coffee/.drip", &info) => 0; + assert(strcmp(info.name, ".drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/..coldbrew", &info) => 0; + assert(strcmp(info.name, "..coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/...turkish", &info) => 0; + assert(strcmp(info.name, "...turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/....tubruk", &info) => 0; + assert(strcmp(info.name, "....tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/.....vietnamese", &info) => 0; + assert(strcmp(info.name, ".....vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/......thai", &info) => 0; + assert(strcmp(info.name, "......thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/.drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/..coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/...turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/....tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/.....vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/......thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/.drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/..coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/...turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/....tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/.....vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/......thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "/coffee/.drip", + "/espresso/.espresso") => 0; + lfs_rename(&lfs, + "/coffee/..coldbrew", + "/espresso/..americano") => 0; + lfs_rename(&lfs, + "/coffee/...turkish", + "/espresso/...macchiato") => 0; + lfs_rename(&lfs, + "/coffee/....tubruk", + "/espresso/....latte") => 0; + lfs_rename(&lfs, + "/coffee/.....vietnamese", + "/espresso/.....cappuccino") => 0; + lfs_rename(&lfs, + "/coffee/......thai", + "/espresso/......mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/espresso/.espresso", &info) => 0; + assert(strcmp(info.name, ".espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/..americano", &info) => 0; + assert(strcmp(info.name, "..americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/...macchiato", &info) => 0; + assert(strcmp(info.name, "...macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/....latte", &info) => 0; + assert(strcmp(info.name, "....latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/.....cappuccino", &info) => 0; + assert(strcmp(info.name, ".....cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/......mocha", &info) => 0; + assert(strcmp(info.name, "......mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "coffee/.drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/..coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/...turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/....tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/.....vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/......thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/espresso/.espresso") => 0; + lfs_remove(&lfs, "/espresso/..americano") => 0; + lfs_remove(&lfs, "/espresso/...macchiato") => 0; + lfs_remove(&lfs, "/espresso/....latte") => 0; + lfs_remove(&lfs, "/espresso/.....cappuccino") => 0; + lfs_remove(&lfs, "/espresso/......mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/espresso/.espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/..americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/...macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/....latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/.....cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/......mocha", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' # root dot dot path test -[cases.test_paths_root_dot_dot] +[cases.test_paths_root_dotdots] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "tea") => 0; - lfs_mkdir(&lfs, "tea/hottea") => 0; - lfs_mkdir(&lfs, "tea/warmtea") => 0; - lfs_mkdir(&lfs, "tea/coldtea") => 0; + + // create paths + lfs_mkdir(&lfs, "no") => 0; lfs_mkdir(&lfs, "coffee") => 0; - lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; - lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; - lfs_mkdir(&lfs, "coffee/coldcoffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/../coffee/drip") => 0; + lfs_mkdir(&lfs, "/../../coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "/../../../coffee/turkish") => 0; + lfs_mkdir(&lfs, "/no/../../coffee/tubruk") => 0; + lfs_mkdir(&lfs, "/no/../../../coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "/no/../../../../coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + // stat paths struct lfs_info info; - lfs_stat(&lfs, "coffee/../../../../../../tea/hottea", &info) => 0; - strcmp(info.name, "hottea") => 0; - - lfs_mkdir(&lfs, "coffee/../../../../../../milk") => 0; - lfs_stat(&lfs, "coffee/../../../../../../milk", &info) => 0; - strcmp(info.name, "milk") => 0; - lfs_stat(&lfs, "milk", &info) => 0; - strcmp(info.name, "milk") => 0; + lfs_stat(&lfs, "/no/../../../../coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/../../../coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/../../coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/../../../coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/../../coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/../coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/../coffee/drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/../../coffee/coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/../../../coffee/turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/../../coffee/tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/../../../coffee/vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/../../../../coffee/thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/../coffee/drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/../../coffee/coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/../../../coffee/turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/../coffee/tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/../../coffee/vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/../../../coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "/no/../../../../coffee/drip", + "/../espresso/espresso") => 0; + lfs_rename(&lfs, + "/no/../../../coffee/coldbrew", + "/../../espresso/americano") => 0; + lfs_rename(&lfs, + "/no/../../coffee/turkish", + "/../../../espresso/macchiato") => 0; + lfs_rename(&lfs, + "/../../../coffee/tubruk", + "/no/../../espresso/latte") => 0; + lfs_rename(&lfs, + "/../../coffee/vietnamese", + "/no/../../../espresso/cappuccino") => 0; + lfs_rename(&lfs, + "/../coffee/thai", + "/no/../../../../espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/no/../../../../espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/../../../espresso/americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/../../espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/../../../espresso/latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/../../espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/../espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "/no/../../../../coffee/drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/../../../coffee/coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/../../coffee/turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/../../../coffee/tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/../../coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/../coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/../espresso/espresso") => 0; + lfs_remove(&lfs, "/../../espresso/americano") => 0; + lfs_remove(&lfs, "/../../../espresso/macchiato") => 0; + lfs_remove(&lfs, "/no/../../espresso/latte") => 0; + lfs_remove(&lfs, "/no/../../../espresso/cappuccino") => 0; + lfs_remove(&lfs, "/no/../../../../espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/no/../../../../espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/../../../espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/../../espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/../../../espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/../../espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/../espresso/mocha", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' -# invalid path tests -[cases.test_paths_invalid] +# trailing noent tests +[cases.test_paths_noent] +defines.DIR = [false, true] code = ''' lfs_t lfs; - lfs_format(&lfs, cfg); + lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfs_stat(&lfs, "dirt", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "dirt/ground", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "dirt/ground/earth", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/_rip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/c_ldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tu_kish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tub_uk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/_vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/thai_", &info) => LFS_ERR_NOENT; - lfs_remove(&lfs, "dirt") => LFS_ERR_NOENT; - lfs_remove(&lfs, "dirt/ground") => LFS_ERR_NOENT; - lfs_remove(&lfs, "dirt/ground/earth") => LFS_ERR_NOENT; + // file open paths, only works on files! + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/_rip", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tu_kish", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tub_uk", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/_vietnamese", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/thai_", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/_rip") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/c_ldbrew") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/tu_kish") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/tub_uk") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/_vietnamese") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/thai_") => LFS_ERR_NOENT; + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "coffee/_rip", + "espresso/espresso") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk", + "espresso/latte") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_", + "espresso/mocha") => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "coffee/_rip") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/c_ldbrew") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/tu_kish") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/tub_uk") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/_vietnamese") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/thai_") => LFS_ERR_NOENT; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_unmount(&lfs) => 0; +''' + +# parent noent tests +[cases.test_paths_noent_parent] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "dirt/ground") => LFS_ERR_NOENT; + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "_offee/drip") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "co_fee/turkish") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "cof_ee/tubruk") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "_coffee/vietnamese") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee_/thai") => LFS_ERR_NOENT; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "_offee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "c_ffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee_/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + } + + // ok, actually create paths + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "_offee/drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "c_ffee/coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "co_fee/turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "cof_ee/tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "_coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee_/thai", &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! lfs_file_t file; - lfs_file_open(&lfs, &file, "dirt/ground", LFS_O_WRONLY | LFS_O_CREAT) - => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "dirt/ground/earth") => LFS_ERR_NOENT; - lfs_file_open(&lfs, &file, "dirt/ground/earth", LFS_O_WRONLY | LFS_O_CREAT) - => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "_offee/drip", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "c_ffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee_/thai", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "_offee/drip") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "co_fee/turkish") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "cof_ee/tubruk") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "_coffee/vietnamese") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee_/thai") => LFS_ERR_NOENT; + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + // bad source + lfs_rename(&lfs, + "_offee/drip", + "espresso/espresso") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "c_ffee/coldbrew", + "espresso/americano") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "co_fee/turkish", + "espresso/macchiato") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "cof_ee/tubruk", + "espresso/latte") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "_coffee/vietnamese", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee_/thai", + "espresso/mocha") => LFS_ERR_NOENT; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "_spresso/espresso") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/coldbrew", + "e_presso/americano") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/turkish", + "es_resso/macchiato") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tubruk", + "esp_esso/latte") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/vietnamese", + "_espresso/cappuccino") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai", + "espresso_/mocha") => LFS_ERR_NOENT; + + // bad source and bad destination + lfs_rename(&lfs, + "_offee/drip", + "_spresso/espresso") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "c_ffee/coldbrew", + "e_presso/americano") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "co_fee/turkish", + "es_resso/macchiato") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "cof_ee/tubruk", + "esp_esso/latte") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "_coffee/vietnamese", + "_espresso/cappuccino") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee_/thai", + "espresso_/mocha") => LFS_ERR_NOENT; + + // here's a weird one, what happens if our rename is also a noop? + lfs_rename(&lfs, + "_offee/drip", + "_offee/drip") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "c_ffee/coldbrew", + "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "co_fee/turkish", + "co_fee/turkish") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "cof_ee/tubruk", + "cof_ee/tubruk") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "_coffee/vietnamese", + "_coffee/vietnamese") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee_/thai", + "coffee_/thai") => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "_offee/drip") => LFS_ERR_NOENT; + lfs_remove(&lfs, "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfs_remove(&lfs, "co_fee/turkish") => LFS_ERR_NOENT; + lfs_remove(&lfs, "cof_ee/tubruk") => LFS_ERR_NOENT; + lfs_remove(&lfs, "_coffee/vietnamese") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee_/thai") => LFS_ERR_NOENT; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_unmount(&lfs) => 0; +''' + +# parent notdir tests +[cases.test_paths_notdir_parent] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_file_t file; + lfs_file_open(&lfs, &file, "drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + + if (DIR) { + lfs_mkdir(&lfs, "drip/coffee") => LFS_ERR_NOTDIR; + lfs_mkdir(&lfs, "coldbrew/coffee") => LFS_ERR_NOTDIR; + lfs_mkdir(&lfs, "turkish/coffee") => LFS_ERR_NOTDIR; + lfs_mkdir(&lfs, "tubruk/coffee") => LFS_ERR_NOTDIR; + lfs_mkdir(&lfs, "vietnamese/coffee") => LFS_ERR_NOTDIR; + lfs_mkdir(&lfs, "thai/coffee") => LFS_ERR_NOTDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "drip/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "turkish/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "thai/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "drip/coffee", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coldbrew/coffee", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "turkish/coffee", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "tubruk/coffee", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "vietnamese/coffee", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "thai/coffee", &info) => LFS_ERR_NOTDIR; + + // file open paths, only works on files! + lfs_file_open(&lfs, &file, "drip/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "turkish/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "thai/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + + // dir open paths, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "drip/coffee") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coldbrew/coffee") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "turkish/coffee") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "tubruk/coffee") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "vietnamese/coffee") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "thai/coffee") => LFS_ERR_NOTDIR; + + // make some normal paths so we have something to rename + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + // bad source + lfs_rename(&lfs, + "drip/coffee", + "espresso/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coldbrew/coffee", + "espresso/americano") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "turkish/coffee", + "espresso/macchiato") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "tubruk/coffee", + "espresso/latte") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "vietnamese/coffee", + "espresso/cappuccino") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "thai/coffee", + "espresso/mocha") => LFS_ERR_NOTDIR; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "drip/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew", + "coldbrew/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish", + "turkish/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk", + "tubruk/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese", + "vietnamese/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai", + "thai/espresso") => LFS_ERR_NOTDIR; + + // bad source and bad destination + lfs_rename(&lfs, + "drip/coffee", + "drip/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coldbrew/coffee", + "coldbrew/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "turkish/coffee", + "turkish/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "tubruk/coffee", + "tubruk/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "vietnamese/coffee", + "vietnamese/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "thai/coffee", + "thai/espresso") => LFS_ERR_NOTDIR; + + // here's a weird one, what happens if our rename is also a noop? + lfs_rename(&lfs, + "drip/coffee", + "drip/coffee") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coldbrew/coffee", + "coldbrew/coffee") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "turkish/coffee", + "turkish/coffee") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "tubruk/coffee", + "tubruk/coffee") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "vietnamese/coffee", + "vietnamese/coffee") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "thai/coffee", + "thai/coffee") => LFS_ERR_NOTDIR; + + // remove paths + lfs_stat(&lfs, "drip/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coldbrew/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "turkish/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "tubruk/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "vietnamese/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "thai/espresso", &info) => LFS_ERR_NOTDIR; + + // stat paths + lfs_stat(&lfs, "drip/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coldbrew/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "turkish/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "tubruk/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "vietnamese/espresso", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "thai/espresso", &info) => LFS_ERR_NOTDIR; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_unmount(&lfs) => 0; ''' # root operations [cases.test_paths_root] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; struct lfs_info info; + + // create root, this should error + if (DIR) { + lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + } + + // stat root lfs_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; + // file open root, only works on files! lfs_file_t file; - lfs_file_open(&lfs, &file, "/", LFS_O_WRONLY | LFS_O_CREAT) - => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + // dir open root, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/") => 0; + lfs_dir_close(&lfs, &dir) => 0; + + // rename root, this should error + lfs_rename(&lfs, "/", "coffee") => LFS_ERR_INVAL; + + lfs_mkdir(&lfs, "coffee") => 0; + lfs_rename(&lfs, "coffee", "/") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee") => 0; + + lfs_rename(&lfs, "/", "/") => LFS_ERR_INVAL; + + // stat root + lfs_stat(&lfs, "/", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + // remove root, this should error lfs_remove(&lfs, "/") => LFS_ERR_INVAL; + + // stat root + lfs_stat(&lfs, "/", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_unmount(&lfs) => 0; ''' -# root representations -[cases.test_paths_root_reprs] +# other root representations +[cases.test_paths_root_aliases] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; struct lfs_info info; + + // create root, this should error + if (DIR) { + lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, ".") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "..") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "./") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "/.") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "//") => LFS_ERR_EXIST; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, ".", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "./", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + } + + // stat root lfs_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); @@ -244,93 +2214,2127 @@ code = ''' lfs_stat(&lfs, "..", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "./", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "/.", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, "//", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); + + // file open root, only works on files! + lfs_file_t file; + lfs_file_open(&lfs, &file, "/", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, ".", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "./", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "//", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + // dir open root, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, ".") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "./") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/.") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "//") => 0; + lfs_dir_close(&lfs, &dir) => 0; + + // rename root, this should error + lfs_rename(&lfs, "/", "coffee") => LFS_ERR_INVAL; + lfs_rename(&lfs, "", "coffee") => LFS_ERR_INVAL; + lfs_rename(&lfs, ".", "coffee") => LFS_ERR_INVAL; + lfs_rename(&lfs, "..", "coffee") => LFS_ERR_INVAL; + lfs_rename(&lfs, "./", "coffee") => LFS_ERR_INVAL; + lfs_rename(&lfs, "/.", "coffee") => LFS_ERR_INVAL; + lfs_rename(&lfs, "//", "coffee") => LFS_ERR_INVAL; + + lfs_mkdir(&lfs, "coffee") => 0; + lfs_rename(&lfs, "coffee", "/") => LFS_ERR_INVAL; + lfs_rename(&lfs, "coffee", "") => LFS_ERR_INVAL; + lfs_rename(&lfs, "coffee", ".") => LFS_ERR_INVAL; + lfs_rename(&lfs, "coffee", "..") => LFS_ERR_INVAL; + lfs_rename(&lfs, "coffee", "./") => LFS_ERR_INVAL; + lfs_rename(&lfs, "coffee", "/.") => LFS_ERR_INVAL; + lfs_rename(&lfs, "coffee", "//") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee") => 0; + + lfs_rename(&lfs, "/", "/") => LFS_ERR_INVAL; + lfs_rename(&lfs, "", "") => LFS_ERR_INVAL; + lfs_rename(&lfs, ".", ".") => LFS_ERR_INVAL; + lfs_rename(&lfs, "..", "..") => LFS_ERR_INVAL; + lfs_rename(&lfs, "./", "./") => LFS_ERR_INVAL; + lfs_rename(&lfs, "/.", "/.") => LFS_ERR_INVAL; + lfs_rename(&lfs, "//", "//") => LFS_ERR_INVAL; + + // stat root + lfs_stat(&lfs, "/", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, ".", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, "./", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "/.", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "//", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + + // remove root, this should error + lfs_remove(&lfs, "/") => LFS_ERR_INVAL; + lfs_remove(&lfs, "") => LFS_ERR_INVAL; + lfs_remove(&lfs, ".") => LFS_ERR_INVAL; + lfs_remove(&lfs, "..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "./") => LFS_ERR_INVAL; + lfs_remove(&lfs, "/.") => LFS_ERR_INVAL; + lfs_remove(&lfs, "//") => LFS_ERR_INVAL; + + // stat root + lfs_stat(&lfs, "/", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, ".", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "./", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "/.", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "//", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_unmount(&lfs) => 0; ''' -# superblock conflict test -[cases.test_paths_superblock_conflict] +# superblock magic shouldn't appear as a file +[cases.test_paths_magic_noent] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; + + // stat littlefs, which shouldn't exist struct lfs_info info; lfs_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; + + // dir open littlefs, which shouldn't exist + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "littlefs") => LFS_ERR_NOENT; + + // rename littlefs, which shouldn't exist + lfs_rename(&lfs, "littlefs", "coffee") => LFS_ERR_NOENT; + + // remove littlefs, which shouldn't exist lfs_remove(&lfs, "littlefs") => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "littlefs") => 0; + // stat littlefs, which shouldn't exist + lfs_stat(&lfs, "coffee", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# superblock magic shouldn't conflict with files, that would be silly +[cases.test_paths_magic_conflict] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create littlefs + if (DIR) { + lfs_mkdir(&lfs, "littlefs") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat littlefs + struct lfs_info info; lfs_stat(&lfs, "littlefs", &info) => 0; assert(strcmp(info.name, "littlefs") == 0); - assert(info.type == LFS_TYPE_DIR); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open littlefs, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open littlefs, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "littlefs") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "littlefs") => LFS_ERR_NOTDIR; + } + + // rename littlefs + lfs_rename(&lfs, "littlefs", "coffee") => 0; + lfs_rename(&lfs, "coffee", "littlefs") => 0; + + // stat littlefs + lfs_stat(&lfs, "littlefs", &info) => 0; + assert(strcmp(info.name, "littlefs") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "coffee", &info) => LFS_ERR_NOENT; + + // remove littlefs lfs_remove(&lfs, "littlefs") => 0; + + // stat littlefs lfs_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' -# max path test -[cases.test_paths_max] +# test name too long +[cases.test_paths_nametoolong] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "coffee") => 0; - lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; - lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; - lfs_mkdir(&lfs, "coffee/coldcoffee") => 0; + char a_name[512]; + memset(a_name, 'a', LFS_NAME_MAX+1); + a_name[LFS_NAME_MAX+1] = '\0'; + + // create names that are too long, should error char path[1024]; - memset(path, 'w', LFS_NAME_MAX+1); - path[LFS_NAME_MAX+1] = '\0'; - lfs_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + sprintf(path, "coffee/%s", a_name); + lfs_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; + } else { + lfs_file_t file; + sprintf(path, "coffee/%s", a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NAMETOOLONG; + } + + // stat paths + struct lfs_info info; + sprintf(path, "coffee/%s", a_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! lfs_file_t file; - lfs_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) - => LFS_ERR_NAMETOOLONG; - - memcpy(path, "coffee/", strlen("coffee/")); - memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX+1); - path[strlen("coffee/")+LFS_NAME_MAX+1] = '\0'; - lfs_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; - lfs_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT) - => LFS_ERR_NAMETOOLONG; + sprintf(path, "coffee/%s", a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfs_dir_t dir; + sprintf(path, "coffee/%s", a_name); + lfs_dir_open(&lfs, &dir, path) => LFS_ERR_NOENT; + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + sprintf(path, "coffee/%s", a_name); + lfs_rename(&lfs, path, "espresso/espresso") => LFS_ERR_NOENT; + + // renaming with too long a destination is tricky! + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + sprintf(path, "espresso/%s", a_name); + lfs_rename(&lfs, "coffee/drip", path) => LFS_ERR_NAMETOOLONG; + + // stat paths + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + sprintf(path, "espresso/%s", a_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + // remove paths + sprintf(path, "espresso/%s", a_name); + lfs_remove(&lfs, path) => LFS_ERR_NOENT; + + // stat paths + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + sprintf(path, "espresso/%s", a_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' -# really big path test -[cases.test_paths_really_big] +# test name really long but not too long +[cases.test_paths_namejustlongenough] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfs_format(&lfs, cfg) => 0; lfs_mount(&lfs, cfg) => 0; - lfs_mkdir(&lfs, "coffee") => 0; - lfs_mkdir(&lfs, "coffee/hotcoffee") => 0; - lfs_mkdir(&lfs, "coffee/warmcoffee") => 0; - lfs_mkdir(&lfs, "coffee/coldcoffee") => 0; + char a_name[512]; + memset(a_name, 'a', LFS_NAME_MAX); + a_name[LFS_NAME_MAX] = '\0'; + char b_name[512]; + memset(b_name, 'b', LFS_NAME_MAX); + b_name[LFS_NAME_MAX] = '\0'; + char c_name[512]; + memset(c_name, 'c', LFS_NAME_MAX); + c_name[LFS_NAME_MAX] = '\0'; + char d_name[512]; + memset(d_name, 'd', LFS_NAME_MAX); + d_name[LFS_NAME_MAX] = '\0'; + char e_name[512]; + memset(e_name, 'e', LFS_NAME_MAX); + e_name[LFS_NAME_MAX] = '\0'; + char f_name[512]; + memset(f_name, 'f', LFS_NAME_MAX); + f_name[LFS_NAME_MAX] = '\0'; + char g_name[512]; + memset(g_name, 'g', LFS_NAME_MAX); + g_name[LFS_NAME_MAX] = '\0'; + char h_name[512]; + memset(h_name, 'h', LFS_NAME_MAX); + h_name[LFS_NAME_MAX] = '\0'; + char i_name[512]; + memset(i_name, 'i', LFS_NAME_MAX); + i_name[LFS_NAME_MAX] = '\0'; + char j_name[512]; + memset(j_name, 'j', LFS_NAME_MAX); + j_name[LFS_NAME_MAX] = '\0'; + char k_name[512]; + memset(k_name, 'k', LFS_NAME_MAX); + k_name[LFS_NAME_MAX] = '\0'; + char l_name[512]; + memset(l_name, 'l', LFS_NAME_MAX); + l_name[LFS_NAME_MAX] = '\0'; + + // create names that aren't too long + lfs_mkdir(&lfs, c_name) => 0; char path[1024]; - memset(path, 'w', LFS_NAME_MAX); - path[LFS_NAME_MAX] = '\0'; - lfs_mkdir(&lfs, path) => 0; + if (DIR) { + sprintf(path, "%s/%s", c_name, a_name); + lfs_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfs_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfs_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfs_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfs_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfs_mkdir(&lfs, path) => 0; + } else { + lfs_file_t file; + sprintf(path, "%s/%s", c_name, a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + sprintf(path, "%s/%s", c_name, a_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, a_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, b_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, b_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, c_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, c_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, d_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, d_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, e_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, e_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, f_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, f_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + sprintf(path, "%s/%s", c_name, a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, b_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, c_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, d_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, e_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, f_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + sprintf(path, "%s/%s", c_name, a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfs_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + sprintf(path, "%s/%s", c_name, a_name); + lfs_dir_open(&lfs, &dir, path) => 0; + lfs_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfs_dir_open(&lfs, &dir, path) => 0; + lfs_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfs_dir_open(&lfs, &dir, path) => 0; + lfs_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfs_dir_open(&lfs, &dir, path) => 0; + lfs_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfs_dir_open(&lfs, &dir, path) => 0; + lfs_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfs_dir_open(&lfs, &dir, path) => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + sprintf(path, "%s/%s", c_name, a_name); + lfs_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, b_name); + lfs_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, c_name); + lfs_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, d_name); + lfs_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, e_name); + lfs_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, f_name); + lfs_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, e_name) => 0; + char path_[1024]; + sprintf(path, "%s/%s", c_name, a_name); + sprintf(path_, "%s/%s", e_name, g_name); + lfs_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, b_name); + sprintf(path_, "%s/%s", e_name, h_name); + lfs_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, c_name); + sprintf(path_, "%s/%s", e_name, i_name); + lfs_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, d_name); + sprintf(path_, "%s/%s", e_name, j_name); + lfs_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, e_name); + sprintf(path_, "%s/%s", e_name, k_name); + lfs_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, f_name); + sprintf(path_, "%s/%s", e_name, l_name); + lfs_rename(&lfs, path, path_) => 0; + + // stat paths + sprintf(path, "%s/%s", e_name, g_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, g_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, h_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, h_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, i_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, i_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, j_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, j_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, k_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, k_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, l_name); + lfs_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, l_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + sprintf(path, "%s/%s", c_name, a_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, b_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, c_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, d_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, e_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, f_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + // remove paths + sprintf(path, "%s/%s", e_name, g_name); lfs_remove(&lfs, path) => 0; - lfs_file_t file; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", e_name, h_name); lfs_remove(&lfs, path) => 0; - - memcpy(path, "coffee/", strlen("coffee/")); - memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX); - path[strlen("coffee/")+LFS_NAME_MAX] = '\0'; - lfs_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, i_name); lfs_remove(&lfs, path) => 0; - lfs_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", e_name, j_name); lfs_remove(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, k_name); + lfs_remove(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, l_name); + lfs_remove(&lfs, path) => 0; + + // stat paths + sprintf(path, "%s/%s", e_name, g_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, h_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, i_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, j_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, k_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, l_name); + lfs_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# a quick utf8 test, though utf8 is easy to support +[cases.test_paths_utf8] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/dripcoffee") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/türkkahvesi") => 0; + lfs_mkdir(&lfs, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") => 0; + lfs_mkdir(&lfs, "coffee/càphêđá") => 0; + lfs_mkdir(&lfs, "coffee/โอเลี้ยง") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "coffee/dripcoffee", &info) => 0; + assert(strcmp(info.name, "dripcoffee") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/türkkahvesi", &info) => 0; + assert(strcmp(info.name, "türkkahvesi") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", &info) => 0; + assert(strcmp(info.name, "ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/càphêđá", &info) => 0; + assert(strcmp(info.name, "càphêđá") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/โอเลี้ยง", &info) => 0; + assert(strcmp(info.name, "โอเลี้ยง") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/dripcoffee") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/türkkahvesi") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/càphêđá") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/โอเลี้ยง") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/dripcoffee") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/türkkahvesi") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/càphêđá") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/โอเลี้ยง") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "caffè") => 0; + lfs_rename(&lfs, + "coffee/dripcoffee", + "caffè/espresso") => 0; + lfs_rename(&lfs, + "coffee/coldbrew", + "caffè/americano") => 0; + lfs_rename(&lfs, + "coffee/türkkahvesi", + "caffè/macchiato") => 0; + lfs_rename(&lfs, + "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + "caffè/latte") => 0; + lfs_rename(&lfs, + "coffee/càphêđá", + "caffè/cappuccino") => 0; + lfs_rename(&lfs, + "coffee/โอเลี้ยง", + "caffè/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "caffè/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "caffè/americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "caffè/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "caffè/latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "caffè/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "caffè/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "coffee/dripcoffee", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/türkkahvesi", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/càphêđá", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/โอเลี้ยง", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "caffè/espresso") => 0; + lfs_remove(&lfs, "caffè/americano") => 0; + lfs_remove(&lfs, "caffè/macchiato") => 0; + lfs_remove(&lfs, "caffè/latte") => 0; + lfs_remove(&lfs, "caffè/cappuccino") => 0; + lfs_remove(&lfs, "caffè/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "caffè/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "caffè/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "caffè/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "caffè/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "caffè/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "caffè/mocha", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# more utf8 tests +[cases.test_paths_utf8_ipa] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "ˈkɔ.fi") => 0; + if (DIR) { + lfs_mkdir(&lfs, "ˈkɔ.fi/dɹɪpˈkɔ.fi") => 0; + lfs_mkdir(&lfs, "ˈkɔ.fi/koʊldbɹuː") => 0; + lfs_mkdir(&lfs, "ˈkɔ.fi/tyɾckɑhvɛˈsi") => 0; + lfs_mkdir(&lfs, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚") => 0; + lfs_mkdir(&lfs, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥") => 0; + lfs_mkdir(&lfs, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "ˈkɔ.fi/dɹɪpˈkɔ.fi", &info) => 0; + assert(strcmp(info.name, "dɹɪpˈkɔ.fi") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "ˈkɔ.fi/koʊldbɹuː", &info) => 0; + assert(strcmp(info.name, "koʊldbɹuː") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "ˈkɔ.fi/tyɾckɑhvɛˈsi", &info) => 0; + assert(strcmp(info.name, "tyɾckɑhvɛˈsi") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", &info) => 0; + assert(strcmp(info.name, "ˈko.piˈt̪up̚.rʊk̚") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", &info) => 0; + assert(strcmp(info.name, "kaː˨˩fe˧˧ɗaː˧˥") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", &info) => 0; + assert(strcmp(info.name, "ʔoː˧.lia̯ŋ˦˥") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/dɹɪpˈkɔ.fi") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/koʊldbɹuː") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/tyɾckɑhvɛˈsi") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/dɹɪpˈkɔ.fi") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/koʊldbɹuː") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/tyɾckɑhvɛˈsi") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "kafˈfɛ") => 0; + lfs_rename(&lfs, + "ˈkɔ.fi/dɹɪpˈkɔ.fi", + "kafˈfɛ/eˈsprɛsso") => 0; + lfs_rename(&lfs, + "ˈkɔ.fi/koʊldbɹuː", + "kafˈfɛ/ameriˈkano") => 0; + lfs_rename(&lfs, + "ˈkɔ.fi/tyɾckɑhvɛˈsi", + "kafˈfɛ/makˈkjato") => 0; + lfs_rename(&lfs, + "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + "kafˈfɛ/ˈlat.te") => 0; + lfs_rename(&lfs, + "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + "kafˈfɛ/kapputˈt͡ʃino") => 0; + lfs_rename(&lfs, + "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + "kafˈfɛ/ˈmoʊkə") => 0; + + // stat paths + lfs_stat(&lfs, "kafˈfɛ/eˈsprɛsso", &info) => 0; + assert(strcmp(info.name, "eˈsprɛsso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "kafˈfɛ/ameriˈkano", &info) => 0; + assert(strcmp(info.name, "ameriˈkano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "kafˈfɛ/makˈkjato", &info) => 0; + assert(strcmp(info.name, "makˈkjato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "kafˈfɛ/ˈlat.te", &info) => 0; + assert(strcmp(info.name, "ˈlat.te") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "kafˈfɛ/kapputˈt͡ʃino", &info) => 0; + assert(strcmp(info.name, "kapputˈt͡ʃino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "kafˈfɛ/ˈmoʊkə", &info) => 0; + assert(strcmp(info.name, "ˈmoʊkə") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "ˈkɔ.fi/dɹɪpˈkɔ.fi", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "ˈkɔ.fi/koʊldbɹuː", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "ˈkɔ.fi/tyɾckɑhvɛˈsi", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "kafˈfɛ/eˈsprɛsso") => 0; + lfs_remove(&lfs, "kafˈfɛ/ameriˈkano") => 0; + lfs_remove(&lfs, "kafˈfɛ/makˈkjato") => 0; + lfs_remove(&lfs, "kafˈfɛ/ˈlat.te") => 0; + lfs_remove(&lfs, "kafˈfɛ/kapputˈt͡ʃino") => 0; + lfs_remove(&lfs, "kafˈfɛ/ˈmoʊkə") => 0; + + // stat paths + lfs_stat(&lfs, "kafˈfɛ/eˈsprɛsso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "kafˈfɛ/ameriˈkano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "kafˈfɛ/makˈkjato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "kafˈfɛ/ˈlat.te", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "kafˈfɛ/kapputˈt͡ʃino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "kafˈfɛ/ˈmoʊkə", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# test spaces have no problems +[cases.test_paths_spaces] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "c o f f e e") => 0; + if (DIR) { + lfs_mkdir(&lfs, "c o f f e e/d r i p") => 0; + lfs_mkdir(&lfs, "c o f f e e/c o l d b r e w") => 0; + lfs_mkdir(&lfs, "c o f f e e/t u r k i s h") => 0; + lfs_mkdir(&lfs, "c o f f e e/t u b r u k") => 0; + lfs_mkdir(&lfs, "c o f f e e/v i e t n a m e s e") => 0; + lfs_mkdir(&lfs, "c o f f e e/t h a i") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "c o f f e e/d r i p", &info) => 0; + assert(strcmp(info.name, "d r i p") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "c o f f e e/c o l d b r e w", &info) => 0; + assert(strcmp(info.name, "c o l d b r e w") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "c o f f e e/t u r k i s h", &info) => 0; + assert(strcmp(info.name, "t u r k i s h") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "c o f f e e/t u b r u k", &info) => 0; + assert(strcmp(info.name, "t u b r u k") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "c o f f e e/v i e t n a m e s e", &info) => 0; + assert(strcmp(info.name, "v i e t n a m e s e") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "c o f f e e/t h a i", &info) => 0; + assert(strcmp(info.name, "t h a i") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "c o f f e e/d r i p") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "c o f f e e/c o l d b r e w") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "c o f f e e/t u r k i s h") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "c o f f e e/t u b r u k") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "c o f f e e/v i e t n a m e s e") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "c o f f e e/t h a i") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "c o f f e e/d r i p") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "c o f f e e/c o l d b r e w") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "c o f f e e/t u r k i s h") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "c o f f e e/t u b r u k") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "c o f f e e/v i e t n a m e s e") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "c o f f e e/t h a i") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "e s p r e s s o") => 0; + lfs_rename(&lfs, + "c o f f e e/d r i p", + "e s p r e s s o/e s p r e s s o") => 0; + lfs_rename(&lfs, + "c o f f e e/c o l d b r e w", + "e s p r e s s o/a m e r i c a n o") => 0; + lfs_rename(&lfs, + "c o f f e e/t u r k i s h", + "e s p r e s s o/m a c c h i a t o") => 0; + lfs_rename(&lfs, + "c o f f e e/t u b r u k", + "e s p r e s s o/l a t t e") => 0; + lfs_rename(&lfs, + "c o f f e e/v i e t n a m e s e", + "e s p r e s s o/c a p p u c c i n o") => 0; + lfs_rename(&lfs, + "c o f f e e/t h a i", + "e s p r e s s o/m o c h a") => 0; + + // stat paths + lfs_stat(&lfs, "e s p r e s s o/e s p r e s s o", &info) => 0; + assert(strcmp(info.name, "e s p r e s s o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "e s p r e s s o/a m e r i c a n o", &info) => 0; + assert(strcmp(info.name, "a m e r i c a n o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "e s p r e s s o/m a c c h i a t o", &info) => 0; + assert(strcmp(info.name, "m a c c h i a t o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "e s p r e s s o/l a t t e", &info) => 0; + assert(strcmp(info.name, "l a t t e") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "e s p r e s s o/c a p p u c c i n o", &info) => 0; + assert(strcmp(info.name, "c a p p u c c i n o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "e s p r e s s o/m o c h a", &info) => 0; + assert(strcmp(info.name, "m o c h a") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "c o f f e e/d r i p", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "c o f f e e/c o l d b r e w", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "c o f f e e/t u r k i s h", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "c o f f e e/t u b r u k", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "c o f f e e/v i e t n a m e s e", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "c o f f e e/t h a i", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "e s p r e s s o/e s p r e s s o") => 0; + lfs_remove(&lfs, "e s p r e s s o/a m e r i c a n o") => 0; + lfs_remove(&lfs, "e s p r e s s o/m a c c h i a t o") => 0; + lfs_remove(&lfs, "e s p r e s s o/l a t t e") => 0; + lfs_remove(&lfs, "e s p r e s s o/c a p p u c c i n o") => 0; + lfs_remove(&lfs, "e s p r e s s o/m o c h a") => 0; + + // stat paths + lfs_stat(&lfs, "e s p r e s s o/e s p r e s s o", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "e s p r e s s o/a m e r i c a n o", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "e s p r e s s o/m a c c h i a t o", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "e s p r e s s o/l a t t e", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "e s p r e s s o/c a p p u c c i n o", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "e s p r e s s o/m o c h a", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# test with only spaces +# +# please don't do this +[cases.test_paths_oopsallspaces] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, " ") => 0; + if (DIR) { + lfs_mkdir(&lfs, " / ") => 0; + lfs_mkdir(&lfs, " / ") => 0; + lfs_mkdir(&lfs, " / ") => 0; + lfs_mkdir(&lfs, " / ") => 0; + lfs_mkdir(&lfs, " / ") => 0; + lfs_mkdir(&lfs, " / ") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, " / ") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, " / ") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, " / ") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, " / ") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, " / ") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, " / ") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, " ") => 0; + lfs_rename(&lfs, + " / ", + " / ") => 0; + lfs_rename(&lfs, + " / ", + " / ") => 0; + lfs_rename(&lfs, + " / ", + " / ") => 0; + lfs_rename(&lfs, + " / ", + " / ") => 0; + lfs_rename(&lfs, + " / ", + " / ") => 0; + lfs_rename(&lfs, + " / ", + " / ") => 0; + + // stat paths + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, " / ") => 0; + lfs_remove(&lfs, " / ") => 0; + lfs_remove(&lfs, " / ") => 0; + lfs_remove(&lfs, " / ") => 0; + lfs_remove(&lfs, " / ") => 0; + lfs_remove(&lfs, " / ") => 0; + + // stat paths + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# test with only ascii control characters +# +# littlefs only cares about "./" and NULL +[cases.test_paths_nonprintable] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "\x0c") => 0; + if (DIR) { + lfs_mkdir(&lfs, "\x0c/\x01") => 0; + lfs_mkdir(&lfs, "\x0c/\x02") => 0; + lfs_mkdir(&lfs, "\x0c/\x03") => 0; + lfs_mkdir(&lfs, "\x0c/\x04") => 0; + lfs_mkdir(&lfs, "\x0c/\x05") => 0; + lfs_mkdir(&lfs, "\x0c/\x06") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "\x0c/\x01", &info) => 0; + assert(strcmp(info.name, "\x01") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0c/\x02", &info) => 0; + assert(strcmp(info.name, "\x02") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0c/\x03", &info) => 0; + assert(strcmp(info.name, "\x03") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0c/\x04", &info) => 0; + assert(strcmp(info.name, "\x04") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0c/\x05", &info) => 0; + assert(strcmp(info.name, "\x05") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0c/\x06", &info) => 0; + assert(strcmp(info.name, "\x06") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\x0c/\x01") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x0c/\x02") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x0c/\x03") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x0c/\x04") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x0c/\x05") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x0c/\x06") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\x0c/\x01") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x0c/\x02") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x0c/\x03") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x0c/\x04") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x0c/\x05") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x0c/\x06") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "\x0e") => 0; + lfs_rename(&lfs, + "\x0c/\x01", + "\x0e/\x1a") => 0; + lfs_rename(&lfs, + "\x0c/\x02", + "\x0e/\x1b") => 0; + lfs_rename(&lfs, + "\x0c/\x03", + "\x0e/\x1c") => 0; + lfs_rename(&lfs, + "\x0c/\x04", + "\x0e/\x1d") => 0; + lfs_rename(&lfs, + "\x0c/\x05", + "\x0e/\x1e") => 0; + lfs_rename(&lfs, + "\x0c/\x06", + "\x0e/\x1f") => 0; + + // stat paths + lfs_stat(&lfs, "\x0e/\x1a", &info) => 0; + assert(strcmp(info.name, "\x1a") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0e/\x1b", &info) => 0; + assert(strcmp(info.name, "\x1b") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0e/\x1c", &info) => 0; + assert(strcmp(info.name, "\x1c") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0e/\x1d", &info) => 0; + assert(strcmp(info.name, "\x1d") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0e/\x1e", &info) => 0; + assert(strcmp(info.name, "\x1e") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x0e/\x1f", &info) => 0; + assert(strcmp(info.name, "\x1f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "\x0c/\x01", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0c/\x02", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0c/\x03", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0c/\x04", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0c/\x05", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0c/\x06", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "\x0e/\x1a") => 0; + lfs_remove(&lfs, "\x0e/\x1b") => 0; + lfs_remove(&lfs, "\x0e/\x1c") => 0; + lfs_remove(&lfs, "\x0e/\x1d") => 0; + lfs_remove(&lfs, "\x0e/\x1e") => 0; + lfs_remove(&lfs, "\x0e/\x1f") => 0; + + // stat paths + lfs_stat(&lfs, "\x0e/\x1a", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0e/\x1b", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0e/\x1c", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0e/\x1d", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0e/\x1e", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x0e/\x1f", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# test with only ascii DELs +# +# I don't know why you'd do this +[cases.test_paths_oopsalldels] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "\x7f") => 0; + if (DIR) { + lfs_mkdir(&lfs, "\x7f/\x7f") => 0; + lfs_mkdir(&lfs, "\x7f/\x7f\x7f") => 0; + lfs_mkdir(&lfs, "\x7f/\x7f\x7f\x7f") => 0; + lfs_mkdir(&lfs, "\x7f/\x7f\x7f\x7f\x7f") => 0; + lfs_mkdir(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_mkdir(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "\x7f/\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f/\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "\x7f\x7f") => 0; + lfs_rename(&lfs, + "\x7f/\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_rename(&lfs, + "\x7f/\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_rename(&lfs, + "\x7f/\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_rename(&lfs, + "\x7f/\x7f\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_rename(&lfs, + "\x7f/\x7f\x7f\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_rename(&lfs, + "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + + // stat paths + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "\x7f/\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f/\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfs_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + + // stat paths + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + +# test with invalid utf8 sequences +# +# Don't do this! These filenames are not utf8 and will probably break +# external tools. +# +[cases.test_paths_nonutf8] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "\xc0") => 0; + if (DIR) { + lfs_mkdir(&lfs, "\xc0/\xa0") => 0; + lfs_mkdir(&lfs, "\xc0/\xb0") => 0; + lfs_mkdir(&lfs, "\xc0/\xc0") => 0; + lfs_mkdir(&lfs, "\xc0/\xd0") => 0; + lfs_mkdir(&lfs, "\xc0/\xe0") => 0; + lfs_mkdir(&lfs, "\xc0/\xf0") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "\xc0/\xa0", &info) => 0; + assert(strcmp(info.name, "\xa0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xc0/\xb0", &info) => 0; + assert(strcmp(info.name, "\xb0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xc0/\xc0", &info) => 0; + assert(strcmp(info.name, "\xc0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xc0/\xd0", &info) => 0; + assert(strcmp(info.name, "\xd0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xc0/\xe0", &info) => 0; + assert(strcmp(info.name, "\xe0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xc0/\xf0", &info) => 0; + assert(strcmp(info.name, "\xf0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\xc0/\xa0") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xc0/\xb0") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xc0/\xc0") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xc0/\xd0") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xc0/\xe0") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xc0/\xf0") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\xc0/\xa0") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xc0/\xb0") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xc0/\xc0") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xc0/\xd0") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xc0/\xe0") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xc0/\xf0") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "\xe0") => 0; + lfs_rename(&lfs, + "\xc0/\xa0", + "\xe0/\xaf") => 0; + lfs_rename(&lfs, + "\xc0/\xb0", + "\xe0/\xbf") => 0; + lfs_rename(&lfs, + "\xc0/\xc0", + "\xe0/\xcf") => 0; + lfs_rename(&lfs, + "\xc0/\xd0", + "\xe0/\xdf") => 0; + lfs_rename(&lfs, + "\xc0/\xe0", + "\xe0/\xef") => 0; + lfs_rename(&lfs, + "\xc0/\xf0", + "\xe0/\xff") => 0; + + // stat paths + lfs_stat(&lfs, "\xe0/\xaf", &info) => 0; + assert(strcmp(info.name, "\xaf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xe0/\xbf", &info) => 0; + assert(strcmp(info.name, "\xbf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xe0/\xcf", &info) => 0; + assert(strcmp(info.name, "\xcf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xe0/\xdf", &info) => 0; + assert(strcmp(info.name, "\xdf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xe0/\xef", &info) => 0; + assert(strcmp(info.name, "\xef") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xe0/\xff", &info) => 0; + assert(strcmp(info.name, "\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "\xc0/\xa0", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xc0/\xb0", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xc0/\xc0", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xc0/\xd0", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xc0/\xe0", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xc0/\xf0", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "\xe0/\xaf") => 0; + lfs_remove(&lfs, "\xe0/\xbf") => 0; + lfs_remove(&lfs, "\xe0/\xcf") => 0; + lfs_remove(&lfs, "\xe0/\xdf") => 0; + lfs_remove(&lfs, "\xe0/\xef") => 0; + lfs_remove(&lfs, "\xe0/\xff") => 0; + + // stat paths + lfs_stat(&lfs, "\xe0/\xaf", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xe0/\xbf", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xe0/\xcf", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xe0/\xdf", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xe0/\xef", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xe0/\xff", &info) => LFS_ERR_NOENT; + lfs_unmount(&lfs) => 0; ''' +# test with only "\xff" characters +# +# Don't do this! These filenames are not utf8 and will probably break +# external tools. +# +[cases.test_paths_oopsallffs] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "\xff") => 0; + if (DIR) { + lfs_mkdir(&lfs, "\xff/\xff") => 0; + lfs_mkdir(&lfs, "\xff/\xff\xff") => 0; + lfs_mkdir(&lfs, "\xff/\xff\xff\xff") => 0; + lfs_mkdir(&lfs, "\xff/\xff\xff\xff\xff") => 0; + lfs_mkdir(&lfs, "\xff/\xff\xff\xff\xff\xff") => 0; + lfs_mkdir(&lfs, "\xff/\xff\xff\xff\xff\xff\xff") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "\xff/\xff", &info) => 0; + assert(strcmp(info.name, "\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff/\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff/\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff/\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff/\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff/\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\xff/\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "\xff/\xff", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\xff/\xff") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff\xff") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "\xff/\xff") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff\xff") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "\xff\xff") => 0; + lfs_rename(&lfs, + "\xff/\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff") => 0; + lfs_rename(&lfs, + "\xff/\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_rename(&lfs, + "\xff/\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_rename(&lfs, + "\xff/\xff\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_rename(&lfs, + "\xff/\xff\xff\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_rename(&lfs, + "\xff/\xff\xff\xff\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + + // stat paths + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "\xff/\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff/\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff/\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff/\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff/\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff/\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff") => 0; + lfs_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfs_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + + // stat paths + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' From 232e736aae99dda27a0a6f3b37e94c3c7c7e61cb Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 20 Nov 2024 18:38:23 -0600 Subject: [PATCH 17/28] paths: Added trailing slashes and dots tests As expected these are failing and will need some work to pass. The issue with lfs_file_open allowing trailing slashes was found by rob-zeno, and the issue with lfs_mkdir disallowing trailing slashes was found by XinStellaris, PoppaChubby, pavel-kirienko, inf265, Xywzel, steverpalmer, and likely others. --- tests/test_paths.toml | 946 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 943 insertions(+), 3 deletions(-) diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 89fb89e9..8ffb2658 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -568,7 +568,311 @@ code = ''' lfs_unmount(&lfs) => 0; ''' -# TODO test trailing slashes +# test trailing slashes +# +# trailing slashes are only allowed on directories +[cases.test_paths_trailing_slashes] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip/") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew//") => 0; + lfs_mkdir(&lfs, "coffee/turkish///") => 0; + lfs_mkdir(&lfs, "coffee/tubruk////") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese/////") => 0; + lfs_mkdir(&lfs, "coffee/thai//////") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + + // still create so we have something to test + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + if (DIR) { + lfs_stat(&lfs, "coffee/drip//////", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/coldbrew/////", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/turkish////", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/tubruk///", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/vietnamese//", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/thai/", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_DIR); + } else { + lfs_stat(&lfs, "coffee/drip//////", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/coldbrew/////", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/turkish////", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/tubruk///", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/vietnamese//", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/thai/", &info) => LFS_ERR_NOTDIR; + } + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip/") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew//") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/turkish///") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/tubruk////") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/////") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/thai//////") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip/") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew//") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/turkish///") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/tubruk////") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/////") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/thai//////") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + if (DIR) { + lfs_rename(&lfs, + "coffee/drip//////", + "espresso/espresso/") => 0; + lfs_rename(&lfs, + "coffee/coldbrew/////", + "espresso/americano//") => 0; + lfs_rename(&lfs, + "coffee/turkish////", + "espresso/macchiato///") => 0; + lfs_rename(&lfs, + "coffee/tubruk///", + "espresso/latte////") => 0; + lfs_rename(&lfs, + "coffee/vietnamese//", + "espresso/cappuccino/////") => 0; + lfs_rename(&lfs, + "coffee/thai/", + "espresso/mocha//////") => 0; + + // stat paths + lfs_stat(&lfs, "espresso/espresso//////", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/americano/////", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/macchiato////", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/latte///", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/cappuccino//", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/mocha/", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == LFS_TYPE_DIR); + + lfs_stat(&lfs, "coffee/drip//////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/coldbrew/////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/turkish////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tubruk///", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/vietnamese//", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/thai/", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "espresso/espresso/") => 0; + lfs_remove(&lfs, "espresso/americano//") => 0; + lfs_remove(&lfs, "espresso/macchiato///") => 0; + lfs_remove(&lfs, "espresso/latte////") => 0; + lfs_remove(&lfs, "espresso/cappuccino/////") => 0; + lfs_remove(&lfs, "espresso/mocha//////") => 0; + + // stat paths + lfs_stat(&lfs, "espresso/espresso//////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano/////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte///", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino//", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha/", &info) => LFS_ERR_NOENT; + + } else { + // bad source + lfs_rename(&lfs, + "coffee/drip//////", + "espresso/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew/////", + "espresso/americano") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish////", + "espresso/macchiato") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk///", + "espresso/latte") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese//", + "espresso/cappuccino") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai/", + "espresso/mocha") => LFS_ERR_NOTDIR; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "espresso/espresso/") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew", + "espresso/americano//") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish", + "espresso/macchiato///") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk", + "espresso/latte////") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/////") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai", + "espresso/mocha//////") => LFS_ERR_NOTDIR; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/drip//////", + "espresso/espresso/") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew/////", + "espresso/americano//") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish////", + "espresso/macchiato///") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk///", + "espresso/latte////") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese//", + "espresso/cappuccino/////") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai/", + "espresso/mocha//////") => LFS_ERR_NOTDIR; + + // remove paths + lfs_remove(&lfs, "coffee/drip/") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/coldbrew//") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/turkish///") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/tubruk////") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/vietnamese/////") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/thai//////") => LFS_ERR_NOTDIR; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_REG); + } + + lfs_unmount(&lfs) => 0; +''' # dot path tests [cases.test_paths_dots] @@ -759,7 +1063,325 @@ code = ''' lfs_unmount(&lfs) => 0; ''' -# TODO test trailing dots +# test trailing dots, these get a bit weird +[cases.test_paths_trailing_dots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip/.") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/coldbrew/./.") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/turkish/././.") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/tubruk/./././.") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/vietnamese/././././.") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/thai/./././././.") => LFS_ERR_NOENT; + + // still create so we have something to test + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + + // still create so we have something to test + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + if (DIR) { + lfs_stat(&lfs, "coffee/drip/./././././.", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/coldbrew/././././.", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/turkish/./././.", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/tubruk/././.", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/vietnamese/./.", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/thai/.", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_DIR); + } else { + lfs_stat(&lfs, "coffee/drip/./././././.", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/coldbrew/././././.", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/turkish/./././.", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/tubruk/././.", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/vietnamese/./.", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/thai/.", &info) => LFS_ERR_NOTDIR; + } + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip/.") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew/./.") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/turkish/././.") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/tubruk/./././.") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/././././.") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/thai/./././././.") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip/.") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew/./.") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/turkish/././.") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/tubruk/./././.") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/././././.") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/thai/./././././.") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + if (DIR) { + // bad source + lfs_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/thai/.", + "espresso/mocha") => LFS_ERR_INVAL; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tubruk", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai/.", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + } else { + // bad source + lfs_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai/.", + "espresso/mocha") => LFS_ERR_NOTDIR; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tubruk", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso/.") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano/./.") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato/././.") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte/./././.") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino/././././.") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai/.", + "espresso/mocha/./././././.") => LFS_ERR_NOTDIR; + } + + // remove paths + if (DIR) { + lfs_remove(&lfs, "coffee/drip/.") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/coldbrew/./.") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/turkish/././.") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/tubruk/./././.") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/vietnamese/././././.") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/thai/./././././.") => LFS_ERR_INVAL; + } else { + lfs_remove(&lfs, "coffee/drip/.") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/coldbrew/./.") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/turkish/././.") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/tubruk/./././.") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/vietnamese/././././.") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/thai/./././././.") => LFS_ERR_NOTDIR; + } + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_unmount(&lfs) => 0; +''' # dot dot path tests [cases.test_paths_dotdots] @@ -953,7 +1575,325 @@ code = ''' lfs_unmount(&lfs) => 0; ''' -# TODO test trailing dotdots +# test trailing dot dots, these get really weird +[cases.test_paths_trailing_dotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip/..") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/coldbrew/../..") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/turkish/../../..") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_NOENT; + + // still create so we have something to test + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + + // still create so we have something to test + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + if (DIR) { + lfs_stat(&lfs, "coffee/drip/../../../../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/turkish/../../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/tubruk/../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/vietnamese/../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/thai/..", &info) => 0; + assert(strcmp(info.name, "coffee") == 0); + assert(info.type == LFS_TYPE_DIR); + } else { + lfs_stat(&lfs, "coffee/drip/../../../../../..", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/turkish/../../../..", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/tubruk/../../..", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/vietnamese/../..", &info) => LFS_ERR_NOTDIR; + lfs_stat(&lfs, "coffee/thai/..", &info) => LFS_ERR_NOTDIR; + } + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip/..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew/../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/turkish/../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip/..") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew/../..") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/turkish/../../..") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + if (DIR) { + // bad source + lfs_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/thai/..", + "espresso/mocha") => LFS_ERR_INVAL; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "espresso/espresso/..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tubruk", + "espresso/latte/../../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/../../../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai", + "espresso/mocha/../../../../../..") => LFS_ERR_NOENT; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso/..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano/../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato/../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte/../../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino/../../../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai/..", + "espresso/mocha/../../../../../..") => LFS_ERR_NOENT; + + } else { + // bad source + lfs_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai/..", + "espresso/mocha") => LFS_ERR_NOTDIR; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "espresso/espresso/..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/../../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk", + "espresso/latte/../../../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/../../../../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai", + "espresso/mocha/../../../../../..") => LFS_ERR_NOTDIR; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso/..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano/../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato/../../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte/../../../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino/../../../../..") => LFS_ERR_NOTDIR; + lfs_rename(&lfs, + "coffee/thai/..", + "espresso/mocha/../../../../../..") => LFS_ERR_NOTDIR; + } + + // remove paths + if (DIR) { + lfs_remove(&lfs, "coffee/drip/..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/coldbrew/../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/turkish/../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; + } else { + lfs_remove(&lfs, "coffee/drip/..") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/coldbrew/../..") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/turkish/../../..") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_NOTDIR; + lfs_remove(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_NOTDIR; + } + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_unmount(&lfs) => 0; +''' # dot dot dot path tests [cases.test_paths_dotdotdots] From a6035071bede7308d30f38c26594b90e5c21395a Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 22 Nov 2024 17:07:51 -0600 Subject: [PATCH 18/28] paths: Fixed/doc trailing slash/dot POSIX incompatibilities - lfs_mkdir now accepts trailing slashes: - before: lfs_mkdir("a/") => LFS_ERR_NOENT - after: lfs_mkdir("a/") => 0 - lfs_stat, lfs_getattr, etc, now reject trailing slashes if the file is not a directory: - before: lfs_stat("reg_a/") => 0 - after: lfs_stat("reg_a/") => LFS_ERR_NOTDIR Note trailing slashes are accepted if the file is a directory: - before: lfs_stat("dir_a/") => 0 - after: lfs_stat("dir_a/") => 0 - lfs_file_open now returns LFS_ERR_NOTDIR if the file exists but the path contains trailing slashes: - before: lfs_file_open("reg_a/") => LFS_ERR_NOENT - after: lfs_file_open("reg_a/") => LFS_ERR_NOTDIR To make these work, the internal lfs_dir_find API required some interesting changes: - lfs_dir_find no longer sets id=0x3ff on not finding a parent entry in the path. Instead, lfs_path_islast can be used to determine if the modified path references a parent entry or child entry based on the remainder of the path string. Note this is only necessary for functions that create new entries (lfs_mkdir, lfs_rename, lfs_file_open). - Trailing slashes mean we can no longer rely on the modified path being NULL-terminated. lfs_path_namelen provides an alternative to strlen that stops at slash or NULL. - lfs_path_isdir also tells you if the modified path must reference a dir (contains trailing slashes). I considered handling this entirely in lfs_dir_find, but the behavior of entry-creating functions is too nuanced. At least lfs_dir_find returns LFS_ERR_NOTDIR if the file exists on disk. Like strlen, lfs_path_namelen/islast/isdir are all O(n) where n is the name length. This isn't great, but if you're using filenames large enough for this to actually matter... uh... open an issue on GitHub and we might improve this in the future. --- There are a couple POSIX incompatibilities that I think are not worth fixing: - Root modifications return EINVAL instead of EBUSY: - littlefs: remove("/") => EINVAL - POSIX: remove("/") => EBUSY Reason: This would be the only use of EBUSY in the system. - We accept modifications of directories with trailing dots: - littlefs: remove("a/.") => 0 - POSIX: remove("a/.") => EBUSY Reason: Not worth implementing. - We do not check for existence of directories followed by dotdots: - littlefs: stat("a/missing/..") => 0 - POSIX: stat("a/missing/..") => ENOENT Reason: Difficult to implement non-recursively. - We accept modifications of directories with trailing dotdots: - littlefs: rename("a/b/..", "c") => 0 - POSIX: rename("a/b/..", "c") => EBUSY Reason: Not worth implementing. These are at least now documented in tests/test_paths.toml, which isn't the greatest location, but it's at least something until a better document is created. Note that these don't really belong in SPEC.md because path parsing is a function of the driver and has no impact on disk. --- lfs.c | 68 ++++-- tests/test_paths.toml | 522 ++++++++++++++++++++---------------------- 2 files changed, 299 insertions(+), 291 deletions(-) diff --git a/lfs.c b/lfs.c index d35d5d6d..db7aae5c 100644 --- a/lfs.c +++ b/lfs.c @@ -282,6 +282,21 @@ static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { /// Small type-level utilities /// + +// some operations on paths +static inline lfs_size_t lfs_path_namelen(const char *path) { + return strcspn(path, "/"); +} + +static inline bool lfs_path_islast(const char *path) { + lfs_size_t namelen = lfs_path_namelen(path); + return path[namelen + strspn(path + namelen, "/")] == '\0'; +} + +static inline bool lfs_path_isdir(const char *path) { + return path[lfs_path_namelen(path)] != '\0'; +} + // operations on block pairs static inline void lfs_pair_swap(lfs_block_t pair[2]) { lfs_block_t t = pair[0]; @@ -1461,13 +1476,16 @@ static int lfs_dir_find_match(void *data, return LFS_CMP_EQ; } +// lfs_dir_find tries to set path and id even if file is not found +// +// returns: +// - 0 if file is found +// - LFS_ERR_NOENT if file or parent is not found +// - LFS_ERR_NOTDIR if parent is not a dir static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, const char **path, uint16_t *id) { // we reduce path to a single name if we can find it const char *name = *path; - if (id) { - *id = 0x3ff; - } // default to root dir lfs_stag_t tag = LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0); @@ -1476,8 +1494,10 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, while (true) { nextname: - // skip slashes - name += strspn(name, "/"); + // skip slashes if we're a directory + if (lfs_tag_type3(tag) == LFS_TYPE_DIR) { + name += strspn(name, "/"); + } lfs_size_t namelen = strcspn(name, "/"); // skip '.' and root '..' @@ -1519,7 +1539,7 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, // update what we've found so far *path = name; - // only continue if we hit a directory + // only continue if we're a directory if (lfs_tag_type3(tag) != LFS_TYPE_DIR) { return LFS_ERR_NOTDIR; } @@ -1539,8 +1559,7 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, tag = lfs_dir_fetchmatch(lfs, dir, dir->tail, LFS_MKTAG(0x780, 0, 0), LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), - // are we last name? - (strchr(name, '/') == NULL) ? id : NULL, + id, lfs_dir_find_match, &(struct lfs_dir_find_match){ lfs, name, namelen}); if (tag < 0) { @@ -2603,12 +2622,12 @@ static int lfs_mkdir_(lfs_t *lfs, const char *path) { cwd.next = lfs->mlist; uint16_t id; err = lfs_dir_find(lfs, &cwd.m, &path, &id); - if (!(err == LFS_ERR_NOENT && id != 0x3ff)) { + if (!(err == LFS_ERR_NOENT && lfs_path_islast(path))) { return (err < 0) ? err : LFS_ERR_EXIST; } // check that name fits - lfs_size_t nlen = strlen(path); + lfs_size_t nlen = lfs_path_namelen(path); if (nlen > lfs->name_max) { return LFS_ERR_NAMETOOLONG; } @@ -3057,7 +3076,7 @@ static int lfs_file_opencfg_(lfs_t *lfs, lfs_file_t *file, // allocate entry for file if it doesn't exist lfs_stag_t tag = lfs_dir_find(lfs, &file->m, &path, &file->id); - if (tag < 0 && !(tag == LFS_ERR_NOENT && file->id != 0x3ff)) { + if (tag < 0 && !(tag == LFS_ERR_NOENT && lfs_path_islast(path))) { err = tag; goto cleanup; } @@ -3077,8 +3096,14 @@ static int lfs_file_opencfg_(lfs_t *lfs, lfs_file_t *file, goto cleanup; } + // don't allow trailing slashes + if (lfs_path_isdir(path)) { + err = LFS_ERR_ISDIR; + goto cleanup; + } + // check that name fits - lfs_size_t nlen = strlen(path); + lfs_size_t nlen = lfs_path_namelen(path); if (nlen > lfs->name_max) { err = LFS_ERR_NAMETOOLONG; goto cleanup; @@ -3842,6 +3867,12 @@ static int lfs_stat_(lfs_t *lfs, const char *path, struct lfs_info *info) { return (int)tag; } + // only allow trailing slashes on dirs + if (strchr(path, '/') != NULL + && lfs_tag_type3(tag) != LFS_TYPE_DIR) { + return LFS_ERR_NOTDIR; + } + return lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag), info); } @@ -3944,7 +3975,7 @@ static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) { uint16_t newid; lfs_stag_t prevtag = lfs_dir_find(lfs, &newcwd, &newpath, &newid); if ((prevtag < 0 || lfs_tag_id(prevtag) == 0x3ff) && - !(prevtag == LFS_ERR_NOENT && newid != 0x3ff)) { + !(prevtag == LFS_ERR_NOENT && lfs_path_islast(newpath))) { return (prevtag < 0) ? (int)prevtag : LFS_ERR_INVAL; } @@ -3955,8 +3986,14 @@ static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) { struct lfs_mlist prevdir; prevdir.next = lfs->mlist; if (prevtag == LFS_ERR_NOENT) { + // if we're a file, don't allow trailing slashes + if (lfs_path_isdir(newpath) + && lfs_tag_type3(oldtag) != LFS_TYPE_DIR) { + return LFS_ERR_NOTDIR; + } + // check that name fits - lfs_size_t nlen = strlen(newpath); + lfs_size_t nlen = lfs_path_namelen(newpath); if (nlen > lfs->name_max) { return LFS_ERR_NAMETOOLONG; } @@ -4016,7 +4053,8 @@ static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) { {LFS_MKTAG_IF(prevtag != LFS_ERR_NOENT, LFS_TYPE_DELETE, newid, 0), NULL}, {LFS_MKTAG(LFS_TYPE_CREATE, newid, 0), NULL}, - {LFS_MKTAG(lfs_tag_type3(oldtag), newid, strlen(newpath)), newpath}, + {LFS_MKTAG(lfs_tag_type3(oldtag), + newid, lfs_path_namelen(newpath)), newpath}, {LFS_MKTAG(LFS_FROM_MOVE, newid, lfs_tag_id(oldtag)), &oldcwd}, {LFS_MKTAG_IF(samepair, LFS_TYPE_DELETE, newoldid, 0), NULL})); diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 8ffb2658..69f1d7fe 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -1064,6 +1064,14 @@ code = ''' ''' # test trailing dots, these get a bit weird +# +# POSIX deviations: +# +# - We accept modifications of directories with trailing dots: +# - littlefs: remove("a/.") => 0 +# - POSIX: remove("a/.") => EBUSY +# Reason: Not worth implementing. +# [cases.test_paths_trailing_dots] defines.DIR = [false, true] code = ''' @@ -1214,26 +1222,6 @@ code = ''' // rename paths lfs_mkdir(&lfs, "espresso") => 0; if (DIR) { - // bad source - lfs_rename(&lfs, - "coffee/drip/./././././.", - "espresso/espresso") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/coldbrew/././././.", - "espresso/americano") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/turkish/./././.", - "espresso/macchiato") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/tubruk/././.", - "espresso/latte") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/vietnamese/./.", - "espresso/cappuccino") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/thai/.", - "espresso/mocha") => LFS_ERR_INVAL; - // bad destination lfs_rename(&lfs, "coffee/drip", @@ -1274,6 +1262,69 @@ code = ''' "coffee/thai/.", "espresso/mocha/./././././.") => LFS_ERR_NOENT; + // this one works + lfs_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso") => 0; + lfs_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano") => 0; + lfs_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato") => 0; + lfs_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte") => 0; + lfs_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino") => 0; + lfs_rename(&lfs, + "coffee/thai/.", + "espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "espresso/espresso/./././././.", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/americano/././././.", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/macchiato/./././.", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/latte/././.", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/cappuccino/./.", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "espresso/mocha/.", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == LFS_TYPE_DIR); + + lfs_stat(&lfs, "coffee/drip/./././././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/coldbrew/././././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/turkish/./././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tubruk/././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/vietnamese/./.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/thai/.", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "espresso/espresso/.") => 0; + lfs_remove(&lfs, "espresso/americano/./.") => 0; + lfs_remove(&lfs, "espresso/macchiato/././.") => 0; + lfs_remove(&lfs, "espresso/latte/./././.") => 0; + lfs_remove(&lfs, "espresso/cappuccino/././././.") => 0; + lfs_remove(&lfs, "espresso/mocha/./././././.") => 0; + + // stat paths + lfs_stat(&lfs, "espresso/espresso/./././././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano/././././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato/./././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte/././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino/./.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha/.", &info) => LFS_ERR_NOENT; + } else { // bad source lfs_rename(&lfs, @@ -1334,51 +1385,42 @@ code = ''' lfs_rename(&lfs, "coffee/thai/.", "espresso/mocha/./././././.") => LFS_ERR_NOTDIR; - } - // remove paths - if (DIR) { - lfs_remove(&lfs, "coffee/drip/.") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/coldbrew/./.") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/turkish/././.") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/tubruk/./././.") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/vietnamese/././././.") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/thai/./././././.") => LFS_ERR_INVAL; - } else { + // remove paths lfs_remove(&lfs, "coffee/drip/.") => LFS_ERR_NOTDIR; lfs_remove(&lfs, "coffee/coldbrew/./.") => LFS_ERR_NOTDIR; lfs_remove(&lfs, "coffee/turkish/././.") => LFS_ERR_NOTDIR; lfs_remove(&lfs, "coffee/tubruk/./././.") => LFS_ERR_NOTDIR; lfs_remove(&lfs, "coffee/vietnamese/././././.") => LFS_ERR_NOTDIR; lfs_remove(&lfs, "coffee/thai/./././././.") => LFS_ERR_NOTDIR; - } - // stat paths - lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "coffee/drip", &info) => 0; - assert(strcmp(info.name, "drip") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; - assert(strcmp(info.name, "coldbrew") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "coffee/turkish", &info) => 0; - assert(strcmp(info.name, "turkish") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "coffee/tubruk", &info) => 0; - assert(strcmp(info.name, "tubruk") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; - assert(strcmp(info.name, "vietnamese") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "coffee/thai", &info) => 0; - assert(strcmp(info.name, "thai") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_REG); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_REG); + } lfs_unmount(&lfs) => 0; ''' @@ -1576,6 +1618,19 @@ code = ''' ''' # test trailing dot dots, these get really weird +# +# POSIX deviations: +# +# - We do not check for existance of directories followed by dotdots: +# - littlefs: stat("a/missing/..") => 0 +# - POSIX: stat("a/missing/..") => ENOENT +# Reason: Difficult to implement non-recursively. +# +# - We accept modifications of directories with trailing dotdots: +# - littlefs: rename("a/b/..", "c") => 0 +# - POSIX: rename("a/b/..", "c") => EBUSY +# Reason: Not worth implementing. +# [cases.test_paths_trailing_dotdots] defines.DIR = [false, true] code = ''' @@ -1586,12 +1641,12 @@ code = ''' // create paths lfs_mkdir(&lfs, "coffee") => 0; if (DIR) { - lfs_mkdir(&lfs, "coffee/drip/..") => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "coffee/coldbrew/../..") => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "coffee/turkish/../../..") => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_NOENT; - lfs_mkdir(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_NOENT; + lfs_mkdir(&lfs, "coffee/drip/..") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "coffee/coldbrew/../..") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "coffee/turkish/../../..") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_EXIST; // still create so we have something to test lfs_mkdir(&lfs, "coffee/drip") => 0; @@ -1604,17 +1659,17 @@ code = ''' } else { lfs_file_t file; lfs_file_open(&lfs, &file, "coffee/drip/..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; lfs_file_open(&lfs, &file, "coffee/turkish/../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; // still create so we have something to test lfs_file_open(&lfs, &file, "coffee/drip", @@ -1639,231 +1694,138 @@ code = ''' // stat paths struct lfs_info info; - if (DIR) { - lfs_stat(&lfs, "coffee/drip/../../../../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/turkish/../../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/tubruk/../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/vietnamese/../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/thai/..", &info) => 0; - assert(strcmp(info.name, "coffee") == 0); - assert(info.type == LFS_TYPE_DIR); - } else { - lfs_stat(&lfs, "coffee/drip/../../../../../..", &info) => LFS_ERR_NOTDIR; - lfs_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => LFS_ERR_NOTDIR; - lfs_stat(&lfs, "coffee/turkish/../../../..", &info) => LFS_ERR_NOTDIR; - lfs_stat(&lfs, "coffee/tubruk/../../..", &info) => LFS_ERR_NOTDIR; - lfs_stat(&lfs, "coffee/vietnamese/../..", &info) => LFS_ERR_NOTDIR; - lfs_stat(&lfs, "coffee/thai/..", &info) => LFS_ERR_NOTDIR; - } + lfs_stat(&lfs, "coffee/drip/../../../../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/turkish/../../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/tubruk/../../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/vietnamese/../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/thai/..", &info) => 0; + assert(strcmp(info.name, "coffee") == 0); + assert(info.type == LFS_TYPE_DIR); // file open paths, only works on files! - if (DIR) { - lfs_file_t file; - lfs_file_open(&lfs, &file, "coffee/drip/..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "coffee/turkish/../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - } else { - lfs_file_t file; - lfs_file_open(&lfs, &file, "coffee/drip/..", - LFS_O_RDONLY) => LFS_ERR_NOTDIR; - lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", - LFS_O_RDONLY) => LFS_ERR_NOTDIR; - lfs_file_open(&lfs, &file, "coffee/turkish/../../..", - LFS_O_RDONLY) => LFS_ERR_NOTDIR; - lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", - LFS_O_RDONLY) => LFS_ERR_NOTDIR; - lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", - LFS_O_RDONLY) => LFS_ERR_NOTDIR; - lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", - LFS_O_RDONLY) => LFS_ERR_NOTDIR; - } + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; // dir open paths, only works on dirs! - if (DIR) { - lfs_dir_t dir; - lfs_dir_open(&lfs, &dir, "coffee/drip/..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/coldbrew/../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/turkish/../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - } else { - lfs_dir_t dir; - lfs_dir_open(&lfs, &dir, "coffee/drip/..") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "coffee/coldbrew/../..") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "coffee/turkish/../../..") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => LFS_ERR_NOTDIR; - } + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/drip/..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/coldbrew/../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/turkish/../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; // rename paths lfs_mkdir(&lfs, "espresso") => 0; - if (DIR) { - // bad source - lfs_rename(&lfs, - "coffee/drip/../../../../../..", - "espresso/espresso") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/coldbrew/../../../../..", - "espresso/americano") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/turkish/../../../..", - "espresso/macchiato") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/tubruk/../../..", - "espresso/latte") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/vietnamese/../..", - "espresso/cappuccino") => LFS_ERR_INVAL; - lfs_rename(&lfs, - "coffee/thai/..", - "espresso/mocha") => LFS_ERR_INVAL; + // bad source + lfs_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino") => LFS_ERR_INVAL; + // this one works + lfs_rename(&lfs, + "coffee/thai/..", + "espresso/mocha") => 0; + lfs_rename(&lfs, + "espresso/mocha", + "coffee") => 0; - // bad destination + // bad destination + if (DIR) { + // this one works lfs_rename(&lfs, "coffee/drip", - "espresso/espresso/..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/coldbrew", - "espresso/americano/../..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/turkish", - "espresso/macchiato/../../..") => LFS_ERR_NOENT; + "espresso/espresso/..") => 0; lfs_rename(&lfs, - "coffee/tubruk", - "espresso/latte/../../../..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/vietnamese", - "espresso/cappuccino/../../../../..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/thai", - "espresso/mocha/../../../../../..") => LFS_ERR_NOENT; - - // bad source and bad destination - lfs_rename(&lfs, - "coffee/drip/../../../../../..", - "espresso/espresso/..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/coldbrew/../../../../..", - "espresso/americano/../..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/turkish/../../../..", - "espresso/macchiato/../../..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/tubruk/../../..", - "espresso/latte/../../../..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/vietnamese/../..", - "espresso/cappuccino/../../../../..") => LFS_ERR_NOENT; - lfs_rename(&lfs, - "coffee/thai/..", - "espresso/mocha/../../../../../..") => LFS_ERR_NOENT; - + "espresso", + "coffee/drip") => 0; } else { - // bad source - lfs_rename(&lfs, - "coffee/drip/../../../../../..", - "espresso/espresso") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/coldbrew/../../../../..", - "espresso/americano") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/turkish/../../../..", - "espresso/macchiato") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/tubruk/../../..", - "espresso/latte") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/vietnamese/../..", - "espresso/cappuccino") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/thai/..", - "espresso/mocha") => LFS_ERR_NOTDIR; - - // bad destination lfs_rename(&lfs, "coffee/drip", - "espresso/espresso/..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/coldbrew", - "espresso/americano/../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/turkish", - "espresso/macchiato/../../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/tubruk", - "espresso/latte/../../../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/vietnamese", - "espresso/cappuccino/../../../../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/thai", - "espresso/mocha/../../../../../..") => LFS_ERR_NOTDIR; - - // bad source and bad destination - lfs_rename(&lfs, - "coffee/drip/../../../../../..", - "espresso/espresso/..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/coldbrew/../../../../..", - "espresso/americano/../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/turkish/../../../..", - "espresso/macchiato/../../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/tubruk/../../..", - "espresso/latte/../../../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/vietnamese/../..", - "espresso/cappuccino/../../../../..") => LFS_ERR_NOTDIR; - lfs_rename(&lfs, - "coffee/thai/..", - "espresso/mocha/../../../../../..") => LFS_ERR_NOTDIR; + "espresso/espresso/..") => LFS_ERR_ISDIR; } + lfs_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tubruk", + "espresso/latte/../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/../../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/thai", + "espresso/mocha/../../../../../..") => LFS_ERR_INVAL; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso/..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano/../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato/../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte/../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino/../../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/thai/..", + "espresso/mocha/../../../../../..") => LFS_ERR_INVAL; // remove paths - if (DIR) { - lfs_remove(&lfs, "coffee/drip/..") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/coldbrew/../..") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/turkish/../../..") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; - lfs_remove(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; - } else { - lfs_remove(&lfs, "coffee/drip/..") => LFS_ERR_NOTDIR; - lfs_remove(&lfs, "coffee/coldbrew/../..") => LFS_ERR_NOTDIR; - lfs_remove(&lfs, "coffee/turkish/../../..") => LFS_ERR_NOTDIR; - lfs_remove(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_NOTDIR; - lfs_remove(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_NOTDIR; - lfs_remove(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_NOTDIR; - } + lfs_remove(&lfs, "coffee/drip/..") => LFS_ERR_NOTEMPTY; + lfs_remove(&lfs, "coffee/coldbrew/../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/turkish/../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; // stat paths lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; @@ -3048,6 +3010,14 @@ code = ''' ''' # root operations +# +# POSIX deviations: +# +# - Root modifications return EINVAL instead of EBUSY: +# - littlefs: remove("/") => EINVAL +# - POSIX: remove("/") => EBUSY +# Reason: This would be the only use of EBUSY in the system. +# [cases.test_paths_root] defines.DIR = [false, true] code = ''' From dc92dec6d3f41213c4d0011c440195c991ef38a4 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 23 Nov 2024 01:23:11 -0600 Subject: [PATCH 19/28] paths: Reject dotdots above root This changes the behavior of paths that attempt to navigate above root to now return LFS_ERR_INVAL: - before: lfs_stat("/../a") => 0 - after: lfs_stat("/../a") => LFS_ERR_INVAL This is a bit of an opinionated change while making other path resolution tweaks. In terms of POSIX-compatibility, it's a bit unclear exactly what dotdots above the root should do. POSIX notes: > As a special case, in the root directory, dot-dot may refer to the > root directory itself. But the word choice of "may" implies it is up to the implementation. I originally implement this as a root-loop simply because that is what my Linux machine does, but I now think that's not the best option. Since we're making other path-related tweaks, we might as well try to adopt behavior that is, in my opinion, safer and less... weird... This should also help make paths more consistent with future theoretical openat-list APIs, where saturating at the current directory is sort of the least expected behavior. --- lfs.c | 10 +- tests/test_paths.toml | 354 +++++++++++++++++++++--------------------- 2 files changed, 182 insertions(+), 182 deletions(-) diff --git a/lfs.c b/lfs.c index db7aae5c..6cef3eed 100644 --- a/lfs.c +++ b/lfs.c @@ -1500,13 +1500,17 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, } lfs_size_t namelen = strcspn(name, "/"); - // skip '.' and root '..' - if ((namelen == 1 && memcmp(name, ".", 1) == 0) || - (namelen == 2 && memcmp(name, "..", 2) == 0)) { + // skip '.' + if (namelen == 1 && memcmp(name, ".", 1) == 0) { name += namelen; goto nextname; } + // error on unmatched '..', trying to go above root? + if (namelen == 2 && memcmp(name, "..", 2) == 0) { + return LFS_ERR_INVAL; + } + // skip if matched by '..' in name const char *suffix = name + namelen; lfs_size_t sufflen; diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 69f1d7fe..9e3a151e 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -1643,10 +1643,10 @@ code = ''' if (DIR) { lfs_mkdir(&lfs, "coffee/drip/..") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "coffee/coldbrew/../..") => LFS_ERR_EXIST; - lfs_mkdir(&lfs, "coffee/turkish/../../..") => LFS_ERR_EXIST; - lfs_mkdir(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_EXIST; - lfs_mkdir(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_EXIST; - lfs_mkdir(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_EXIST; + lfs_mkdir(&lfs, "coffee/turkish/../../..") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; // still create so we have something to test lfs_mkdir(&lfs, "coffee/drip") => 0; @@ -1663,13 +1663,13 @@ code = ''' lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; lfs_file_open(&lfs, &file, "coffee/turkish/../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; // still create so we have something to test lfs_file_open(&lfs, &file, "coffee/drip", @@ -1694,18 +1694,10 @@ code = ''' // stat paths struct lfs_info info; - lfs_stat(&lfs, "coffee/drip/../../../../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/turkish/../../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "coffee/tubruk/../../..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/drip/../../../../../..", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "coffee/turkish/../../../..", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "coffee/tubruk/../../..", &info) => LFS_ERR_INVAL; lfs_stat(&lfs, "coffee/vietnamese/../..", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); @@ -1720,13 +1712,13 @@ code = ''' lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "coffee/turkish/../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; + LFS_O_RDONLY) => LFS_ERR_INVAL; lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; + LFS_O_RDONLY) => LFS_ERR_INVAL; lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; + LFS_O_RDONLY) => LFS_ERR_INVAL; lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; + LFS_O_RDONLY) => LFS_ERR_INVAL; // dir open paths, only works on dirs! lfs_dir_t dir; @@ -1734,14 +1726,10 @@ code = ''' lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, "coffee/coldbrew/../..") => 0; lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/turkish/../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => 0; - lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/turkish/../../..") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; // rename paths lfs_mkdir(&lfs, "espresso") => 0; @@ -2249,181 +2237,208 @@ code = ''' lfs_mkdir(&lfs, "no") => 0; lfs_mkdir(&lfs, "coffee") => 0; if (DIR) { - lfs_mkdir(&lfs, "/../coffee/drip") => 0; - lfs_mkdir(&lfs, "/../../coffee/coldbrew") => 0; - lfs_mkdir(&lfs, "/../../../coffee/turkish") => 0; - lfs_mkdir(&lfs, "/no/../../coffee/tubruk") => 0; - lfs_mkdir(&lfs, "/no/../../../coffee/vietnamese") => 0; - lfs_mkdir(&lfs, "/no/../../../../coffee/thai") => 0; + lfs_mkdir(&lfs, "/../coffee/drip") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "/../../coffee/coldbrew") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "/../../../coffee/turkish") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "/no/../../coffee/tubruk") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "/no/../../../coffee/vietnamese") => LFS_ERR_INVAL; + lfs_mkdir(&lfs, "/no/../../../../coffee/thai") => LFS_ERR_INVAL; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + } + + // ok, actually create paths + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + lfs_file_open(&lfs, &file, "coffee/coldbrew", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + lfs_file_open(&lfs, &file, "coffee/turkish", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + lfs_file_open(&lfs, &file, "coffee/tubruk", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + lfs_file_open(&lfs, &file, "coffee/vietnamese", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + lfs_file_open(&lfs, &file, "coffee/thai", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; lfs_file_close(&lfs, &file) => 0; } // stat paths struct lfs_info info; - lfs_stat(&lfs, "/no/../../../../coffee/drip", &info) => 0; - assert(strcmp(info.name, "drip") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/no/../../../coffee/coldbrew", &info) => 0; - assert(strcmp(info.name, "coldbrew") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/no/../../coffee/turkish", &info) => 0; - assert(strcmp(info.name, "turkish") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/../../../coffee/tubruk", &info) => 0; - assert(strcmp(info.name, "tubruk") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/../../coffee/vietnamese", &info) => 0; - assert(strcmp(info.name, "vietnamese") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/../coffee/thai", &info) => 0; - assert(strcmp(info.name, "thai") == 0); - assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/../../../../coffee/drip", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "/no/../../../coffee/coldbrew", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "/no/../../coffee/turkish", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "/../../../coffee/tubruk", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "/../../coffee/vietnamese", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "/../coffee/thai", &info) => LFS_ERR_INVAL; // file open paths, only works on files! - if (DIR) { - lfs_file_t file; - lfs_file_open(&lfs, &file, "/../coffee/drip", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "/../../../coffee/turkish", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", - LFS_O_RDONLY) => LFS_ERR_ISDIR; - } else { - lfs_file_t file; - lfs_file_open(&lfs, &file, "/../coffee/drip", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/../../../coffee/turkish", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; - } + lfs_file_t file; + lfs_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_RDONLY) => LFS_ERR_INVAL; // dir open paths, only works on dirs! - if (DIR) { - lfs_dir_t dir; - lfs_dir_open(&lfs, &dir, "/../coffee/drip") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/../../coffee/coldbrew") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/../../../coffee/turkish") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/no/../../coffee/tubruk") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/no/../../../coffee/vietnamese") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/no/../../../../coffee/thai") => 0; - lfs_dir_close(&lfs, &dir) => 0; - } else { - lfs_dir_t dir; - lfs_dir_open(&lfs, &dir, "/../coffee/drip") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "/../../coffee/coldbrew") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "/../../../coffee/turkish") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "/no/../coffee/tubruk") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "/no/../../coffee/vietnamese") => LFS_ERR_NOTDIR; - lfs_dir_open(&lfs, &dir, "/no/../../../coffee/thai") => LFS_ERR_NOTDIR; - } + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/../coffee/drip") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "/../../coffee/coldbrew") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "/../../../coffee/turkish") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "/no/../../coffee/tubruk") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "/no/../../../coffee/vietnamese") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "/no/../../../../coffee/thai") => LFS_ERR_INVAL; // rename paths lfs_mkdir(&lfs, "espresso") => 0; + // bad source + lfs_rename(&lfs, + "/no/../../../../coffee/drip", + "espresso/espresso") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/no/../../../coffee/coldbrew", + "espresso/americano") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/no/../../coffee/turkish", + "espresso/macchiato") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/../../../coffee/tubruk", + "espresso/latte") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/../../coffee/vietnamese", + "espresso/cappuccino") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/../coffee/thai", + "espresso/mocha") => LFS_ERR_INVAL; + + // bad destination + lfs_rename(&lfs, + "coffee/drip", + "/../espresso/espresso") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/coldbrew", + "/../../espresso/americano") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/turkish", + "/../../../espresso/macchiato") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tubruk", + "/no/../../espresso/latte") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/vietnamese", + "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/thai", + "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; + + // bad source and bad destination lfs_rename(&lfs, "/no/../../../../coffee/drip", - "/../espresso/espresso") => 0; + "/../espresso/espresso") => LFS_ERR_INVAL; lfs_rename(&lfs, "/no/../../../coffee/coldbrew", - "/../../espresso/americano") => 0; + "/../../espresso/americano") => LFS_ERR_INVAL; lfs_rename(&lfs, "/no/../../coffee/turkish", - "/../../../espresso/macchiato") => 0; + "/../../../espresso/macchiato") => LFS_ERR_INVAL; lfs_rename(&lfs, "/../../../coffee/tubruk", - "/no/../../espresso/latte") => 0; + "/no/../../espresso/latte") => LFS_ERR_INVAL; lfs_rename(&lfs, "/../../coffee/vietnamese", - "/no/../../../espresso/cappuccino") => 0; + "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; lfs_rename(&lfs, "/../coffee/thai", - "/no/../../../../espresso/mocha") => 0; + "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; + + // here's a weird one, what happens if our rename is also a noop? + lfs_rename(&lfs, + "/../coffee/drip", + "/../espresso/espresso") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/../../coffee/coldbrew", + "/../../espresso/americano") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/../../../coffee/turkish", + "/../../../espresso/macchiato") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/no/../../coffee/tubruk", + "/no/../../espresso/latte") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/no/../../../coffee/vietnamese", + "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "/no/../../../../coffee/thai", + "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; + + // remove paths + lfs_remove(&lfs, "/../espresso/espresso") => LFS_ERR_INVAL; + lfs_remove(&lfs, "/../../espresso/americano") => LFS_ERR_INVAL; + lfs_remove(&lfs, "/../../../espresso/macchiato") => LFS_ERR_INVAL; + lfs_remove(&lfs, "/no/../../espresso/latte") => LFS_ERR_INVAL; + lfs_remove(&lfs, "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; + lfs_remove(&lfs, "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; // stat paths - lfs_stat(&lfs, "/no/../../../../espresso/espresso", &info) => 0; - assert(strcmp(info.name, "espresso") == 0); + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/no/../../../espresso/americano", &info) => 0; - assert(strcmp(info.name, "americano") == 0); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/no/../../espresso/macchiato", &info) => 0; - assert(strcmp(info.name, "macchiato") == 0); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/../../../espresso/latte", &info) => 0; - assert(strcmp(info.name, "latte") == 0); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/../../espresso/cappuccino", &info) => 0; - assert(strcmp(info.name, "cappuccino") == 0); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/../espresso/mocha", &info) => 0; - assert(strcmp(info.name, "mocha") == 0); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfs_stat(&lfs, "/no/../../../../coffee/drip", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/no/../../../coffee/coldbrew", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/no/../../coffee/turkish", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/../../../coffee/tubruk", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/../../coffee/vietnamese", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/../coffee/thai", &info) => LFS_ERR_NOENT; - - // remove paths - lfs_remove(&lfs, "/../espresso/espresso") => 0; - lfs_remove(&lfs, "/../../espresso/americano") => 0; - lfs_remove(&lfs, "/../../../espresso/macchiato") => 0; - lfs_remove(&lfs, "/no/../../espresso/latte") => 0; - lfs_remove(&lfs, "/no/../../../espresso/cappuccino") => 0; - lfs_remove(&lfs, "/no/../../../../espresso/mocha") => 0; - - // stat paths - lfs_stat(&lfs, "/no/../../../../espresso/espresso", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/no/../../../espresso/americano", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/no/../../espresso/macchiato", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/../../../espresso/latte", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/../../espresso/cappuccino", &info) => LFS_ERR_NOENT; - lfs_stat(&lfs, "/../espresso/mocha", &info) => LFS_ERR_NOENT; - lfs_unmount(&lfs) => 0; ''' @@ -3089,7 +3104,6 @@ code = ''' lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "") => LFS_ERR_EXIST; lfs_mkdir(&lfs, ".") => LFS_ERR_EXIST; - lfs_mkdir(&lfs, "..") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "./") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "/.") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "//") => LFS_ERR_EXIST; @@ -3101,8 +3115,6 @@ code = ''' LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, ".", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "..", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "./", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/.", @@ -3121,9 +3133,6 @@ code = ''' lfs_stat(&lfs, ".", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, "./", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); @@ -3142,8 +3151,6 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, ".", LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "..", - LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "./", LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/.", @@ -3159,8 +3166,6 @@ code = ''' lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, ".") => 0; lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "..") => 0; - lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, "./") => 0; lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, "/.") => 0; @@ -3172,7 +3177,6 @@ code = ''' lfs_rename(&lfs, "/", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, "", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, ".", "coffee") => LFS_ERR_INVAL; - lfs_rename(&lfs, "..", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, "./", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, "/.", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, "//", "coffee") => LFS_ERR_INVAL; @@ -3181,7 +3185,6 @@ code = ''' lfs_rename(&lfs, "coffee", "/") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", "") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", ".") => LFS_ERR_INVAL; - lfs_rename(&lfs, "coffee", "..") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", "./") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", "/.") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", "//") => LFS_ERR_INVAL; @@ -3205,9 +3208,6 @@ code = ''' lfs_stat(&lfs, ".", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, "./", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); @@ -3222,7 +3222,6 @@ code = ''' lfs_remove(&lfs, "/") => LFS_ERR_INVAL; lfs_remove(&lfs, "") => LFS_ERR_INVAL; lfs_remove(&lfs, ".") => LFS_ERR_INVAL; - lfs_remove(&lfs, "..") => LFS_ERR_INVAL; lfs_remove(&lfs, "./") => LFS_ERR_INVAL; lfs_remove(&lfs, "/.") => LFS_ERR_INVAL; lfs_remove(&lfs, "//") => LFS_ERR_INVAL; @@ -3237,9 +3236,6 @@ code = ''' lfs_stat(&lfs, ".", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, "./", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); From 815f0d85a53d2ae7fa99ec0be8cf0d86b90dc780 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 23 Nov 2024 01:49:08 -0600 Subject: [PATCH 20/28] paths: Fixed dots followed by dotdots Unlike normal files, dots (".") should not change the depth when attempting to skip dotdot ("..") entries. A weird nuance in the path parser, but at least it had a relatively easy fix. Added test_paths_dot_dotdots to prevent a regression. --- lfs.c | 4 +- tests/test_paths.toml | 192 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/lfs.c b/lfs.c index 6cef3eed..29e2838b 100644 --- a/lfs.c +++ b/lfs.c @@ -1522,7 +1522,9 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, 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; if (depth == 0) { name = suffix + sufflen; diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 9e3a151e..16430f01 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -1845,6 +1845,198 @@ code = ''' lfs_unmount(&lfs) => 0; ''' +# dot dot dot path tests +[cases.test_paths_dot_dotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "no") => 0; + lfs_mkdir(&lfs, "no/no") => 0; + lfs_mkdir(&lfs, "coffee") => 0; + lfs_mkdir(&lfs, "coffee/no") => 0; + if (DIR) { + lfs_mkdir(&lfs, "/coffee/drip") => 0; + lfs_mkdir(&lfs, "/no/./../coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "/coffee/no/./../turkish") => 0; + lfs_mkdir(&lfs, "/no/no/./.././../coffee/tubruk") => 0; + lfs_mkdir(&lfs, "/no/no/./.././../coffee/no/./../vietnamese") => 0; + lfs_mkdir(&lfs, "/no/no/./.././../no/no/./.././../coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/./.././../coffee/no/./../coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/./.././../coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/no/./../tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/./../coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/./../coffee/coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/no/./../turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/no/./../vietnamese") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/no/no/./.././../no/no/./.././../coffee/thai") => 0; + lfs_dir_close(&lfs, &dir) => 0; + } else { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/./../coffee/coldbrew") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/coffee/no/./../turkish") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/tubruk") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/no/./.././../coffee/no/./../vietnamese") => LFS_ERR_NOTDIR; + lfs_dir_open(&lfs, &dir, "/no/no/./.././../no/no/./.././../coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + lfs_rename(&lfs, + "/no/no/./.././../no/no/./.././../coffee/drip", + "/espresso/espresso") => 0; + lfs_rename(&lfs, + "/no/no/./.././../coffee/no/./../coldbrew", + "/no/./../espresso/americano") => 0; + lfs_rename(&lfs, + "/no/no/./.././../coffee/turkish", + "/espresso/no/./../macchiato") => 0; + lfs_rename(&lfs, + "/coffee/no/./../tubruk", + "/no/no/./.././../espresso/latte") => 0; + lfs_rename(&lfs, + "/no/./../coffee/vietnamese", + "/no/no/./.././../espresso/no/./../cappuccino") => 0; + lfs_rename(&lfs, + "/coffee/thai", + "/no/no/./.././../no/no/./.././../espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/./.././../espresso/no/./../americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/no/./.././../espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/no/./../latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/no/./../espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../coffee/drip", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/./.././../coffee/no/./../coldbrew", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/./.././../coffee/turkish", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/no/./../tubruk", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/./../coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "/espresso/espresso") => 0; + lfs_remove(&lfs, "/no/./../espresso/americano") => 0; + lfs_remove(&lfs, "/espresso/no/./../macchiato") => 0; + lfs_remove(&lfs, "/no/no/./.././../espresso/latte") => 0; + lfs_remove(&lfs, "/no/no/./.././../espresso/no/./../cappuccino") => 0; + lfs_remove(&lfs, "/no/no/./.././../no/no/./.././../espresso/mocha") => 0; + + // stat paths + lfs_stat(&lfs, "/no/no/./.././../no/no/./.././../espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/./.././../espresso/no/./../americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/no/./.././../espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/no/./../latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/no/./../espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_unmount(&lfs) => 0; +''' + # dot dot dot path tests [cases.test_paths_dotdotdots] defines.DIR = [false, true] From 80ca1ea300a7a969984ab4b9afd04f276fba40a8 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 23 Nov 2024 18:25:40 -0600 Subject: [PATCH 21/28] paths: Reject empty paths Before this, the empty path ("") was treated as an alias for the root. This was unintentional and just a side-effect of how the path parser worked. Now, the empty path should always result in LFS_ERR_INVAL: - before: lfs_stat("") => 0 - after: lfs_stat("") => LFS_ERR_INVAL --- lfs.c | 7 ++++- tests/test_paths.toml | 72 +++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/lfs.c b/lfs.c index 29e2838b..94d23f7b 100644 --- a/lfs.c +++ b/lfs.c @@ -1492,6 +1492,11 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, dir->tail[0] = lfs->root[0]; dir->tail[1] = lfs->root[1]; + // empty paths are not allowed + if (*name == '\0') { + return LFS_ERR_INVAL; + } + while (true) { nextname: // skip slashes if we're a directory @@ -1538,7 +1543,7 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, } // found path - if (name[0] == '\0') { + if (*name == '\0') { return tag; } diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 16430f01..aefcd203 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -3216,6 +3216,58 @@ code = ''' lfs_unmount(&lfs) => 0; ''' +# test an empty path, this should error +[cases.test_paths_empty] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + struct lfs_info info; + + // create empty, this should error + if (DIR) { + lfs_mkdir(&lfs, "") => LFS_ERR_INVAL; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + } + + // stat empty + lfs_stat(&lfs, "", &info) => LFS_ERR_INVAL; + + // file open empty, only works on files! + lfs_file_t file; + lfs_file_open(&lfs, &file, "", + LFS_O_RDONLY) => LFS_ERR_INVAL; + + // dir open empty, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "") => LFS_ERR_INVAL; + lfs_dir_close(&lfs, &dir) => 0; + + // rename empty, this should error + lfs_rename(&lfs, "", "coffee") => LFS_ERR_INVAL; + + lfs_mkdir(&lfs, "coffee") => 0; + lfs_rename(&lfs, "coffee", "") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee") => 0; + + lfs_rename(&lfs, "", "") => LFS_ERR_INVAL; + + // stat empty + lfs_stat(&lfs, "", &info) => LFS_ERR_INVAL; + + // remove empty, this should error + lfs_remove(&lfs, "") => LFS_ERR_INVAL; + + // stat empty + lfs_stat(&lfs, "", &info) => LFS_ERR_INVAL; + + lfs_unmount(&lfs) => 0; +''' + # root operations # # POSIX deviations: @@ -3294,7 +3346,6 @@ code = ''' // create root, this should error if (DIR) { lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST; - lfs_mkdir(&lfs, "") => LFS_ERR_EXIST; lfs_mkdir(&lfs, ".") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "./") => LFS_ERR_EXIST; lfs_mkdir(&lfs, "/.") => LFS_ERR_EXIST; @@ -3303,8 +3354,6 @@ code = ''' lfs_file_t file; lfs_file_open(&lfs, &file, "/", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, ".", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "./", @@ -3319,9 +3368,6 @@ code = ''' lfs_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, ".", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); @@ -3339,8 +3385,6 @@ code = ''' lfs_file_t file; lfs_file_open(&lfs, &file, "/", LFS_O_RDONLY) => LFS_ERR_ISDIR; - lfs_file_open(&lfs, &file, "", - LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, ".", LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "./", @@ -3354,8 +3398,6 @@ code = ''' lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "/") => 0; lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "") => 0; - lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, ".") => 0; lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, "./") => 0; @@ -3367,7 +3409,6 @@ code = ''' // rename root, this should error lfs_rename(&lfs, "/", "coffee") => LFS_ERR_INVAL; - lfs_rename(&lfs, "", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, ".", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, "./", "coffee") => LFS_ERR_INVAL; lfs_rename(&lfs, "/.", "coffee") => LFS_ERR_INVAL; @@ -3375,7 +3416,6 @@ code = ''' lfs_mkdir(&lfs, "coffee") => 0; lfs_rename(&lfs, "coffee", "/") => LFS_ERR_INVAL; - lfs_rename(&lfs, "coffee", "") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", ".") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", "./") => LFS_ERR_INVAL; lfs_rename(&lfs, "coffee", "/.") => LFS_ERR_INVAL; @@ -3383,7 +3423,6 @@ code = ''' lfs_remove(&lfs, "coffee") => 0; lfs_rename(&lfs, "/", "/") => LFS_ERR_INVAL; - lfs_rename(&lfs, "", "") => LFS_ERR_INVAL; lfs_rename(&lfs, ".", ".") => LFS_ERR_INVAL; lfs_rename(&lfs, "..", "..") => LFS_ERR_INVAL; lfs_rename(&lfs, "./", "./") => LFS_ERR_INVAL; @@ -3394,9 +3433,6 @@ code = ''' lfs_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, ".", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); @@ -3412,7 +3448,6 @@ code = ''' // remove root, this should error lfs_remove(&lfs, "/") => LFS_ERR_INVAL; - lfs_remove(&lfs, "") => LFS_ERR_INVAL; lfs_remove(&lfs, ".") => LFS_ERR_INVAL; lfs_remove(&lfs, "./") => LFS_ERR_INVAL; lfs_remove(&lfs, "/.") => LFS_ERR_INVAL; @@ -3422,9 +3457,6 @@ code = ''' lfs_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - lfs_stat(&lfs, "", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); lfs_stat(&lfs, ".", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); From 30947054d4a3f59300fc2f7bd66f7727cd911cd8 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 25 Nov 2024 14:26:50 -0600 Subject: [PATCH 22/28] paths: Extended tests to cover open with CREAT/EXCL These flags change the behavior of open quite significantly. It's useful to cover these in our path tests so the behavior is locked down. --- tests/test_paths.toml | 1318 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1294 insertions(+), 24 deletions(-) diff --git a/tests/test_paths.toml b/tests/test_paths.toml index aefcd203..4b9d280c 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -74,6 +74,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "coffee/thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "coffee/drip", @@ -94,6 +120,38 @@ code = ''' lfs_file_open(&lfs, &file, "coffee/thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -265,6 +323,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/coffee/thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/coffee/drip", @@ -285,6 +369,38 @@ code = ''' lfs_file_open(&lfs, &file, "/coffee/thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -454,6 +570,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "//////coffee//////thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/coffee/drip", @@ -474,6 +616,38 @@ code = ''' lfs_file_open(&lfs, &file, "//////coffee//////thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -668,6 +842,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "coffee/thai//////", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "coffee/drip/", @@ -682,6 +882,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/thai//////", LFS_O_RDONLY) => LFS_ERR_NOTDIR; + + lfs_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + + lfs_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; } // dir open paths, only works on dirs! @@ -949,6 +1175,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/coffee/drip", @@ -969,6 +1221,38 @@ code = ''' lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -1178,8 +1462,34 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "coffee/thai/./././././.", LFS_O_RDONLY) => LFS_ERR_ISDIR; - } else { - lfs_file_t file; + + lfs_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfs_file_t file; lfs_file_open(&lfs, &file, "coffee/drip/.", LFS_O_RDONLY) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", @@ -1192,6 +1502,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/thai/./././././.", LFS_O_RDONLY) => LFS_ERR_NOTDIR; + + lfs_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + + lfs_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; } // dir open paths, only works on dirs! @@ -1503,6 +1839,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/coffee/drip", @@ -1523,6 +1885,38 @@ code = ''' lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -1720,6 +2114,32 @@ code = ''' lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + + lfs_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + // dir open paths, only works on dirs! lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "coffee/drip/..") => 0; @@ -1923,6 +2343,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/coffee/drip", @@ -1943,6 +2389,38 @@ code = ''' lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -2113,6 +2591,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/coffee/.../thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/coffee/.../drip", @@ -2133,6 +2637,38 @@ code = ''' lfs_file_open(&lfs, &file, "/coffee/.../thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -2303,6 +2839,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "/coffee/......thai", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "/coffee/.drip", @@ -2323,19 +2885,51 @@ code = ''' lfs_file_open(&lfs, &file, "/coffee/......thai", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; - } - // dir open paths, only works on dirs! - if (DIR) { - lfs_dir_t dir; - lfs_dir_open(&lfs, &dir, "/coffee/.drip") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/coffee/..coldbrew") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/coffee/...turkish") => 0; - lfs_dir_close(&lfs, &dir) => 0; - lfs_dir_open(&lfs, &dir, "/coffee/....tubruk") => 0; - lfs_dir_close(&lfs, &dir) => 0; + lfs_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "/coffee/.drip") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/..coldbrew") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/...turkish") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "/coffee/....tubruk") => 0; + lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, "/coffee/.....vietnamese") => 0; lfs_dir_close(&lfs, &dir) => 0; lfs_dir_open(&lfs, &dir, "/coffee/......thai") => 0; @@ -2505,6 +3099,32 @@ code = ''' lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + + lfs_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + // dir open paths, only works on dirs! lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "/../coffee/drip") => LFS_ERR_INVAL; @@ -2852,6 +3472,32 @@ code = ''' lfs_file_open(&lfs, &file, "coffee_/thai", LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "_offee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "c_ffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee_/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + + lfs_file_open(&lfs, &file, "_offee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "c_ffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee_/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + // dir open paths, only works on dirs! lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "_offee/drip") => LFS_ERR_NOENT; @@ -3056,6 +3702,32 @@ code = ''' lfs_file_open(&lfs, &file, "thai/coffee", LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "drip/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "turkish/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "thai/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + + lfs_file_open(&lfs, &file, "drip/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "turkish/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfs_file_open(&lfs, &file, "thai/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + // dir open paths, only works on dirs! lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "drip/coffee") => LFS_ERR_NOTDIR; @@ -3242,6 +3914,12 @@ code = ''' lfs_file_open(&lfs, &file, "", LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + + lfs_file_open(&lfs, &file, "", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + // dir open empty, only works on dirs! lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "") => LFS_ERR_INVAL; @@ -3304,6 +3982,12 @@ code = ''' lfs_file_open(&lfs, &file, "/", LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + // dir open root, only works on dirs! lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "/") => 0; @@ -3394,6 +4078,28 @@ code = ''' lfs_file_open(&lfs, &file, "//", LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, ".", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "./", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, ".", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "./", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + // dir open root, only works on dirs! lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "/") => 0; @@ -3484,6 +4190,11 @@ code = ''' struct lfs_info info; lfs_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; + // file open littlefs, which shouldn't exist + lfs_file_t file; + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_RDONLY) => LFS_ERR_NOENT; + // dir open littlefs, which shouldn't exist lfs_dir_t dir; lfs_dir_open(&lfs, &dir, "littlefs") => LFS_ERR_NOENT; @@ -3530,11 +4241,24 @@ code = ''' lfs_file_t file; lfs_file_open(&lfs, &file, "littlefs", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "littlefs", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open littlefs, only works on dirs! @@ -3786,6 +4510,44 @@ code = ''' sprintf(path, "%s/%s", c_name, f_name); lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => LFS_ERR_ISDIR; + + sprintf(path, "%s/%s", c_name, a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, b_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, c_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, d_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, e_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, f_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + sprintf(path, "%s/%s", c_name, a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, b_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, c_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, d_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, e_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, f_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; sprintf(path, "%s/%s", c_name, a_name); @@ -3812,6 +4574,50 @@ code = ''' lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + sprintf(path, "%s/%s", c_name, a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + sprintf(path, "%s/%s", c_name, a_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, b_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, c_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, d_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, e_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, f_name); + lfs_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -3943,7 +4749,7 @@ code = ''' lfs_unmount(&lfs) => 0; ''' -# a quick utf8 test, though utf8 is easy to support +# a quick utf8 test, utf8 is easy to support [cases.test_paths_utf8] defines.DIR = [false, true] code = ''' @@ -4018,6 +4824,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "coffee/dripcoffee", @@ -4038,6 +4870,38 @@ code = ''' lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -4207,19 +5071,45 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", LFS_O_RDONLY) => LFS_ERR_ISDIR; - } else { - lfs_file_t file; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", - LFS_O_RDONLY) => 0; - lfs_file_close(&lfs, &file) => 0; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", - LFS_O_RDONLY) => 0; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_RDONLY) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", LFS_O_RDONLY) => 0; @@ -4227,6 +5117,38 @@ code = ''' lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -4396,6 +5318,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "c o f f e e/t h a i", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "c o f f e e/d r i p", @@ -4416,6 +5364,38 @@ code = ''' lfs_file_open(&lfs, &file, "c o f f e e/t h a i", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -4587,6 +5567,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, " / ", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, " / ", @@ -4607,6 +5613,38 @@ code = ''' lfs_file_open(&lfs, &file, " / ", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -4778,6 +5816,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "\x0c/\x06", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "\x0c/\x01", @@ -4798,6 +5862,38 @@ code = ''' lfs_file_open(&lfs, &file, "\x0c/\x06", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -4969,6 +6065,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "\x7f/\x7f", @@ -4989,6 +6111,38 @@ code = ''' lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -5162,6 +6316,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "\xc0/\xf0", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "\xc0/\xa0", @@ -5182,6 +6362,38 @@ code = ''' lfs_file_open(&lfs, &file, "\xc0/\xf0", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! @@ -5355,6 +6567,32 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_ISDIR; lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } else { lfs_file_t file; lfs_file_open(&lfs, &file, "\xff/\xff", @@ -5375,6 +6613,38 @@ code = ''' lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", LFS_O_RDONLY) => 0; lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfs_file_close(&lfs, &file) => 0; + + lfs_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfs_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; } // dir open paths, only works on dirs! From b735c8fd7f948e4db34f063c52086b802d095f28 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 25 Nov 2024 15:16:01 -0600 Subject: [PATCH 23/28] paths: Added tests over NOENT + trailing slash/dot - test_paths_noent_trailing_slashes - test_paths_noent_trailing_dots - test_paths_noent_trailing_dotdots These managed to slip through our path testing but should be tested, if anything just to know exactly what errors these return. --- tests/test_paths.toml | 682 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 670 insertions(+), 12 deletions(-) diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 4b9d280c..d8ae57f9 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -3198,23 +3198,23 @@ code = ''' // here's a weird one, what happens if our rename is also a noop? lfs_rename(&lfs, - "/../coffee/drip", - "/../espresso/espresso") => LFS_ERR_INVAL; + "/no/../../../../coffee/drip", + "/no/../../../../coffee/drip") => LFS_ERR_INVAL; lfs_rename(&lfs, - "/../../coffee/coldbrew", - "/../../espresso/americano") => LFS_ERR_INVAL; + "/no/../../../coffee/coldbrew", + "/no/../../../coffee/coldbrew") => LFS_ERR_INVAL; lfs_rename(&lfs, - "/../../../coffee/turkish", - "/../../../espresso/macchiato") => LFS_ERR_INVAL; + "/no/../../coffee/turkish", + "/no/../../coffee/turkish") => LFS_ERR_INVAL; lfs_rename(&lfs, - "/no/../../coffee/tubruk", - "/no/../../espresso/latte") => LFS_ERR_INVAL; + "/../../../coffee/tubruk", + "/../../../coffee/tubruk") => LFS_ERR_INVAL; lfs_rename(&lfs, - "/no/../../../coffee/vietnamese", - "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; + "/../../coffee/vietnamese", + "/../../coffee/vietnamese") => LFS_ERR_INVAL; lfs_rename(&lfs, - "/no/../../../../coffee/thai", - "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; + "/../coffee/thai", + "/../coffee/thai") => LFS_ERR_INVAL; // remove paths lfs_remove(&lfs, "/../espresso/espresso") => LFS_ERR_INVAL; @@ -3347,6 +3347,26 @@ code = ''' "coffee/thai_", "espresso/mocha") => LFS_ERR_NOENT; + // here's a weird one, what happens if our rename is also a noop? + lfs_rename(&lfs, + "coffee/_rip", + "coffee/_rip") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew", + "coffee/c_ldbrew") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish", + "coffee/tu_kish") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk", + "coffee/tub_uk") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese", + "coffee/_vietnamese") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_", + "coffee/thai_") => LFS_ERR_NOENT; + // remove paths lfs_remove(&lfs, "coffee/_rip") => LFS_ERR_NOENT; lfs_remove(&lfs, "coffee/c_ldbrew") => LFS_ERR_NOENT; @@ -3888,6 +3908,644 @@ code = ''' lfs_unmount(&lfs) => 0; ''' +# noent tests with trailing slashes +[cases.test_paths_noent_trailing_slashes] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "coffee/_rip//////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/c_ldbrew/////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tu_kish////", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tub_uk///", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/_vietnamese//", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/thai_/", &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/_rip/", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew//", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tu_kish///", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tub_uk////", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/_vietnamese/////", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/thai_//////", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + lfs_file_open(&lfs, &file, "coffee/_rip/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tu_kish///", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tub_uk////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/_vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai_//////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfs_file_open(&lfs, &file, "coffee/_rip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tu_kish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tub_uk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/_vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/thai_//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + + // dir open paths, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/_rip/") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/c_ldbrew//") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/tu_kish///") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/tub_uk////") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/_vietnamese/////") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/thai_//////") => LFS_ERR_NOENT; + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + // bad source + lfs_rename(&lfs, + "coffee/_rip//////", + "espresso/espresso") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew/////", + "espresso/americano") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish////", + "espresso/macchiato") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk///", + "espresso/latte") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese//", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_/", + "espresso/mocha") => LFS_ERR_NOENT; + + // bad destination + lfs_rename(&lfs, + "coffee/_rip", + "espresso/espresso/") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano//") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato///") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk", + "espresso/latte////") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino/////") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_", + "espresso/mocha//////") => LFS_ERR_NOENT; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/_rip//////", + "espresso/espresso/") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew/////", + "espresso/americano//") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish////", + "espresso/macchiato///") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk///", + "espresso/latte////") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese//", + "espresso/cappuccino/////") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_/", + "espresso/mocha//////") => LFS_ERR_NOENT; + + // here's a weird one, what happens if our rename is also a noop? + lfs_rename(&lfs, + "coffee/_rip//////", + "coffee/_rip//////") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew/////", + "coffee/c_ldbrew/////") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish////", + "coffee/tu_kish////") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk///", + "coffee/tub_uk///") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese//", + "coffee/_vietnamese//") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_/", + "coffee/thai_/") => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "coffee/_rip/") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/c_ldbrew//") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/tu_kish///") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/tub_uk////") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/_vietnamese/////") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/thai_//////") => LFS_ERR_NOENT; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_unmount(&lfs) => 0; +''' + +# noent tests with trailing dots +[cases.test_paths_noent_trailing_dots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "coffee/_rip/./././././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/c_ldbrew/././././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tu_kish/./././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/tub_uk/././.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/_vietnamese/./.", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "coffee/thai_/.", &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/_rip/.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew/./.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tu_kish/././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tub_uk/./././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/_vietnamese/././././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/thai_/./././././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + lfs_file_open(&lfs, &file, "coffee/_rip/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tu_kish/././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tub_uk/./././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/_vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/thai_/./././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + + lfs_file_open(&lfs, &file, "coffee/_rip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tu_kish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/tub_uk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/_vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfs_file_open(&lfs, &file, "coffee/thai_/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/_rip/.") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/c_ldbrew/./.") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/tu_kish/././.") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/tub_uk/./././.") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/_vietnamese/././././.") => LFS_ERR_NOENT; + lfs_dir_open(&lfs, &dir, "coffee/thai_/./././././.") => LFS_ERR_NOENT; + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + // bad source + lfs_rename(&lfs, + "coffee/_rip/./././././.", + "espresso/espresso") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew/././././.", + "espresso/americano") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish/./././.", + "espresso/macchiato") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk/././.", + "espresso/latte") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese/./.", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_/.", + "espresso/mocha") => LFS_ERR_NOENT; + + // bad destination + lfs_rename(&lfs, + "coffee/_rip", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/_rip/./././././.", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew/././././.", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish/./././.", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk/././.", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese/./.", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_/.", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // here's a weird one, what happens if our rename is also a noop? + lfs_rename(&lfs, + "coffee/_rip/./././././.", + "coffee/_rip/./././././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew/././././.", + "coffee/c_ldbrew/././././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish/./././.", + "coffee/tu_kish/./././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk/././.", + "coffee/tub_uk/././.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese/./.", + "coffee/_vietnamese/./.") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_/.", + "coffee/thai_/.") => LFS_ERR_NOENT; + + // remove paths + lfs_remove(&lfs, "coffee/_rip/.") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/c_ldbrew/./.") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/tu_kish/././.") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/tub_uk/./././.") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/_vietnamese/././././.") => LFS_ERR_NOENT; + lfs_remove(&lfs, "coffee/thai_/./././././.") => LFS_ERR_NOENT; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_unmount(&lfs) => 0; +''' + +# noent tests with trailing dotdots +[cases.test_paths_noent_trailing_dotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfs_format(&lfs, cfg) => 0; + lfs_mount(&lfs, cfg) => 0; + + // create paths + lfs_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfs_mkdir(&lfs, "coffee/drip") => 0; + lfs_mkdir(&lfs, "coffee/coldbrew") => 0; + lfs_mkdir(&lfs, "coffee/turkish") => 0; + lfs_mkdir(&lfs, "coffee/tubruk") => 0; + lfs_mkdir(&lfs, "coffee/vietnamese") => 0; + lfs_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + lfs_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfs_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfs_stat(&lfs, "coffee/_rip/../../../../../..", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "coffee/c_ldbrew/../../../../..", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "coffee/tu_kish/../../../..", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "coffee/tub_uk/../../..", &info) => LFS_ERR_INVAL; + lfs_stat(&lfs, "coffee/_vietnamese/../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfs_stat(&lfs, "coffee/thai_/..", &info) => 0; + assert(strcmp(info.name, "coffee") == 0); + assert(info.type == LFS_TYPE_DIR); + + // file open paths, only works on files! + lfs_file_t file; + lfs_file_open(&lfs, &file, "coffee/_rip/..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/c_ldbrew/../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfs_file_open(&lfs, &file, "coffee/tu_kish/../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/tub_uk/../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/_vietnamese/../../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfs_file_open(&lfs, &file, "coffee/thai_/../../../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + + // dir open paths, only works on dirs! + lfs_dir_t dir; + lfs_dir_open(&lfs, &dir, "coffee/_rip/..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/c_ldbrew/../..") => 0; + lfs_dir_close(&lfs, &dir) => 0; + lfs_dir_open(&lfs, &dir, "coffee/tu_kish/../../..") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "coffee/tub_uk/../../../..") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "coffee/_vietnamese/../../../../..") => LFS_ERR_INVAL; + lfs_dir_open(&lfs, &dir, "coffee/thai_/../../../../../..") => LFS_ERR_INVAL; + + // rename paths + lfs_mkdir(&lfs, "espresso") => 0; + // bad source + lfs_rename(&lfs, + "coffee/_rip/../../../../../..", + "espresso/espresso") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/c_ldbrew/../../../../..", + "espresso/americano") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tu_kish/../../../..", + "espresso/macchiato") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tub_uk/../../..", + "espresso/latte") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/_vietnamese/../..", + "espresso/cappuccino") => LFS_ERR_INVAL; + // this one works + lfs_rename(&lfs, + "coffee/thai_/..", + "espresso/mocha") => 0; + lfs_rename(&lfs, + "espresso/mocha", + "coffee") => 0; + + // bad destination + lfs_rename(&lfs, + "coffee/_rip", + "espresso/espresso/..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano/../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato/../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/tub_uk", + "espresso/latte/../../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino/../../../../..") => LFS_ERR_NOENT; + lfs_rename(&lfs, + "coffee/thai_", + "espresso/mocha/../../../../../..") => LFS_ERR_NOENT; + + // bad source and bad destination + lfs_rename(&lfs, + "coffee/_rip/../../../../../..", + "espresso/espresso/..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/c_ldbrew/../../../../..", + "espresso/americano/../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tu_kish/../../../..", + "espresso/macchiato/../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tub_uk/../../..", + "espresso/latte/../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/_vietnamese/../..", + "espresso/cappuccino/../../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/thai_/..", + "espresso/mocha/../../../../../..") => LFS_ERR_INVAL; + + // here's a weird one, what happens if our rename is also a noop? + lfs_rename(&lfs, + "coffee/_rip/../../../../../..", + "coffee/_rip/../../../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/c_ldbrew/../../../../..", + "coffee/c_ldbrew/../../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tu_kish/../../../..", + "coffee/tu_kish/../../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/tub_uk/../../..", + "coffee/tub_uk/../../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/_vietnamese/../..", + "coffee/_vietnamese/../..") => LFS_ERR_INVAL; + lfs_rename(&lfs, + "coffee/thai_/..", + "coffee/thai_/..") => 0; + + // remove paths + lfs_remove(&lfs, "coffee/_rip/..") => LFS_ERR_NOTEMPTY; + lfs_remove(&lfs, "coffee/c_ldbrew/../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/tu_kish/../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/tub_uk/../../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/_vietnamese/../../../../..") => LFS_ERR_INVAL; + lfs_remove(&lfs, "coffee/thai_/../../../../../..") => LFS_ERR_INVAL; + + // stat paths + lfs_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfs_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfs_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfs_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfs_unmount(&lfs) => 0; +''' + # test an empty path, this should error [cases.test_paths_empty] defines.DIR = [false, true] From 999ef6656f13eeaa0de7f7d880ba6d1937aa60dd Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 25 Nov 2024 15:22:33 -0600 Subject: [PATCH 24/28] paths: Changed CREAT with a trailing slash to return NOTDIR - before: lfs_file_open("missing/") => LFS_ERR_ISDIR - after: lfs_file_open("missing/") => LFS_ERR_NOTDIR As noted by bmcdonnell-fb, returning LFS_ERR_ISDIR here was inconsistent with the case where the file exists: case before after lfs_file_open("dir_a") => LFS_ERR_ISDIR LFS_ERR_ISDIR lfs_file_open("dir_a/") => LFS_ERR_ISDIR LFS_ERR_ISDIR lfs_file_open("reg_a/") => LFS_ERR_NOTDIR LFS_ERR_NOTDIR lfs_file_open("missing_a/") => LFS_ERR_ISDIR LFS_ERR_NOTDIR Note this is consistent with the behavior of lfs_stat: lfs_file_open("reg_a/") => LFS_ERR_NOTDIR lfs_stat("reg_a/") => LFS_ERR_NOTDIR And the only other function that can "create" files, lfs_rename: lfs_file_open("missing_a/") => LFS_ERR_NOTDIR lfs_rename("reg_a", "missing_a/") => LFS_ERR_NOTDIR There is some ongoing discussion about if these should return NOTDIR, ISDIR, or INVAL, but this is at least an improvement over the rename/open mismatch. --- lfs.c | 2 +- tests/test_paths.toml | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lfs.c b/lfs.c index 94d23f7b..b46cca5b 100644 --- a/lfs.c +++ b/lfs.c @@ -3109,7 +3109,7 @@ static int lfs_file_opencfg_(lfs_t *lfs, lfs_file_t *file, // don't allow trailing slashes if (lfs_path_isdir(path)) { - err = LFS_ERR_ISDIR; + err = LFS_ERR_NOTDIR; goto cleanup; } diff --git a/tests/test_paths.toml b/tests/test_paths.toml index d8ae57f9..29574fa1 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -764,17 +764,17 @@ code = ''' } else { lfs_file_t file; lfs_file_open(&lfs, &file, "coffee/drip/", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/coldbrew//", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/turkish///", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/tubruk////", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/vietnamese/////", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/thai//////", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; // still create so we have something to test lfs_file_open(&lfs, &file, "coffee/drip", @@ -3972,30 +3972,30 @@ code = ''' LFS_O_RDONLY) => LFS_ERR_NOENT; lfs_file_open(&lfs, &file, "coffee/_rip/", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/c_ldbrew//", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/tu_kish///", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/tub_uk////", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/_vietnamese/////", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/thai_//////", - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/_rip/", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/c_ldbrew//", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/tu_kish///", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/tub_uk////", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/_vietnamese/////", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; lfs_file_open(&lfs, &file, "coffee/thai_//////", - LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_ISDIR; + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; // dir open paths, only works on dirs! lfs_dir_t dir; From 215613e41fcbf859597d46e60ea2f6e1454421ee Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 9 Dec 2024 14:56:12 -0600 Subject: [PATCH 25/28] gha: Fixed x86-only statuses Looks like I missed a line during refactoring, resulted in only x86 sizes being reported in GitHub statuses. If we wanted to limited these to one architecture, thumb would have probably been a better pick. --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 48d00eff..73e5aa6d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -273,7 +273,6 @@ jobs: }' | tee status/$(basename $f .csv).json done - name: upload-status-sizes - if: ${{matrix.arch == 'x86_64'}} uses: actions/upload-artifact@v4 with: name: status-sizes-${{matrix.arch}} From 469c863c18b99bf17470e1c066252d43bfaa3e14 Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Tue, 10 Dec 2024 00:17:43 +0800 Subject: [PATCH 26/28] Assert on NULL IO function --- lfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lfs.c b/lfs.c index 9e7fff7f..e92381ae 100644 --- a/lfs.c +++ b/lfs.c @@ -4217,6 +4217,14 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { // which littlefs currently does not support LFS_ASSERT((bool)0x80000000); + // check that the required io functions are provided + LFS_ASSERT(lfs->cfg->read != NULL); +#ifndef LFS_READONLY + LFS_ASSERT(lfs->cfg->prog != NULL); + LFS_ASSERT(lfs->cfg->erase != NULL); + LFS_ASSERT(lfs->cfg->sync != NULL); +#endif + // validate that the lfs-cfg sizes were initiated properly before // performing any arithmetic logics with them LFS_ASSERT(lfs->cfg->read_size != 0); From dae656aa53cfab693f3013a6be6b051c2b20543d Mon Sep 17 00:00:00 2001 From: Dong Wang Date: Tue, 10 Dec 2024 01:21:59 +0800 Subject: [PATCH 27/28] Fix prettyasserts.py for pointer asserts --- scripts/prettyasserts.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/scripts/prettyasserts.py b/scripts/prettyasserts.py index 3a62d360..925c14f0 100755 --- a/scripts/prettyasserts.py +++ b/scripts/prettyasserts.py @@ -86,6 +86,13 @@ def write_header(f, limit=LIMIT): f.writeln("}") f.writeln() 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(" const void *v, size_t size) {") f.writeln(" const uint8_t *v_ = v;") @@ -183,6 +190,23 @@ def write_header(f, limit=LIMIT): f.writeln(" _rh, strlen(_rh)); \\") f.writeln(" } \\") 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() @@ -301,6 +325,8 @@ def p_assert(p): cmp = p.expect('cmp') ; p.accept('ws') rh = p_expr(p) ; p.accept('ws') p.expect(')') + if rh == 'NULL' or lh == 'NULL': + return mkassert('ptr', CMP[cmp], lh, rh) return mkassert('int', CMP[cmp], lh, rh) except ParseFailure: p.pop(state) From 3d0386489b0a6f7fd1986e4ca4f60c49f9186401 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 11 Dec 2024 16:23:10 -0600 Subject: [PATCH 28/28] Bumped minor version to v2.10 --- lfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lfs.h b/lfs.h index 84738973..45315603 100644 --- a/lfs.h +++ b/lfs.h @@ -21,7 +21,7 @@ extern "C" // Software library version // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions -#define LFS_VERSION 0x00020009 +#define LFS_VERSION 0x0002000a #define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16)) #define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))