littlefs-python 0.13.3__tar.gz → 0.15.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.github/workflows/deploy.yml +25 -15
  2. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.github/workflows/run-tests.yml +3 -3
  3. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/PKG-INFO +3 -1
  4. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/README.rst +2 -0
  5. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/.github/workflows/test.yml +19 -8
  6. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/Makefile +11 -1
  7. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/README.md +6 -1
  8. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/lfs.c +62 -31
  9. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/lfs.h +6 -2
  10. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/lfs_util.h +10 -10
  11. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/runners/bench_runner.c +5 -0
  12. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/runners/test_runner.c +5 -0
  13. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/bench.py +4 -1
  14. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/changeprefix.py +1 -1
  15. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/test.py +4 -1
  16. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_orphans.toml +68 -1
  17. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_relocations.toml +168 -0
  18. littlefs_python-0.15.0/littlefs/tests/test_shrink.toml +109 -0
  19. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_superblocks.toml +108 -0
  20. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/lfs.c +11192 -13089
  21. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/lfs.pxd +3 -0
  22. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs_python.egg-info/PKG-INFO +3 -1
  23. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs_python.egg-info/SOURCES.txt +1 -0
  24. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_version.py +1 -1
  25. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.gitattributes +0 -0
  26. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.github/dependabot.yml +0 -0
  27. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.gitignore +0 -0
  28. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.gitmodules +0 -0
  29. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.pre-commit-config.yaml +0 -0
  30. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/.readthedocs.yml +0 -0
  31. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/LICENSE +0 -0
  32. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/MANIFEST.in +0 -0
  33. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/ci/build-wheels.sh +0 -0
  34. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/ci/download_release_files.py +0 -0
  35. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/Makefile +0 -0
  36. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/api/index.rst +0 -0
  37. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/cli.rst +0 -0
  38. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/conf.py +0 -0
  39. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/doc8.ini +0 -0
  40. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/examples/index.rst +0 -0
  41. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/index.rst +0 -0
  42. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/make.bat +0 -0
  43. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/requirements.txt +0 -0
  44. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/docs/usage.rst +0 -0
  45. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/examples/mkfsimg.py +0 -0
  46. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/examples/walk.py +0 -0
  47. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/.git +0 -0
  48. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/.gitattributes +0 -0
  49. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/.github/workflows/post-release.yml +0 -0
  50. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/.github/workflows/release.yml +0 -0
  51. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/.github/workflows/status.yml +0 -0
  52. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/.gitignore +0 -0
  53. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/DESIGN.md +0 -0
  54. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/LICENSE.md +0 -0
  55. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/SPEC.md +0 -0
  56. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/bd/lfs_emubd.c +0 -0
  57. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/bd/lfs_emubd.h +0 -0
  58. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/bd/lfs_filebd.c +0 -0
  59. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/bd/lfs_filebd.h +0 -0
  60. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/bd/lfs_rambd.c +0 -0
  61. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/bd/lfs_rambd.h +0 -0
  62. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/benches/bench_dir.toml +0 -0
  63. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/benches/bench_file.toml +0 -0
  64. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/benches/bench_superblock.toml +0 -0
  65. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/lfs_util.c +0 -0
  66. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/runners/bench_runner.h +0 -0
  67. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/runners/test_runner.h +0 -0
  68. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/code.py +0 -0
  69. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/cov.py +0 -0
  70. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/data.py +0 -0
  71. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/perf.py +0 -0
  72. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/perfbd.py +0 -0
  73. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/plot.py +0 -0
  74. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/plotmpl.py +0 -0
  75. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/prettyasserts.py +0 -0
  76. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/readblock.py +0 -0
  77. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/readmdir.py +0 -0
  78. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/readtree.py +0 -0
  79. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/stack.py +0 -0
  80. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/structs.py +0 -0
  81. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/summary.py +0 -0
  82. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/tailpipe.py +0 -0
  83. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/teepipe.py +0 -0
  84. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/tracebd.py +0 -0
  85. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/scripts/watch.py +0 -0
  86. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_alloc.toml +0 -0
  87. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_attrs.toml +0 -0
  88. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_badblocks.toml +0 -0
  89. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_bd.toml +0 -0
  90. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_compat.toml +0 -0
  91. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_dirs.toml +0 -0
  92. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_entries.toml +0 -0
  93. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_evil.toml +0 -0
  94. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_exhaustion.toml +0 -0
  95. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_files.toml +0 -0
  96. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_interspersed.toml +0 -0
  97. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_move.toml +0 -0
  98. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_paths.toml +0 -0
  99. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_powerloss.toml +0 -0
  100. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_seek.toml +0 -0
  101. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/littlefs/tests/test_truncate.toml +0 -0
  102. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/mypy.ini +0 -0
  103. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/pyproject.toml +0 -0
  104. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/requirements.txt +0 -0
  105. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/setup.cfg +0 -0
  106. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/setup.py +0 -0
  107. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/__init__.py +0 -0
  108. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/__main__.py +0 -0
  109. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/context.py +0 -0
  110. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/errors.py +0 -0
  111. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/lfs.pyi +0 -0
  112. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/lfs.pyx +0 -0
  113. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs/py.typed +0 -0
  114. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs_python.egg-info/dependency_links.txt +0 -0
  115. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs_python.egg-info/entry_points.txt +0 -0
  116. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs_python.egg-info/not-zip-safe +0 -0
  117. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs_python.egg-info/requires.txt +0 -0
  118. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/src/littlefs_python.egg-info/top_level.txt +0 -0
  119. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/lfs/conftest.py +0 -0
  120. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/lfs/test_dir_functions.py +0 -0
  121. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/lfs/test_file_functions.py +0 -0
  122. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/lfs/test_fs_functions.py +0 -0
  123. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_attr.py +0 -0
  124. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_block_count.py +0 -0
  125. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_directories.py +0 -0
  126. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_files.py +0 -0
  127. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_grow.py +0 -0
  128. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_multiversion.py +0 -0
  129. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_name_max.py +0 -0
  130. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_remove_rename.py +0 -0
  131. {littlefs_python-0.13.3 → littlefs_python-0.15.0}/test/test_walk.py +0 -0
@@ -1,6 +1,13 @@
1
1
  name: Build and Deploy Package
2
2
 
3
- on: workflow_dispatch
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ upload_to_pypi:
7
+ description: 'Upload to PyPI after building'
8
+ required: true
9
+ default: false
10
+ type: boolean
4
11
 
5
12
  jobs:
6
13
  build_wheels:
@@ -11,14 +18,15 @@ jobs:
11
18
  os: [ubuntu-22.04, macos-13, windows-latest]
12
19
 
13
20
  env:
14
- CIBW_BUILD: "cp37-* cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* pp37-* pp38-* pp39-* pp310-*"
15
- CIBW_SKIP: "cp36-* pp* *-win_arm64 *-musllinux_aarch64"
21
+ CIBW_BUILD: "cp38-* cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*"
22
+ CIBW_SKIP: "*-win_arm64 *-musllinux_aarch64"
16
23
  CIBW_ARCHS_LINUX: "x86_64 i686 aarch64"
17
24
 
18
25
  steps:
19
- - uses: actions/checkout@v4
26
+ - uses: actions/checkout@v5
20
27
  with:
21
28
  submodules: "recursive"
29
+ fetch-depth: 0
22
30
 
23
31
  - name: Setup QEMU # Needed to build aarch64 wheels
24
32
  if: runner.os == 'Linux'
@@ -27,9 +35,9 @@ jobs:
27
35
  platforms: all
28
36
 
29
37
  - name: Build wheels
30
- uses: pypa/cibuildwheel@v2.23.1
38
+ uses: pypa/cibuildwheel@v3.2.1
31
39
 
32
- - uses: actions/upload-artifact@v4
40
+ - uses: actions/upload-artifact@v5
33
41
  with:
34
42
  name: wheels-${{ matrix.os }}
35
43
  path: ./wheelhouse/*.whl
@@ -43,15 +51,16 @@ jobs:
43
51
  cibw_archs: ["arm64"]
44
52
 
45
53
  steps:
46
- - uses: actions/checkout@v4
54
+ - uses: actions/checkout@v5
47
55
  with:
48
56
  submodules: "recursive"
57
+ fetch-depth: 0
49
58
 
50
59
  - name: Build wheels
51
- uses: pypa/cibuildwheel@v2.23.1
60
+ uses: pypa/cibuildwheel@v3.2.1
52
61
  env:
53
62
  CIBW_BUILD: ${{ matrix.cibw_build }}
54
- CIBW_SKIP: "cp36-* pp*"
63
+ CIBW_SKIP: "pp*"
55
64
  CIBW_ARCHS: ${{ matrix.cibw_archs }}
56
65
  CIBW_REPAIR_WHEEL_COMMAND: |
57
66
  echo "Target delocate archs: {delocate_archs}"
@@ -75,7 +84,7 @@ jobs:
75
84
  delocate-listdeps --all {dest_dir}/$WHEEL_SIMPLE_FILENAME
76
85
 
77
86
  echo "DONE."
78
- - uses: actions/upload-artifact@v4
87
+ - uses: actions/upload-artifact@v5
79
88
  with:
80
89
  name: wheels-macos-arm64
81
90
  path: ./wheelhouse/*.whl
@@ -84,16 +93,17 @@ jobs:
84
93
  name: Build source distribution
85
94
  runs-on: ubuntu-22.04
86
95
  steps:
87
- - uses: actions/checkout@v4
96
+ - uses: actions/checkout@v5
88
97
  with:
89
98
  submodules: "recursive"
99
+ fetch-depth: 0
90
100
 
91
101
  - name: Build sdist
92
102
  run: |
93
103
  pip install build
94
104
  python -m build . --sdist
95
105
 
96
- - uses: actions/upload-artifact@v4
106
+ - uses: actions/upload-artifact@v5
97
107
  with:
98
108
  name: wheels-sdist
99
109
  path: dist/*.tar.gz
@@ -101,15 +111,15 @@ jobs:
101
111
  upload_pypi:
102
112
  needs: [build_wheels, build_wheels_macos_arm64, build_sdist]
103
113
  runs-on: ubuntu-22.04
104
- # if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/')
114
+ if: ${{ inputs.upload_to_pypi }}
105
115
  steps:
106
- - uses: actions/download-artifact@v4
116
+ - uses: actions/download-artifact@v6
107
117
  with:
108
118
  path: dist
109
119
  pattern: wheels-*
110
120
  merge-multiple: true
111
121
 
112
- - uses: pypa/gh-action-pypi-publish@v1.12.4
122
+ - uses: pypa/gh-action-pypi-publish@v1.13.0
113
123
  with:
114
124
  user: __token__
115
125
  password: ${{ secrets.pypi_api_token }}
@@ -15,14 +15,14 @@ jobs:
15
15
  strategy:
16
16
  matrix:
17
17
  os: [ubuntu-22.04, macos-13, windows-latest]
18
- python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
18
+ python-version: [3.8, 3.9, "3.10", "3.11", "3.12", "3.13", "3.14"]
19
19
 
20
20
  steps:
21
- - uses: actions/checkout@v4
21
+ - uses: actions/checkout@v5
22
22
  with:
23
23
  submodules: "recursive"
24
24
  - name: Set up Python ${{ matrix.python-version }}
25
- uses: actions/setup-python@v5
25
+ uses: actions/setup-python@v6
26
26
  with:
27
27
  python-version: ${{ matrix.python-version }}
28
28
  - name: Install dependencies
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: littlefs-python
3
- Version: 0.13.3
3
+ Version: 0.15.0
4
4
  Summary: A python wrapper for littlefs
5
5
  Home-page: https://github.com/jrast/littlefs-python
6
6
  Author: Jürg Rast
@@ -103,6 +103,8 @@ from scratch the latest version is recommended.
103
103
  .. csv-table::
104
104
  :header: "LittleFS Version", "Package Version", "LittleFS File System Version"
105
105
 
106
+ 2.11.2, v0.15.X, 2.0 / 2.1 [#f1]_
107
+ 2.11.0, v0.14.X, 2.0 / 2.1 [#f1]_
106
108
  2.10.0, v0.13.X, 2.0 / 2.1 [#f1]_
107
109
  2.9.0, v0.12.X v0.11.X, 2.0 / 2.1 [#f1]_
108
110
  2.9.0, v0.10.X, 2.0 / 2.1 [#f1]_
@@ -70,6 +70,8 @@ from scratch the latest version is recommended.
70
70
  .. csv-table::
71
71
  :header: "LittleFS Version", "Package Version", "LittleFS File System Version"
72
72
 
73
+ 2.11.2, v0.15.X, 2.0 / 2.1 [#f1]_
74
+ 2.11.0, v0.14.X, 2.0 / 2.1 [#f1]_
73
75
  2.10.0, v0.13.X, 2.0 / 2.1 [#f1]_
74
76
  2.9.0, v0.12.X v0.11.X, 2.0 / 2.1 [#f1]_
75
77
  2.9.0, v0.10.X, 2.0 / 2.1 [#f1]_
@@ -374,6 +374,22 @@ jobs:
374
374
  run: |
375
375
  CFLAGS="$CFLAGS -DLFS_NO_INTRINSICS" make test
376
376
 
377
+ test-shrink:
378
+ runs-on: ubuntu-latest
379
+ steps:
380
+ - uses: actions/checkout@v4
381
+ - name: install
382
+ run: |
383
+ # need a few things
384
+ sudo apt-get update -qq
385
+ sudo apt-get install -qq gcc python3 python3-pip
386
+ pip3 install toml
387
+ gcc --version
388
+ python3 --version
389
+ - name: test-no-intrinsics
390
+ run: |
391
+ CFLAGS="$CFLAGS -DLFS_SHRINKNONRELOCATING" make test
392
+
377
393
  # run with all trace options enabled to at least make sure these
378
394
  # all compile
379
395
  test-yes-trace:
@@ -454,8 +470,7 @@ jobs:
454
470
  TESTFLAGS="$TESTFLAGS --valgrind --context=1024 -Gdefault -Pnone" \
455
471
  make test
456
472
 
457
- # test that compilation is warning free under clang
458
- # run with Clang, mostly to check for Clang-specific warnings
473
+ # compile/run with Clang, mostly to check for Clang-specific warnings
459
474
  test-clang:
460
475
  runs-on: ubuntu-latest
461
476
  steps:
@@ -469,12 +484,8 @@ jobs:
469
484
  python3 --version
470
485
  - name: test-clang
471
486
  run: |
472
- # override CFLAGS since Clang does not support -fcallgraph-info
473
- # and -ftrack-macro-expansions
474
- make \
475
- CC=clang \
476
- CFLAGS="$CFLAGS -MMD -g3 -I. -std=c99 -Wall -Wextra -pedantic" \
477
- test
487
+ CC=clang \
488
+ make test
478
489
 
479
490
  # run benchmarks
480
491
  #
@@ -18,6 +18,12 @@ VALGRIND ?= valgrind
18
18
  GDB ?= gdb
19
19
  PERF ?= perf
20
20
 
21
+ # guess clang or gcc (clang sometimes masquerades as gcc because of
22
+ # course it does)
23
+ ifneq ($(shell $(CC) --version | grep clang),)
24
+ NO_GCC = 1
25
+ endif
26
+
21
27
  SRC ?= $(filter-out $(wildcard *.t.* *.b.*),$(wildcard *.c))
22
28
  OBJ := $(SRC:%.c=$(BUILDDIR)/%.o)
23
29
  DEP := $(SRC:%.c=$(BUILDDIR)/%.d)
@@ -59,12 +65,15 @@ BENCH_PERF := $(BENCH_RUNNER:%=%.perf)
59
65
  BENCH_TRACE := $(BENCH_RUNNER:%=%.trace)
60
66
  BENCH_CSV := $(BENCH_RUNNER:%=%.csv)
61
67
 
62
- CFLAGS += -fcallgraph-info=su
63
68
  CFLAGS += -g3
64
69
  CFLAGS += -I.
65
70
  CFLAGS += -std=c99 -Wall -Wextra -pedantic
66
71
  CFLAGS += -Wmissing-prototypes
72
+ ifndef NO_GCC
73
+ CFLAGS += -fcallgraph-info=su
67
74
  CFLAGS += -ftrack-macro-expansion=0
75
+ endif
76
+
68
77
  ifdef DEBUG
69
78
  CFLAGS += -O0
70
79
  else
@@ -466,6 +475,7 @@ benchmarks-diff: $(BENCH_CSV)
466
475
  # rules
467
476
  -include $(DEP)
468
477
  -include $(TEST_DEP)
478
+ -include $(BENCH_DEP)
469
479
  .SUFFIXES:
470
480
  .SECONDARY:
471
481
 
@@ -267,7 +267,11 @@ License Identifiers that are here available: http://spdx.org/licenses/
267
267
  to create images of the filesystem on your PC. Check if littlefs will fit
268
268
  your needs, create images for a later download to the target memory or
269
269
  inspect the content of a binary image of the target memory.
270
-
270
+
271
+ - [littlefs-toy] - A command-line tool for creating and working with littlefs
272
+ images. Uses syntax similar to tar command for ease of use. Supports working
273
+ on littlefs images embedded inside another file (firmware image, etc).
274
+
271
275
  - [littlefs2-rust] - A Rust wrapper for littlefs. This project allows you
272
276
  to use littlefs in a Rust-friendly API, reaping the benefits of Rust's memory
273
277
  safety and other guarantees.
@@ -321,6 +325,7 @@ License Identifiers that are here available: http://spdx.org/licenses/
321
325
  [littlefs-js]: https://github.com/geky/littlefs-js
322
326
  [littlefs-js-demo]:http://littlefs.geky.net/demo.html
323
327
  [littlefs-python]: https://pypi.org/project/littlefs-python/
328
+ [littlefs-toy]: https://github.com/tjko/littlefs-toy
324
329
  [littlefs2-rust]: https://crates.io/crates/littlefs2
325
330
  [nim-littlefs]: https://github.com/Graveflo/nim-littlefs
326
331
  [chamelon]: https://github.com/yomimono/chamelon
@@ -93,6 +93,7 @@ static int lfs_bd_read(lfs_t *lfs,
93
93
  // bypass cache?
94
94
  diff = lfs_aligndown(diff, lfs->cfg->read_size);
95
95
  int err = lfs->cfg->read(lfs->cfg, block, off, data, diff);
96
+ LFS_ASSERT(err <= 0);
96
97
  if (err) {
97
98
  return err;
98
99
  }
@@ -739,6 +740,7 @@ static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir,
739
740
  int err = lfs_bd_read(lfs,
740
741
  NULL, &lfs->rcache, sizeof(ntag),
741
742
  dir->pair[0], off, &ntag, sizeof(ntag));
743
+ LFS_ASSERT(err <= 0);
742
744
  if (err) {
743
745
  return err;
744
746
  }
@@ -767,6 +769,7 @@ static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir,
767
769
  err = lfs_bd_read(lfs,
768
770
  NULL, &lfs->rcache, diff,
769
771
  dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff);
772
+ LFS_ASSERT(err <= 0);
770
773
  if (err) {
771
774
  return err;
772
775
  }
@@ -828,9 +831,6 @@ static int lfs_dir_getread(lfs_t *lfs, const lfs_mdir_t *dir,
828
831
  size -= diff;
829
832
  continue;
830
833
  }
831
-
832
- // rcache takes priority
833
- diff = lfs_min(diff, rcache->off-off);
834
834
  }
835
835
 
836
836
  // load to cache, first condition can no longer fail
@@ -1282,6 +1282,7 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
1282
1282
  if (err == LFS_ERR_CORRUPT) {
1283
1283
  break;
1284
1284
  }
1285
+ return err;
1285
1286
  }
1286
1287
 
1287
1288
  lfs_fcrc_fromle32(&fcrc);
@@ -2267,7 +2268,7 @@ static int lfs_dir_relocatingcommit(lfs_t *lfs, lfs_mdir_t *dir,
2267
2268
  }
2268
2269
  }
2269
2270
 
2270
- if (dir->erased) {
2271
+ if (dir->erased && dir->count < 0xff) {
2271
2272
  // try to commit
2272
2273
  struct lfs_commit commit = {
2273
2274
  .block = dir->pair[0],
@@ -3932,7 +3933,9 @@ static int lfs_remove_(lfs_t *lfs, const char *path) {
3932
3933
  }
3933
3934
 
3934
3935
  lfs->mlist = dir.next;
3935
- if (lfs_tag_type3(tag) == LFS_TYPE_DIR) {
3936
+ if (lfs_gstate_hasorphans(&lfs->gstate)) {
3937
+ LFS_ASSERT(lfs_tag_type3(tag) == LFS_TYPE_DIR);
3938
+
3936
3939
  // fix orphan
3937
3940
  err = lfs_fs_preporphans(lfs, -1);
3938
3941
  if (err) {
@@ -4076,8 +4079,10 @@ static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) {
4076
4079
  }
4077
4080
 
4078
4081
  lfs->mlist = prevdir.next;
4079
- if (prevtag != LFS_ERR_NOENT
4080
- && lfs_tag_type3(prevtag) == LFS_TYPE_DIR) {
4082
+ if (lfs_gstate_hasorphans(&lfs->gstate)) {
4083
+ LFS_ASSERT(prevtag != LFS_ERR_NOENT
4084
+ && lfs_tag_type3(prevtag) == LFS_TYPE_DIR);
4085
+
4081
4086
  // fix orphan
4082
4087
  err = lfs_fs_preporphans(lfs, -1);
4083
4088
  if (err) {
@@ -5221,7 +5226,9 @@ static int lfs_fs_gc_(lfs_t *lfs) {
5221
5226
  }
5222
5227
 
5223
5228
  // try to populate the lookahead buffer, unless it's already full
5224
- if (lfs->lookahead.size < 8*lfs->cfg->lookahead_size) {
5229
+ if (lfs->lookahead.size < lfs_min(
5230
+ 8 * lfs->cfg->lookahead_size,
5231
+ lfs->block_count)) {
5225
5232
  err = lfs_alloc_scan(lfs);
5226
5233
  if (err) {
5227
5234
  return err;
@@ -5233,40 +5240,64 @@ static int lfs_fs_gc_(lfs_t *lfs) {
5233
5240
  #endif
5234
5241
 
5235
5242
  #ifndef LFS_READONLY
5243
+ #ifdef LFS_SHRINKNONRELOCATING
5244
+ static int lfs_shrink_checkblock(void *data, lfs_block_t block) {
5245
+ lfs_size_t threshold = *((lfs_size_t*)data);
5246
+ if (block >= threshold) {
5247
+ return LFS_ERR_NOTEMPTY;
5248
+ }
5249
+ return 0;
5250
+ }
5251
+ #endif
5252
+
5236
5253
  static int lfs_fs_grow_(lfs_t *lfs, lfs_size_t block_count) {
5237
- // shrinking is not supported
5238
- LFS_ASSERT(block_count >= lfs->block_count);
5254
+ int err;
5239
5255
 
5240
- if (block_count > lfs->block_count) {
5241
- lfs->block_count = block_count;
5256
+ if (block_count == lfs->block_count) {
5257
+ return 0;
5258
+ }
5242
5259
 
5243
- // fetch the root
5244
- lfs_mdir_t root;
5245
- int err = lfs_dir_fetch(lfs, &root, lfs->root);
5260
+
5261
+ #ifndef LFS_SHRINKNONRELOCATING
5262
+ // shrinking is not supported
5263
+ LFS_ASSERT(block_count >= lfs->block_count);
5264
+ #endif
5265
+ #ifdef LFS_SHRINKNONRELOCATING
5266
+ if (block_count < lfs->block_count) {
5267
+ err = lfs_fs_traverse_(lfs, lfs_shrink_checkblock, &block_count, true);
5246
5268
  if (err) {
5247
5269
  return err;
5248
5270
  }
5271
+ }
5272
+ #endif
5249
5273
 
5250
- // update the superblock
5251
- lfs_superblock_t superblock;
5252
- lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),
5253
- LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
5254
- &superblock);
5255
- if (tag < 0) {
5256
- return tag;
5257
- }
5258
- lfs_superblock_fromle32(&superblock);
5274
+ lfs->block_count = block_count;
5259
5275
 
5260
- superblock.block_count = lfs->block_count;
5276
+ // fetch the root
5277
+ lfs_mdir_t root;
5278
+ err = lfs_dir_fetch(lfs, &root, lfs->root);
5279
+ if (err) {
5280
+ return err;
5281
+ }
5261
5282
 
5262
- lfs_superblock_tole32(&superblock);
5263
- err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
5264
- {tag, &superblock}));
5265
- if (err) {
5266
- return err;
5267
- }
5283
+ // update the superblock
5284
+ lfs_superblock_t superblock;
5285
+ lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),
5286
+ LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
5287
+ &superblock);
5288
+ if (tag < 0) {
5289
+ return tag;
5268
5290
  }
5291
+ lfs_superblock_fromle32(&superblock);
5269
5292
 
5293
+ superblock.block_count = lfs->block_count;
5294
+
5295
+ lfs_superblock_tole32(&superblock);
5296
+ err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(
5297
+ {tag, &superblock}));
5298
+ if (err) {
5299
+ return err;
5300
+ }
5270
5301
  return 0;
5271
5302
  }
5272
5303
  #endif
@@ -21,7 +21,7 @@ extern "C"
21
21
  // Software library version
22
22
  // Major (top-nibble), incremented on backwards incompatible changes
23
23
  // Minor (bottom-nibble), incremented on feature additions
24
- #define LFS_VERSION 0x0002000a
24
+ #define LFS_VERSION 0x0002000b
25
25
  #define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
26
26
  #define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
27
27
 
@@ -766,7 +766,11 @@ int lfs_fs_gc(lfs_t *lfs);
766
766
  // Grows the filesystem to a new size, updating the superblock with the new
767
767
  // block count.
768
768
  //
769
- // Note: This is irreversible.
769
+ // If LFS_SHRINKNONRELOCATING is defined, this function will also accept
770
+ // block_counts smaller than the current configuration, after checking
771
+ // that none of the blocks that are being removed are in use.
772
+ // Note that littlefs's pseudorandom block allocation means that
773
+ // this is very unlikely to work in the general case.
770
774
  //
771
775
  // Returns a negative error code on failure.
772
776
  int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count);
@@ -195,10 +195,10 @@ static inline uint32_t lfs_fromle32(uint32_t a) {
195
195
  (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
196
196
  return __builtin_bswap32(a);
197
197
  #else
198
- return (((uint8_t*)&a)[0] << 0) |
199
- (((uint8_t*)&a)[1] << 8) |
200
- (((uint8_t*)&a)[2] << 16) |
201
- (((uint8_t*)&a)[3] << 24);
198
+ return ((uint32_t)((uint8_t*)&a)[0] << 0) |
199
+ ((uint32_t)((uint8_t*)&a)[1] << 8) |
200
+ ((uint32_t)((uint8_t*)&a)[2] << 16) |
201
+ ((uint32_t)((uint8_t*)&a)[3] << 24);
202
202
  #endif
203
203
  }
204
204
 
@@ -218,10 +218,10 @@ static inline uint32_t lfs_frombe32(uint32_t a) {
218
218
  (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
219
219
  return a;
220
220
  #else
221
- return (((uint8_t*)&a)[0] << 24) |
222
- (((uint8_t*)&a)[1] << 16) |
223
- (((uint8_t*)&a)[2] << 8) |
224
- (((uint8_t*)&a)[3] << 0);
221
+ return ((uint32_t)((uint8_t*)&a)[0] << 24) |
222
+ ((uint32_t)((uint8_t*)&a)[1] << 16) |
223
+ ((uint32_t)((uint8_t*)&a)[2] << 8) |
224
+ ((uint32_t)((uint8_t*)&a)[3] << 0);
225
225
  #endif
226
226
  }
227
227
 
@@ -231,8 +231,8 @@ static inline uint32_t lfs_tobe32(uint32_t a) {
231
231
 
232
232
  // Calculate CRC-32 with polynomial = 0x04c11db7
233
233
  #ifdef LFS_CRC
234
- uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
235
- return LFS_CRC(crc, buffer, size)
234
+ static inline uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
235
+ return LFS_CRC(crc, buffer, size);
236
236
  }
237
237
  #else
238
238
  uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
@@ -123,8 +123,13 @@ typedef struct bench_id {
123
123
 
124
124
 
125
125
  // bench suites are linked into a custom ld section
126
+ #if defined(__APPLE__)
127
+ extern struct bench_suite __start__bench_suites __asm("section$start$__DATA$_bench_suites");
128
+ extern struct bench_suite __stop__bench_suites __asm("section$end$__DATA$_bench_suites");
129
+ #else
126
130
  extern struct bench_suite __start__bench_suites;
127
131
  extern struct bench_suite __stop__bench_suites;
132
+ #endif
128
133
 
129
134
  const struct bench_suite *bench_suites = &__start__bench_suites;
130
135
  #define BENCH_SUITE_COUNT \
@@ -136,8 +136,13 @@ typedef struct test_id {
136
136
 
137
137
 
138
138
  // test suites are linked into a custom ld section
139
+ #if defined(__APPLE__)
140
+ extern struct test_suite __start__test_suites __asm("section$start$__DATA$_test_suites");
141
+ extern struct test_suite __stop__test_suites __asm("section$end$__DATA$_test_suites");
142
+ #else
139
143
  extern struct test_suite __start__test_suites;
140
144
  extern struct test_suite __stop__test_suites;
145
+ #endif
141
146
 
142
147
  const struct test_suite *test_suites = &__start__test_suites;
143
148
  #define TEST_SUITE_COUNT \
@@ -404,12 +404,15 @@ def compile(bench_paths, **args):
404
404
  f.writeln()
405
405
 
406
406
  # create suite struct
407
- #
407
+ f.writeln('#if defined(__APPLE__)')
408
+ f.writeln('__attribute__((section("__DATA,_bench_suites")))')
409
+ f.writeln('#else')
408
410
  # note we place this in the custom bench_suites section with
409
411
  # minimum alignment, otherwise GCC ups the alignment to
410
412
  # 32-bytes for some reason
411
413
  f.writeln('__attribute__((section("_bench_suites"), '
412
414
  'aligned(1)))')
415
+ f.writeln('#endif')
413
416
  f.writeln('const struct bench_suite __bench__%s__suite = {'
414
417
  % suite.name)
415
418
  f.writeln(4*' '+'.name = "%s",' % suite.name)
@@ -73,7 +73,7 @@ def changefile(from_prefix, to_prefix, from_path, to_path, *,
73
73
  shutil.copystat(from_path, to_path)
74
74
 
75
75
  if to_path_temp:
76
- os.rename(to_path, from_path)
76
+ shutil.move(to_path, from_path)
77
77
  elif from_path != '-':
78
78
  os.remove(from_path)
79
79
 
@@ -412,12 +412,15 @@ def compile(test_paths, **args):
412
412
  f.writeln()
413
413
 
414
414
  # create suite struct
415
- #
415
+ f.writeln('#if defined(__APPLE__)')
416
+ f.writeln('__attribute__((section("__DATA,_test_suites")))')
417
+ f.writeln('#else')
416
418
  # note we place this in the custom test_suites section with
417
419
  # minimum alignment, otherwise GCC ups the alignment to
418
420
  # 32-bytes for some reason
419
421
  f.writeln('__attribute__((section("_test_suites"), '
420
422
  'aligned(1)))')
423
+ f.writeln('#endif')
421
424
  f.writeln('const struct test_suite __test__%s__suite = {'
422
425
  % suite.name)
423
426
  f.writeln(4*' '+'.name = "%s",' % suite.name)
@@ -207,7 +207,8 @@ code = '''
207
207
  [cases.test_orphans_reentrant]
208
208
  reentrant = true
209
209
  # TODO fix this case, caused by non-DAG trees
210
- if = '!(DEPTH == 3 && CACHE_SIZE != 64)'
210
+ # NOTE the second condition is required
211
+ if = '!(DEPTH == 3 && CACHE_SIZE != 64) && 2*FILES < BLOCK_COUNT'
211
212
  defines = [
212
213
  {FILES=6, DEPTH=1, CYCLES=20},
213
214
  {FILES=26, DEPTH=1, CYCLES=20},
@@ -271,3 +272,69 @@ code = '''
271
272
  lfs_unmount(&lfs) => 0;
272
273
  '''
273
274
 
275
+ # non-reentrant testing for orphans, this is the same as reentrant
276
+ # testing, but we test way more states than we could under powerloss
277
+ [cases.test_orphans_nonreentrant]
278
+ # TODO fix this case, caused by non-DAG trees
279
+ # NOTE the second condition is required
280
+ if = '!(DEPTH == 3 && CACHE_SIZE != 64) && 2*FILES < BLOCK_COUNT'
281
+ defines = [
282
+ {FILES=6, DEPTH=1, CYCLES=2000},
283
+ {FILES=26, DEPTH=1, CYCLES=2000},
284
+ {FILES=3, DEPTH=3, CYCLES=2000},
285
+ ]
286
+ code = '''
287
+ lfs_t lfs;
288
+ lfs_format(&lfs, cfg) => 0;
289
+ lfs_mount(&lfs, cfg) => 0;
290
+
291
+ uint32_t prng = 1;
292
+ const char alpha[] = "abcdefghijklmnopqrstuvwxyz";
293
+ for (unsigned i = 0; i < CYCLES; i++) {
294
+ // create random path
295
+ char full_path[256];
296
+ for (unsigned d = 0; d < DEPTH; d++) {
297
+ sprintf(&full_path[2*d], "/%c", alpha[TEST_PRNG(&prng) % FILES]);
298
+ }
299
+
300
+ // if it does not exist, we create it, else we destroy
301
+ struct lfs_info info;
302
+ int res = lfs_stat(&lfs, full_path, &info);
303
+ if (res == LFS_ERR_NOENT) {
304
+ // create each directory in turn, ignore if dir already exists
305
+ for (unsigned d = 0; d < DEPTH; d++) {
306
+ char path[1024];
307
+ strcpy(path, full_path);
308
+ path[2*d+2] = '\0';
309
+ int err = lfs_mkdir(&lfs, path);
310
+ assert(!err || err == LFS_ERR_EXIST);
311
+ }
312
+
313
+ for (unsigned d = 0; d < DEPTH; d++) {
314
+ char path[1024];
315
+ strcpy(path, full_path);
316
+ path[2*d+2] = '\0';
317
+ lfs_stat(&lfs, path, &info) => 0;
318
+ assert(strcmp(info.name, &path[2*d+1]) == 0);
319
+ assert(info.type == LFS_TYPE_DIR);
320
+ }
321
+ } else {
322
+ // is valid dir?
323
+ assert(strcmp(info.name, &full_path[2*(DEPTH-1)+1]) == 0);
324
+ assert(info.type == LFS_TYPE_DIR);
325
+
326
+ // try to delete path in reverse order, ignore if dir is not empty
327
+ for (int d = DEPTH-1; d >= 0; d--) {
328
+ char path[1024];
329
+ strcpy(path, full_path);
330
+ path[2*d+2] = '\0';
331
+ int err = lfs_remove(&lfs, path);
332
+ assert(!err || err == LFS_ERR_NOTEMPTY);
333
+ }
334
+
335
+ lfs_stat(&lfs, full_path, &info) => LFS_ERR_NOENT;
336
+ }
337
+ }
338
+ lfs_unmount(&lfs) => 0;
339
+ '''
340
+