mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 00:32:38 +01:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into v2-alpha
This commit is contained in:
		
							
								
								
									
										69
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -28,7 +28,7 @@ script: | |||||||
|   # compile and find the code size with the smallest configuration |   # compile and find the code size with the smallest configuration | ||||||
|   - make clean size |   - make clean size | ||||||
|         OBJ="$(ls lfs*.o | tr '\n' ' ')" |         OBJ="$(ls lfs*.o | tr '\n' ' ')" | ||||||
|         CFLAGS+="-DLFS_NO{ASSERT,DEBUG,WARN,ERROR}" |         CFLAGS+="-DLFS_NO_ASSERT -DLFS_NO_DEBUG -DLFS_NO_WARN -DLFS_NO_ERROR" | ||||||
|         | tee sizes |         | tee sizes | ||||||
|  |  | ||||||
|   # update status if we succeeded, compare with master if possible |   # update status if we succeeded, compare with master if possible | ||||||
| @@ -135,53 +135,44 @@ jobs: | |||||||
|         - STAGE=deploy |         - STAGE=deploy | ||||||
|         - NAME=deploy |         - NAME=deploy | ||||||
|       script: |       script: | ||||||
|         # Update tag for version defined in lfs.h |         # Find version defined in lfs.h | ||||||
|         - LFS_VERSION=$(grep -ox '#define LFS_VERSION .*' lfs.h | cut -d ' ' -f3) |         - LFS_VERSION=$(grep -ox '#define LFS_VERSION .*' lfs.h | cut -d ' ' -f3) | ||||||
|         - LFS_VERSION_MAJOR=$((0xffff & ($LFS_VERSION >> 16))) |         - LFS_VERSION_MAJOR=$((0xffff & ($LFS_VERSION >> 16))) | ||||||
|         - LFS_VERSION_MINOR=$((0xffff & ($LFS_VERSION >>  0))) |         - LFS_VERSION_MINOR=$((0xffff & ($LFS_VERSION >>  0))) | ||||||
|         - LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR" |         # Grab latests patch from repo tags, default to 0 | ||||||
|         - echo "littlefs version $LFS_VERSION" |         - LFS_VERSION_PATCH=$(curl -f -u "$GEKY_BOT_RELEASES" | ||||||
|  |                 https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs | ||||||
|  |                 | jq 'map(.ref | match( | ||||||
|  |                     "refs/tags/v'"$LFS_VERSION_MAJOR"'\\.'"$LFS_VERSION_MINOR"'\\.(.*)$") | ||||||
|  |                     .captures[].string | tonumber + 1) | max // 0') | ||||||
|  |         # We have our new version | ||||||
|  |         - LFS_VERSION="v$LFS_VERSION_MAJOR.$LFS_VERSION_MINOR.$LFS_VERSION_PATCH" | ||||||
|  |         - echo "VERSION $LFS_VERSION" | ||||||
|         - | |         - | | ||||||
|           curl -u $GEKY_BOT_RELEASES -X POST \ |           # Check that we're the most recent commit | ||||||
|             https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs \ |           CURRENT_COMMIT=$(curl -f -u "$GEKY_BOT_RELEASES" \ | ||||||
|             -d "{ |                 https://api.github.com/repos/$TRAVIS_REPO_SLUG/commits/master \ | ||||||
|               \"ref\": \"refs/tags/$LFS_VERSION\", |                 | jq -re '.sha') | ||||||
|               \"sha\": \"$TRAVIS_COMMIT\" |           if [ "$TRAVIS_COMMIT" == "$CURRENT_COMMIT" ] | ||||||
|             }" |  | ||||||
|         - | |  | ||||||
|           curl -f -u $GEKY_BOT_RELEASES -X PATCH \ |  | ||||||
|             https://api.github.com/repos/$TRAVIS_REPO_SLUG/git/refs/tags/$LFS_VERSION \ |  | ||||||
|             -d "{ |  | ||||||
|               \"sha\": \"$TRAVIS_COMMIT\" |  | ||||||
|             }" |  | ||||||
|         # Create release notes from commits |  | ||||||
|         - LFS_PREV_VERSION="v$LFS_VERSION_MAJOR.$(($LFS_VERSION_MINOR-1))" |  | ||||||
|         - | |  | ||||||
|           if [ $(git tag -l "$LFS_PREV_VERSION") ] |  | ||||||
|           then |           then | ||||||
|             curl -u $GEKY_BOT_RELEASES -X POST \ |             # Build release notes | ||||||
|  |             PREV=$(git tag --sort=-v:refname -l "v*" | head -1) | ||||||
|  |             if [ ! -z "$PREV" ] | ||||||
|  |             then | ||||||
|  |                 echo "PREV $PREV" | ||||||
|  |                 CHANGES=$'### Changes\n\n'$( \ | ||||||
|  |                     git log --oneline $PREV.. --grep='^Merge' --invert-grep) | ||||||
|  |                 printf "CHANGES\n%s\n\n" "$CHANGES" | ||||||
|  |             fi | ||||||
|  |             # Create the release | ||||||
|  |             curl -f -u "$GEKY_BOT_RELEASES" -X POST \ | ||||||
|                 https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases \ |                 https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases \ | ||||||
|                 -d "{ |                 -d "{ | ||||||
|                     \"tag_name\": \"$LFS_VERSION\", |                     \"tag_name\": \"$LFS_VERSION\", | ||||||
|                     \"name\": \"$LFS_VERSION\" |                     \"target_commitish\": \"$TRAVIS_COMMIT\", | ||||||
|  |                     \"name\": \"${LFS_VERSION%.0}\", | ||||||
|  |                     \"body\": $(jq -sR '.' <<< "$CHANGES") | ||||||
|                 }" |                 }" | ||||||
|             RELEASE=$( |  | ||||||
|                 curl -f -u $GEKY_BOT_RELEASES \ |  | ||||||
|                     https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/tags/$LFS_VERSION |  | ||||||
|             ) |  | ||||||
|             CHANGES=$( |  | ||||||
|                 git log --oneline $LFS_PREV_VERSION.. --grep='^Merge' --invert-grep |  | ||||||
|             ) |  | ||||||
|             curl -f -u $GEKY_BOT_RELEASES -X PATCH \ |  | ||||||
|                 https://api.github.com/repos/$TRAVIS_REPO_SLUG/releases/$( |  | ||||||
|                     jq -r '.id' <<< "$RELEASE" |  | ||||||
|                 ) \ |  | ||||||
|                 -d "$( |  | ||||||
|                     jq -s '{ |  | ||||||
|                         "body": ((.[0] // "" | sub("(?<=\n)#+ Changes.*"; ""; "mi")) |  | ||||||
|                             + "### Changes\n\n" + .[1]) |  | ||||||
|                     }' <(jq '.body' <<< "$RELEASE") <(jq -sR '.' <<< "$CHANGES") |  | ||||||
|                 )" |  | ||||||
|           fi |           fi | ||||||
|  |  | ||||||
| # Manage statuses | # Manage statuses | ||||||
|   | |||||||
							
								
								
									
										183
									
								
								LICENSE.md
									
									
									
									
									
								
							
							
						
						
									
										183
									
								
								LICENSE.md
									
									
									
									
									
								
							| @@ -1,165 +1,24 @@ | |||||||
| Apache License | Copyright (c) 2017, Arm Limited. All rights reserved. | ||||||
| Version 2.0, January 2004 |  | ||||||
| http://www.apache.org/licenses/ |  | ||||||
|  |  | ||||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | Redistribution and use in source and binary forms, with or without modification, | ||||||
|  | are permitted provided that the following conditions are met: | ||||||
|  |  | ||||||
| 1. Definitions. | -  Redistributions of source code must retain the above copyright notice, this | ||||||
|  |    list of conditions and the following disclaimer. | ||||||
|  | -  Redistributions in binary form must reproduce the above copyright notice, this | ||||||
|  |    list of conditions and the following disclaimer in the documentation and/or | ||||||
|  |    other materials provided with the distribution. | ||||||
|  | -  Neither the name of ARM nor the names of its contributors may be used to | ||||||
|  |    endorse or promote products derived from this software without specific prior | ||||||
|  |    written permission. | ||||||
|  |  | ||||||
| "License" shall mean the terms and conditions for use, reproduction, and | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||||
| distribution as defined by Sections 1 through 9 of this document. | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
| "Licensor" shall mean the copyright owner or entity authorized by the copyright | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||||||
| owner that is granting the License. | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
| "Legal Entity" shall mean the union of the acting entity and all other entities | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||||
| that control, are controlled by, or are under common control with that entity. | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
| For the purposes of this definition, "control" means (i) the power, direct or | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
| indirect, to cause the direction or management of such entity, whether by | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
| contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the |  | ||||||
| outstanding shares, or (iii) beneficial ownership of such entity. |  | ||||||
|  |  | ||||||
| "You" (or "Your") shall mean an individual or Legal Entity exercising |  | ||||||
| permissions granted by this License. |  | ||||||
|  |  | ||||||
| "Source" form shall mean the preferred form for making modifications, including |  | ||||||
| but not limited to software source code, documentation source, and configuration |  | ||||||
| files. |  | ||||||
|  |  | ||||||
| "Object" form shall mean any form resulting from mechanical transformation or |  | ||||||
| translation of a Source form, including but not limited to compiled object code, |  | ||||||
| generated documentation, and conversions to other media types. |  | ||||||
|  |  | ||||||
| "Work" shall mean the work of authorship, whether in Source or Object form, made |  | ||||||
| available under the License, as indicated by a copyright notice that is included |  | ||||||
| in or attached to the work (an example is provided in the Appendix below). |  | ||||||
|  |  | ||||||
| "Derivative Works" shall mean any work, whether in Source or Object form, that |  | ||||||
| is based on (or derived from) the Work and for which the editorial revisions, |  | ||||||
| annotations, elaborations, or other modifications represent, as a whole, an |  | ||||||
| original work of authorship. For the purposes of this License, Derivative Works |  | ||||||
| shall not include works that remain separable from, or merely link (or bind by |  | ||||||
| name) to the interfaces of, the Work and Derivative Works thereof. |  | ||||||
|  |  | ||||||
| "Contribution" shall mean any work of authorship, including the original version |  | ||||||
| of the Work and any modifications or additions to that Work or Derivative Works |  | ||||||
| thereof, that is intentionally submitted to Licensor for inclusion in the Work |  | ||||||
| by the copyright owner or by an individual or Legal Entity authorized to submit |  | ||||||
| on behalf of the copyright owner. For the purposes of this definition, |  | ||||||
| "submitted" means any form of electronic, verbal, or written communication sent |  | ||||||
| to the Licensor or its representatives, including but not limited to |  | ||||||
| communication on electronic mailing lists, source code control systems, and |  | ||||||
| issue tracking systems that are managed by, or on behalf of, the Licensor for |  | ||||||
| the purpose of discussing and improving the Work, but excluding communication |  | ||||||
| that is conspicuously marked or otherwise designated in writing by the copyright |  | ||||||
| owner as "Not a Contribution." |  | ||||||
|  |  | ||||||
| "Contributor" shall mean Licensor and any individual or Legal Entity on behalf |  | ||||||
| of whom a Contribution has been received by Licensor and subsequently |  | ||||||
| incorporated within the Work. |  | ||||||
|  |  | ||||||
| 2. Grant of Copyright License. |  | ||||||
|  |  | ||||||
| Subject to the terms and conditions of this License, each Contributor hereby |  | ||||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, |  | ||||||
| irrevocable copyright license to reproduce, prepare Derivative Works of, |  | ||||||
| publicly display, publicly perform, sublicense, and distribute the Work and such |  | ||||||
| Derivative Works in Source or Object form. |  | ||||||
|  |  | ||||||
| 3. Grant of Patent License. |  | ||||||
|  |  | ||||||
| Subject to the terms and conditions of this License, each Contributor hereby |  | ||||||
| grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, |  | ||||||
| irrevocable (except as stated in this section) patent license to make, have |  | ||||||
| made, use, offer to sell, sell, import, and otherwise transfer the Work, where |  | ||||||
| such license applies only to those patent claims licensable by such Contributor |  | ||||||
| that are necessarily infringed by their Contribution(s) alone or by combination |  | ||||||
| of their Contribution(s) with the Work to which such Contribution(s) was |  | ||||||
| submitted. If You institute patent litigation against any entity (including a |  | ||||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work or a |  | ||||||
| Contribution incorporated within the Work constitutes direct or contributory |  | ||||||
| patent infringement, then any patent licenses granted to You under this License |  | ||||||
| for that Work shall terminate as of the date such litigation is filed. |  | ||||||
|  |  | ||||||
| 4. Redistribution. |  | ||||||
|  |  | ||||||
| You may reproduce and distribute copies of the Work or Derivative Works thereof |  | ||||||
| in any medium, with or without modifications, and in Source or Object form, |  | ||||||
| provided that You meet the following conditions: |  | ||||||
|  |  | ||||||
| You must give any other recipients of the Work or Derivative Works a copy of |  | ||||||
| this License; and |  | ||||||
| You must cause any modified files to carry prominent notices stating that You |  | ||||||
| changed the files; and |  | ||||||
| You must retain, in the Source form of any Derivative Works that You distribute, |  | ||||||
| all copyright, patent, trademark, and attribution notices from the Source form |  | ||||||
| of the Work, excluding those notices that do not pertain to any part of the |  | ||||||
| Derivative Works; and |  | ||||||
| If the Work includes a "NOTICE" text file as part of its distribution, then any |  | ||||||
| Derivative Works that You distribute must include a readable copy of the |  | ||||||
| attribution notices contained within such NOTICE file, excluding those notices |  | ||||||
| that do not pertain to any part of the Derivative Works, in at least one of the |  | ||||||
| following places: within a NOTICE text file distributed as part of the |  | ||||||
| Derivative Works; within the Source form or documentation, if provided along |  | ||||||
| with the Derivative Works; or, within a display generated by the Derivative |  | ||||||
| Works, if and wherever such third-party notices normally appear. The contents of |  | ||||||
| the NOTICE file are for informational purposes only and do not modify the |  | ||||||
| License. You may add Your own attribution notices within Derivative Works that |  | ||||||
| You distribute, alongside or as an addendum to the NOTICE text from the Work, |  | ||||||
| provided that such additional attribution notices cannot be construed as |  | ||||||
| modifying the License. |  | ||||||
| You may add Your own copyright statement to Your modifications and may provide |  | ||||||
| additional or different license terms and conditions for use, reproduction, or |  | ||||||
| distribution of Your modifications, or for any such Derivative Works as a whole, |  | ||||||
| provided Your use, reproduction, and distribution of the Work otherwise complies |  | ||||||
| with the conditions stated in this License. |  | ||||||
|  |  | ||||||
| 5. Submission of Contributions. |  | ||||||
|  |  | ||||||
| Unless You explicitly state otherwise, any Contribution intentionally submitted |  | ||||||
| for inclusion in the Work by You to the Licensor shall be under the terms and |  | ||||||
| conditions of this License, without any additional terms or conditions. |  | ||||||
| Notwithstanding the above, nothing herein shall supersede or modify the terms of |  | ||||||
| any separate license agreement you may have executed with Licensor regarding |  | ||||||
| such Contributions. |  | ||||||
|  |  | ||||||
| 6. Trademarks. |  | ||||||
|  |  | ||||||
| This License does not grant permission to use the trade names, trademarks, |  | ||||||
| service marks, or product names of the Licensor, except as required for |  | ||||||
| reasonable and customary use in describing the origin of the Work and |  | ||||||
| reproducing the content of the NOTICE file. |  | ||||||
|  |  | ||||||
| 7. Disclaimer of Warranty. |  | ||||||
|  |  | ||||||
| Unless required by applicable law or agreed to in writing, Licensor provides the |  | ||||||
| Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, |  | ||||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, |  | ||||||
| including, without limitation, any warranties or conditions of TITLE, |  | ||||||
| NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are |  | ||||||
| solely responsible for determining the appropriateness of using or |  | ||||||
| redistributing the Work and assume any risks associated with Your exercise of |  | ||||||
| permissions under this License. |  | ||||||
|  |  | ||||||
| 8. Limitation of Liability. |  | ||||||
|  |  | ||||||
| In no event and under no legal theory, whether in tort (including negligence), |  | ||||||
| contract, or otherwise, unless required by applicable law (such as deliberate |  | ||||||
| and grossly negligent acts) or agreed to in writing, shall any Contributor be |  | ||||||
| liable to You for damages, including any direct, indirect, special, incidental, |  | ||||||
| or consequential damages of any character arising as a result of this License or |  | ||||||
| out of the use or inability to use the Work (including but not limited to |  | ||||||
| damages for loss of goodwill, work stoppage, computer failure or malfunction, or |  | ||||||
| any and all other commercial damages or losses), even if such Contributor has |  | ||||||
| been advised of the possibility of such damages. |  | ||||||
|  |  | ||||||
| 9. Accepting Warranty or Additional Liability. |  | ||||||
|  |  | ||||||
| While redistributing the Work or Derivative Works thereof, You may choose to |  | ||||||
| offer, and charge a fee for, acceptance of support, warranty, indemnity, or |  | ||||||
| other liability obligations and/or rights consistent with this License. However, |  | ||||||
| in accepting such obligations, You may act only on Your own behalf and on Your |  | ||||||
| sole responsibility, not on behalf of any other Contributor, and only if You |  | ||||||
| agree to indemnify, defend, and hold each Contributor harmless for any liability |  | ||||||
| incurred by, or claims asserted against, such Contributor by reason of your |  | ||||||
| accepting any such warranty or additional liability. |  | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,4 +1,7 @@ | |||||||
| TARGET = lfs | TARGET = lfs.a | ||||||
|  | ifneq ($(wildcard test.c main.c),) | ||||||
|  | override TARGET = lfs | ||||||
|  | endif | ||||||
|  |  | ||||||
| CC ?= gcc | CC ?= gcc | ||||||
| AR ?= ar | AR ?= ar | ||||||
| @@ -22,7 +25,7 @@ ifdef WORD | |||||||
| override CFLAGS += -m$(WORD) | override CFLAGS += -m$(WORD) | ||||||
| endif | endif | ||||||
| override CFLAGS += -I. | override CFLAGS += -I. | ||||||
| override CFLAGS += -std=c99 -Wall -pedantic | override CFLAGS += -std=c99 -Wall -pedantic -Wshadow -Wunused-parameter | ||||||
|  |  | ||||||
|  |  | ||||||
| all: $(TARGET) | all: $(TARGET) | ||||||
| @@ -36,7 +39,9 @@ size: $(OBJ) | |||||||
| test: test_format test_dirs test_files test_seek test_truncate \ | test: test_format test_dirs test_files test_seek test_truncate \ | ||||||
| 	test_entries test_interspersed test_alloc test_paths test_attrs \ | 	test_entries test_interspersed test_alloc test_paths test_attrs \ | ||||||
| 	test_move test_orphan test_corrupt | 	test_move test_orphan test_corrupt | ||||||
|  | 	@rm test.c | ||||||
| test_%: tests/test_%.sh | test_%: tests/test_%.sh | ||||||
|  |  | ||||||
| ifdef QUIET | ifdef QUIET | ||||||
| 	@./$< | sed -n '/^[-=]/p' | 	@./$< | sed -n '/^[-=]/p' | ||||||
| else | else | ||||||
| @@ -45,7 +50,7 @@ endif | |||||||
|  |  | ||||||
| -include $(DEP) | -include $(DEP) | ||||||
|  |  | ||||||
| $(TARGET): $(OBJ) | lfs: $(OBJ) | ||||||
| 	$(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ | 	$(CC) $(CFLAGS) $^ $(LFLAGS) -o $@ | ||||||
|  |  | ||||||
| %.a: $(OBJ) | %.a: $(OBJ) | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
									
									
									
									
								
							| @@ -146,6 +146,19 @@ The tests assume a Linux environment and can be started with make: | |||||||
| make test | make test | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | ## License | ||||||
|  |  | ||||||
|  | The littlefs is provided under the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) | ||||||
|  | license. See [LICENSE.md](LICENSE.md) for more information. Contributions to | ||||||
|  | this project are accepted under the same license. | ||||||
|  |  | ||||||
|  | Individual files contain the following tag instead of the full license text. | ||||||
|  |  | ||||||
|  |     SPDX-License-Identifier:    BSD-3-Clause | ||||||
|  |  | ||||||
|  | This enables machine processing of license information based on the SPDX | ||||||
|  | License Identifiers that are here available: http://spdx.org/licenses/ | ||||||
|  |  | ||||||
| ## Related projects | ## Related projects | ||||||
|  |  | ||||||
| [Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) - | [Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) - | ||||||
|   | |||||||
| @@ -1,19 +1,8 @@ | |||||||
| /* | /* | ||||||
|  * Block device emulated on standard files |  * Block device emulated on standard files | ||||||
|  * |  * | ||||||
|  * Copyright (c) 2017 ARM Limited |  * Copyright (c) 2017, Arm Limited. All rights reserved. | ||||||
|  * |  * SPDX-License-Identifier: BSD-3-Clause | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  */ | ||||||
| #include "emubd/lfs_emubd.h" | #include "emubd/lfs_emubd.h" | ||||||
|  |  | ||||||
| @@ -27,6 +16,7 @@ | |||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  | #include <inttypes.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| // Block device emulated on existing filesystem | // Block device emulated on existing filesystem | ||||||
| @@ -96,7 +86,7 @@ int lfs_emubd_read(const struct lfs_config *cfg, lfs_block_t block, | |||||||
|     memset(data, 0, size); |     memset(data, 0, size); | ||||||
|  |  | ||||||
|     // Read data |     // Read data | ||||||
|     snprintf(emu->child, LFS_NAME_MAX, "%x", block); |     snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); | ||||||
|  |  | ||||||
|     FILE *f = fopen(emu->path, "rb"); |     FILE *f = fopen(emu->path, "rb"); | ||||||
|     if (!f && errno != ENOENT) { |     if (!f && errno != ENOENT) { | ||||||
| @@ -135,7 +125,7 @@ int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block, | |||||||
|     assert(block < cfg->block_count); |     assert(block < cfg->block_count); | ||||||
|  |  | ||||||
|     // Program data |     // Program data | ||||||
|     snprintf(emu->child, LFS_NAME_MAX, "%x", block); |     snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); | ||||||
|  |  | ||||||
|     FILE *f = fopen(emu->path, "r+b"); |     FILE *f = fopen(emu->path, "r+b"); | ||||||
|     if (!f) { |     if (!f) { | ||||||
| @@ -182,7 +172,7 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) { | |||||||
|     assert(block < cfg->block_count); |     assert(block < cfg->block_count); | ||||||
|  |  | ||||||
|     // Erase the block |     // Erase the block | ||||||
|     snprintf(emu->child, LFS_NAME_MAX, "%x", block); |     snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); | ||||||
|     struct stat st; |     struct stat st; | ||||||
|     int err = stat(emu->path, &st); |     int err = stat(emu->path, &st); | ||||||
|     if (err && errno != ENOENT) { |     if (err && errno != ENOENT) { | ||||||
| @@ -250,4 +240,3 @@ int lfs_emubd_sync(const struct lfs_config *cfg) { | |||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,19 +1,8 @@ | |||||||
| /* | /* | ||||||
|  * Block device emulated on standard files |  * Block device emulated on standard files | ||||||
|  * |  * | ||||||
|  * Copyright (c) 2017 ARM Limited |  * Copyright (c) 2017, Arm Limited. All rights reserved. | ||||||
|  * |  * SPDX-License-Identifier: BSD-3-Clause | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  */ | ||||||
| #ifndef LFS_EMUBD_H | #ifndef LFS_EMUBD_H | ||||||
| #define LFS_EMUBD_H | #define LFS_EMUBD_H | ||||||
| @@ -21,6 +10,11 @@ | |||||||
| #include "lfs.h" | #include "lfs.h" | ||||||
| #include "lfs_util.h" | #include "lfs_util.h" | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" | ||||||
|  | { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| // Config options | // Config options | ||||||
| #ifndef LFS_EMUBD_READ_SIZE | #ifndef LFS_EMUBD_READ_SIZE | ||||||
| @@ -86,4 +80,8 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block); | |||||||
| int lfs_emubd_sync(const struct lfs_config *cfg); | int lfs_emubd_sync(const struct lfs_config *cfg); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } /* extern "C" */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										235
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										235
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -74,12 +74,12 @@ static int lfs_cache_read(lfs_t *lfs, | |||||||
|  |  | ||||||
|         // load to cache, first condition can no longer fail |         // load to cache, first condition can no longer fail | ||||||
|         LFS_ASSERT(block < lfs->cfg->block_count); |         LFS_ASSERT(block < lfs->cfg->block_count); | ||||||
|         lfs_size_t size = store ? lfs->cfg->cache_size : lfs->cfg->prog_size; |         lfs_size_t nsize = store ? lfs->cfg->cache_size : lfs->cfg->prog_size; | ||||||
|         rcache->block = block; |         rcache->block = block; | ||||||
|         rcache->off = lfs_aligndown(off, size); |         rcache->off = lfs_aligndown(off, nsize); | ||||||
|         rcache->size = size; |         rcache->size = nsize; | ||||||
|         int err = lfs->cfg->read(lfs->cfg, rcache->block, |         int err = lfs->cfg->read(lfs->cfg, rcache->block, | ||||||
|                 rcache->off, rcache->buffer, size); |                 rcache->off, rcache->buffer, nsize); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -127,6 +127,19 @@ static int lfs_cache_crc(lfs_t *lfs, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) { | ||||||
|  |     // do not zero, cheaper if cache is readonly or only going to be | ||||||
|  |     // written with identical data (during relocates) | ||||||
|  |     (void)lfs; | ||||||
|  |     rcache->block = 0xffffffff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) { | ||||||
|  |     // zero to avoid information leak | ||||||
|  |     memset(pcache->buffer, 0xff, lfs->cfg->prog_size); | ||||||
|  |     pcache->block = 0xffffffff; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int lfs_cache_flush(lfs_t *lfs, | static int lfs_cache_flush(lfs_t *lfs, | ||||||
|         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { |         lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { | ||||||
|     if (pcache->block != 0xffffffff) { |     if (pcache->block != 0xffffffff) { | ||||||
| @@ -140,7 +153,7 @@ static int lfs_cache_flush(lfs_t *lfs, | |||||||
|  |  | ||||||
|         if (validate) { |         if (validate) { | ||||||
|             // check data on disk |             // check data on disk | ||||||
|             rcache->block = 0xffffffff; |             lfs_cache_drop(lfs, rcache); | ||||||
|             int res = lfs_cache_cmp(lfs, NULL, rcache, pcache->block, |             int res = lfs_cache_cmp(lfs, NULL, rcache, pcache->block, | ||||||
|                     pcache->off, pcache->buffer, diff); |                     pcache->off, pcache->buffer, diff); | ||||||
|             if (res < 0) { |             if (res < 0) { | ||||||
| @@ -152,7 +165,7 @@ static int lfs_cache_flush(lfs_t *lfs, | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         pcache->block = 0xffffffff; |         lfs_cache_zero(lfs, pcache); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -234,7 +247,7 @@ static int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_bd_sync(lfs_t *lfs) { | static int lfs_bd_sync(lfs_t *lfs) { | ||||||
|     lfs->rcache.block = 0xffffffff; |     lfs_cache_drop(lfs, &lfs->rcache); | ||||||
|  |  | ||||||
|     int err = lfs_cache_flush(lfs, &lfs->pcache, &lfs->rcache, false); |     int err = lfs_cache_flush(lfs, &lfs->pcache, &lfs->rcache, false); | ||||||
|     if (err) { |     if (err) { | ||||||
| @@ -253,6 +266,7 @@ static int32_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2], | |||||||
| static int lfs_fs_relocate(lfs_t *lfs, | static int lfs_fs_relocate(lfs_t *lfs, | ||||||
|         const lfs_block_t oldpair[2], lfs_block_t newpair[2]); |         const lfs_block_t oldpair[2], lfs_block_t newpair[2]); | ||||||
| static int lfs_fs_forceconsistency(lfs_t *lfs); | static int lfs_fs_forceconsistency(lfs_t *lfs); | ||||||
|  | static int lfs_deinit(lfs_t *lfs); | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Block allocator /// | /// Block allocator /// | ||||||
| @@ -294,7 +308,8 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { | |||||||
|  |  | ||||||
|         // check if we have looked at all blocks since last ack |         // check if we have looked at all blocks since last ack | ||||||
|         if (lfs->free.ack == 0) { |         if (lfs->free.ack == 0) { | ||||||
|             LFS_WARN("No more free space %d", lfs->free.i + lfs->free.off); |             LFS_WARN("No more free space %"PRIu32, | ||||||
|  |                     lfs->free.i + lfs->free.off); | ||||||
|             return LFS_ERR_NOSPC; |             return LFS_ERR_NOSPC; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -517,7 +532,7 @@ static int lfs_commitattr(lfs_t *lfs, struct lfs_commit *commit, | |||||||
|         // special case for moves |         // special case for moves | ||||||
|         return lfs_commitmove(lfs, commit, |         return lfs_commitmove(lfs, commit, | ||||||
|                 lfs_tagsize(tag), lfs_tagid(tag), |                 lfs_tagsize(tag), lfs_tagid(tag), | ||||||
|                 buffer, NULL);  |                 buffer, NULL); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // check if we fit |     // check if we fit | ||||||
| @@ -549,7 +564,7 @@ static int lfs_commitattr(lfs_t *lfs, struct lfs_commit *commit, | |||||||
|         for (lfs_off_t i = 0; i < size; i++) { |         for (lfs_off_t i = 0; i < size; i++) { | ||||||
|             // rely on caching to make this efficient |             // rely on caching to make this efficient | ||||||
|             uint8_t dat; |             uint8_t dat; | ||||||
|             int err = lfs_bd_read(lfs, disk->block, disk->off+i, &dat, 1); |             err = lfs_bd_read(lfs, disk->block, disk->off+i, &dat, 1); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -723,7 +738,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) { | |||||||
|     // the revision may be valid |     // the revision may be valid | ||||||
|     int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->rev, 4); |     int err = lfs_bd_read(lfs, dir->pair[0], 0, &dir->rev, 4); | ||||||
|     dir->rev = lfs_fromle32(dir->rev); |     dir->rev = lfs_fromle32(dir->rev); | ||||||
|     if (err) { |     if (err && err != LFS_ERR_CORRUPT) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -752,11 +767,16 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|     // find the block with the most recent revision |     // find the block with the most recent revision | ||||||
|     uint32_t rev[2]; |     uint32_t rev[2]; | ||||||
|     for (int i = 0; i < 2; i++) { |     for (int i = 0; i < 2; i++) { | ||||||
|         int err = lfs_bd_read(lfs, dir->pair[i], 0, &rev[i], sizeof(rev[i])); |         int err = lfs_cache_read(lfs, &lfs->pcache, &lfs->rcache, false, | ||||||
|         if (err) { |                 dir->pair[i], 0, &rev[i], sizeof(rev[i])); | ||||||
|  |         rev[i] = lfs_fromle32(rev[i]); | ||||||
|  |         if (err && err != LFS_ERR_CORRUPT) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|         rev[i] = lfs_fromle32(rev[i]); |  | ||||||
|  |         if (err == LFS_ERR_CORRUPT) { | ||||||
|  |             rev[i] = rev[(i+1)%2] - 1; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (lfs_scmp(rev[1], rev[0]) > 0) { |     if (lfs_scmp(rev[1], rev[0]) > 0) { | ||||||
| @@ -788,6 +808,11 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|             int err = lfs_bd_read(lfs, dir->pair[0], |             int err = lfs_bd_read(lfs, dir->pair[0], | ||||||
|                     off, &tag, sizeof(tag)); |                     off, &tag, sizeof(tag)); | ||||||
|             if (err) { |             if (err) { | ||||||
|  |                 if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                     // can't continue? | ||||||
|  |                     dir->erased = false; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -809,9 +834,13 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|             if (lfs_tagtype(tag) == LFS_TYPE_CRC) { |             if (lfs_tagtype(tag) == LFS_TYPE_CRC) { | ||||||
|                 // check the crc attr |                 // check the crc attr | ||||||
|                 uint32_t dcrc; |                 uint32_t dcrc; | ||||||
|                 int err = lfs_bd_read(lfs, dir->pair[0], |                 err = lfs_bd_read(lfs, dir->pair[0], | ||||||
|                         off+sizeof(tag), &dcrc, sizeof(dcrc)); |                         off+sizeof(tag), &dcrc, sizeof(dcrc)); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|  |                     if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                         dir->erased = false; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
|                 dcrc = lfs_fromle32(dcrc); |                 dcrc = lfs_fromle32(dcrc); | ||||||
| @@ -834,7 +863,10 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|                 err = lfs_bd_crc(lfs, dir->pair[0], |                 err = lfs_bd_crc(lfs, dir->pair[0], | ||||||
|                         off+sizeof(tag), lfs_tagsize(tag), &crc); |                         off+sizeof(tag), lfs_tagsize(tag), &crc); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                         dir->erased = false; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (lfs_tagid(tag) < 0x3ff && lfs_tagid(tag) >= tempcount) { |                 if (lfs_tagid(tag) < 0x3ff && lfs_tagid(tag) >= tempcount) { | ||||||
| @@ -846,7 +878,10 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|                     err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag), |                     err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag), | ||||||
|                             temptail, sizeof(temptail)); |                             temptail, sizeof(temptail)); | ||||||
|                     if (err) { |                     if (err) { | ||||||
|                         return err; |                         if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                             dir->erased = false; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                     lfs_pairfromle32(temptail); |                     lfs_pairfromle32(temptail); | ||||||
|                 } else if (lfs_tagsubtype(tag) == LFS_TYPE_GLOBALS) { |                 } else if (lfs_tagsubtype(tag) == LFS_TYPE_GLOBALS) { | ||||||
| @@ -854,7 +889,10 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|                     err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag), |                     err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag), | ||||||
|                             &templocals, sizeof(templocals)); |                             &templocals, sizeof(templocals)); | ||||||
|                     if (err) { |                     if (err) { | ||||||
|                         return err; |                         if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                             dir->erased = false; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } else if (lfs_tagsubtype(tag) == LFS_TYPE_DELETE) { |                 } else if (lfs_tagsubtype(tag) == LFS_TYPE_DELETE) { | ||||||
|                     LFS_ASSERT(tempcount > 0); |                     LFS_ASSERT(tempcount > 0); | ||||||
| @@ -870,6 +908,10 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|                     int res = lfs_bd_cmp(lfs, dir->pair[0], off+sizeof(tag), |                     int res = lfs_bd_cmp(lfs, dir->pair[0], off+sizeof(tag), | ||||||
|                             findbuffer, lfs_tagsize(tag)); |                             findbuffer, lfs_tagsize(tag)); | ||||||
|                     if (res < 0) { |                     if (res < 0) { | ||||||
|  |                         if (res == LFS_ERR_CORRUPT) { | ||||||
|  |                             dir->erased = false; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|                         return res; |                         return res; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
| @@ -904,7 +946,8 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|         lfs_pairswap(rev); |         lfs_pairswap(rev); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     LFS_ERROR("Corrupted dir pair at %d %d", dir->pair[0], dir->pair[1]); |     LFS_ERROR("Corrupted dir pair at %"PRIu32" %"PRIu32, | ||||||
|  |             dir->pair[0], dir->pair[1]); | ||||||
|     return LFS_ERR_CORRUPT; |     return LFS_ERR_CORRUPT; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1051,7 +1094,7 @@ static int lfs_dir_compact(lfs_t *lfs, | |||||||
| split: | split: | ||||||
|         // commit no longer fits, need to split dir, |         // commit no longer fits, need to split dir, | ||||||
|         // drop caches and create tail |         // drop caches and create tail | ||||||
|         lfs->pcache.block = 0xffffffff; |         lfs_cache_drop(lfs, &lfs->pcache); | ||||||
|  |  | ||||||
|         if (ack == -1) { |         if (ack == -1) { | ||||||
|             // If we can't fit in this block, we won't fit in next block |             // If we can't fit in this block, we won't fit in next block | ||||||
| @@ -1081,15 +1124,16 @@ split: | |||||||
|  |  | ||||||
| relocate: | relocate: | ||||||
|         //commit was corrupted |         //commit was corrupted | ||||||
|         LFS_DEBUG("Bad block at %d", dir->pair[1]); |         LFS_DEBUG("Bad block at %"PRIu32, | ||||||
|  |                 dir->pair[1]); | ||||||
|  |  | ||||||
|         // drop caches and prepare to relocate block |         // drop caches and prepare to relocate block | ||||||
|         relocated = true; |         relocated = true; | ||||||
|         lfs->pcache.block = 0xffffffff; |         lfs_cache_drop(lfs, &lfs->pcache); | ||||||
|  |  | ||||||
|         // can't relocate superblock, filesystem is now frozen |         // can't relocate superblock, filesystem is now frozen | ||||||
|         if (lfs_paircmp(oldpair, (const lfs_block_t[2]){0, 1}) == 0) { |         if (lfs_paircmp(oldpair, (const lfs_block_t[2]){0, 1}) == 0) { | ||||||
|             LFS_WARN("Superblock %d has become unwritable", oldpair[1]); |             LFS_WARN("Superblock %"PRIu32" has become unwritable", oldpair[1]); | ||||||
|             return LFS_ERR_CORRUPT; |             return LFS_ERR_CORRUPT; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -1108,7 +1152,7 @@ relocate: | |||||||
|         lfs_globalzero(&lfs->locals); |         lfs_globalzero(&lfs->locals); | ||||||
|     } else { |     } else { | ||||||
|         // update references if we relocated |         // update references if we relocated | ||||||
|         LFS_DEBUG("Relocating %d %d to %d %d", |         LFS_DEBUG("Relocating %"PRIu32" %"PRIu32" to %"PRIu32" %"PRIu32, | ||||||
|                 oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); |                 oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); | ||||||
|         int err = lfs_fs_relocate(lfs, oldpair, dir->pair); |         int err = lfs_fs_relocate(lfs, oldpair, dir->pair); | ||||||
|         if (err) { |         if (err) { | ||||||
| @@ -1174,15 +1218,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!dir->erased) { |     if (dir->erased) { | ||||||
| compact: |  | ||||||
|         // fall back to compaction |  | ||||||
|         lfs->pcache.block = 0xffffffff; |  | ||||||
|         int err = lfs_dir_compact(lfs, dir, attrs, dir, 0, dir->count); |  | ||||||
|         if (err) { |  | ||||||
|             return err; |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         // try to commit |         // try to commit | ||||||
|         struct lfs_commit commit = { |         struct lfs_commit commit = { | ||||||
|             .block = dir->pair[0], |             .block = dir->pair[0], | ||||||
| @@ -1241,6 +1277,14 @@ compact: | |||||||
|         // successful commit, update globals |         // successful commit, update globals | ||||||
|         lfs_globalxor(&dir->locals, &lfs->locals); |         lfs_globalxor(&dir->locals, &lfs->locals); | ||||||
|         lfs_globalzero(&lfs->locals); |         lfs_globalzero(&lfs->locals); | ||||||
|  |     } else { | ||||||
|  | compact: | ||||||
|  |         // fall back to compaction | ||||||
|  |         lfs_cache_drop(lfs, &lfs->pcache); | ||||||
|  |         int err = lfs_dir_compact(lfs, dir, attrs, dir, 0, dir->count); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // update globals that are affected |     // update globals that are affected | ||||||
| @@ -1583,7 +1627,7 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) { | |||||||
|                 return LFS_ERR_INVAL; |                 return LFS_ERR_INVAL; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             int err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail); |             err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -1752,10 +1796,10 @@ static int lfs_ctzextend(lfs_t *lfs, | |||||||
|         } |         } | ||||||
|  |  | ||||||
| relocate: | relocate: | ||||||
|         LFS_DEBUG("Bad block at %d", nblock); |         LFS_DEBUG("Bad block at %"PRIu32, nblock); | ||||||
|  |  | ||||||
|         // just clear cache and try a new block |         // just clear cache and try a new block | ||||||
|         pcache->block = 0xffffffff; |         lfs_cache_drop(lfs, pcache); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1849,7 +1893,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|  |  | ||||||
|         // get next slot and create entry to remember name |         // get next slot and create entry to remember name | ||||||
|         file->id = file->m.count; |         file->id = file->m.count; | ||||||
|         int err = lfs_dir_commit(lfs, &file->m, |         err = lfs_dir_commit(lfs, &file->m, | ||||||
|                 LFS_MKATTR(LFS_TYPE_REG, file->id, path, nlen, |                 LFS_MKATTR(LFS_TYPE_REG, file->id, path, nlen, | ||||||
|                 LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id, NULL, 0, |                 LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id, NULL, 0, | ||||||
|                 NULL))); |                 NULL))); | ||||||
| @@ -1902,7 +1946,6 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // allocate buffer if needed |     // allocate buffer if needed | ||||||
|     file->cache.block = 0xffffffff; |  | ||||||
|     if (file->cfg->buffer) { |     if (file->cfg->buffer) { | ||||||
|         file->cache.buffer = file->cfg->buffer; |         file->cache.buffer = file->cfg->buffer; | ||||||
|     } else { |     } else { | ||||||
| @@ -1913,6 +1956,9 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // zero to avoid information leak | ||||||
|  |     lfs_cache_zero(lfs, &file->cache); | ||||||
|  |  | ||||||
|     if (lfs_tagtype(tag) == LFS_TYPE_INLINESTRUCT) { |     if (lfs_tagtype(tag) == LFS_TYPE_INLINESTRUCT) { | ||||||
|         // load inline files |         // load inline files | ||||||
|         file->ctz.head = 0xfffffffe; |         file->ctz.head = 0xfffffffe; | ||||||
| @@ -2009,7 +2055,7 @@ static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { | |||||||
|         file->cache.block = lfs->pcache.block; |         file->cache.block = lfs->pcache.block; | ||||||
|         file->cache.off = lfs->pcache.off; |         file->cache.off = lfs->pcache.off; | ||||||
|         file->cache.size = lfs->pcache.size; |         file->cache.size = lfs->pcache.size; | ||||||
|         lfs->pcache.block = 0xffffffff; |         lfs_cache_zero(lfs, &lfs->pcache); | ||||||
|  |  | ||||||
|         file->block = nblock; |         file->block = nblock; | ||||||
|         return 0; |         return 0; | ||||||
| @@ -2036,7 +2082,7 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | |||||||
|                 .pos = file->pos, |                 .pos = file->pos, | ||||||
|                 .cache = lfs->rcache, |                 .cache = lfs->rcache, | ||||||
|             }; |             }; | ||||||
|             lfs->rcache.block = 0xffffffff; |             lfs_cache_drop(lfs, &lfs->rcache); | ||||||
|  |  | ||||||
|             while (file->pos < file->ctz.size) { |             while (file->pos < file->ctz.size) { | ||||||
|                 // copy over a byte at a time, leave it up to caching |                 // copy over a byte at a time, leave it up to caching | ||||||
| @@ -2054,8 +2100,8 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | |||||||
|  |  | ||||||
|                 // keep our reference to the rcache in sync |                 // keep our reference to the rcache in sync | ||||||
|                 if (lfs->rcache.block != 0xffffffff) { |                 if (lfs->rcache.block != 0xffffffff) { | ||||||
|                     orig.cache.block = 0xffffffff; |                     lfs_cache_drop(lfs, &orig.cache); | ||||||
|                     lfs->rcache.block = 0xffffffff; |                     lfs_cache_drop(lfs, &lfs->rcache); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -2073,7 +2119,7 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | |||||||
|                 break; |                 break; | ||||||
|  |  | ||||||
| relocate: | relocate: | ||||||
|                 LFS_DEBUG("Bad block at %d", file->block); |                 LFS_DEBUG("Bad block at %"PRIu32, file->block); | ||||||
|                 err = lfs_file_relocate(lfs, file); |                 err = lfs_file_relocate(lfs, file); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
| @@ -2123,7 +2169,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|  |  | ||||||
|             // commit file data and attributes |             // commit file data and attributes | ||||||
|             lfs_ctztole32(&file->ctz); |             lfs_ctztole32(&file->ctz); | ||||||
|             int err = lfs_dir_commit(lfs, &file->m, |             err = lfs_dir_commit(lfs, &file->m, | ||||||
|                     LFS_MKATTR(type, file->id, buffer, size, |                     LFS_MKATTR(type, file->id, buffer, size, | ||||||
|                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0, |                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0, | ||||||
|                     NULL))); |                     NULL))); | ||||||
| @@ -2284,7 +2330,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     // mark cache as dirty since we may have read data into it |                     // mark cache as dirty since we may have read data into it | ||||||
|                     file->cache.block = 0xffffffff; |                     lfs_cache_zero(lfs, &file->cache); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 // extend file with new blocks |                 // extend file with new blocks | ||||||
| @@ -2482,7 +2528,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { | |||||||
|         } |         } | ||||||
|         lfs_pairfromle32(pair); |         lfs_pairfromle32(pair); | ||||||
|  |  | ||||||
|         int err = lfs_dir_fetch(lfs, &dir, pair); |         err = lfs_dir_fetch(lfs, &dir, pair); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2504,7 +2550,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (lfs_tagtype(tag) == LFS_TYPE_DIR) { |     if (lfs_tagtype(tag) == LFS_TYPE_DIR) { | ||||||
|         int err = lfs_fs_pred(lfs, dir.pair, &cwd); |         err = lfs_fs_pred(lfs, dir.pair, &cwd); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2571,7 +2617,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|             lfs_pairfromle32(prevpair); |             lfs_pairfromle32(prevpair); | ||||||
|  |  | ||||||
|             // must be empty before removal |             // must be empty before removal | ||||||
|             int err = lfs_dir_fetch(lfs, &prevdir, prevpair); |             err = lfs_dir_fetch(lfs, &prevdir, prevpair); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
| @@ -2616,7 +2662,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (prevtag != LFS_ERR_NOENT && lfs_tagtype(prevtag) == LFS_TYPE_DIR) { |     if (prevtag != LFS_ERR_NOENT && lfs_tagtype(prevtag) == LFS_TYPE_DIR) { | ||||||
|         int err = lfs_fs_pred(lfs, prevdir.pair, &newcwd); |         err = lfs_fs_pred(lfs, prevdir.pair, &newcwd); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2697,6 +2743,7 @@ static inline void lfs_superblocktole32(lfs_superblock_t *superblock) { | |||||||
|  |  | ||||||
| static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | ||||||
|     lfs->cfg = cfg; |     lfs->cfg = cfg; | ||||||
|  |     int err = 0; | ||||||
|  |  | ||||||
|     // check that block size is a multiple of cache size is a multiple |     // check that block size is a multiple of cache size is a multiple | ||||||
|     // of prog and read sizes |     // of prog and read sizes | ||||||
| @@ -2709,27 +2756,31 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|             <= lfs->cfg->block_size); |             <= lfs->cfg->block_size); | ||||||
|  |  | ||||||
|     // setup read cache |     // setup read cache | ||||||
|     lfs->rcache.block = 0xffffffff; |  | ||||||
|     if (lfs->cfg->read_buffer) { |     if (lfs->cfg->read_buffer) { | ||||||
|         lfs->rcache.buffer = lfs->cfg->read_buffer; |         lfs->rcache.buffer = lfs->cfg->read_buffer; | ||||||
|     } else { |     } else { | ||||||
|         lfs->rcache.buffer = lfs_malloc(lfs->cfg->cache_size); |         lfs->rcache.buffer = lfs_malloc(lfs->cfg->cache_size); | ||||||
|         if (!lfs->rcache.buffer) { |         if (!lfs->rcache.buffer) { | ||||||
|             return LFS_ERR_NOMEM; |             err = LFS_ERR_NOMEM; | ||||||
|  |             goto cleanup; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // setup program cache |     // setup program cache | ||||||
|     lfs->pcache.block = 0xffffffff; |  | ||||||
|     if (lfs->cfg->prog_buffer) { |     if (lfs->cfg->prog_buffer) { | ||||||
|         lfs->pcache.buffer = lfs->cfg->prog_buffer; |         lfs->pcache.buffer = lfs->cfg->prog_buffer; | ||||||
|     } else { |     } else { | ||||||
|         lfs->pcache.buffer = lfs_malloc(lfs->cfg->cache_size); |         lfs->pcache.buffer = lfs_malloc(lfs->cfg->cache_size); | ||||||
|         if (!lfs->pcache.buffer) { |         if (!lfs->pcache.buffer) { | ||||||
|             return LFS_ERR_NOMEM; |             err = LFS_ERR_NOMEM; | ||||||
|  |             goto cleanup; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // zero to avoid information leaks | ||||||
|  |     lfs_cache_zero(lfs, &lfs->rcache); | ||||||
|  |     lfs_cache_zero(lfs, &lfs->pcache); | ||||||
|  |  | ||||||
|     // setup lookahead, must be multiple of 32-bits |     // setup lookahead, must be multiple of 32-bits | ||||||
|     LFS_ASSERT(lfs->cfg->lookahead % 32 == 0); |     LFS_ASSERT(lfs->cfg->lookahead % 32 == 0); | ||||||
|     LFS_ASSERT(lfs->cfg->lookahead > 0); |     LFS_ASSERT(lfs->cfg->lookahead > 0); | ||||||
| @@ -2738,7 +2789,8 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     } else { |     } else { | ||||||
|         lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8); |         lfs->free.buffer = lfs_malloc(lfs->cfg->lookahead/8); | ||||||
|         if (!lfs->free.buffer) { |         if (!lfs->free.buffer) { | ||||||
|             return LFS_ERR_NOMEM; |             err = LFS_ERR_NOMEM; | ||||||
|  |             goto cleanup; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2773,6 +2825,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs_globalzero(&lfs->locals); |     lfs_globalzero(&lfs->locals); | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|  | cleanup: | ||||||
|  |     lfs_deinit(lfs); | ||||||
|  |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_deinit(lfs_t *lfs) { | static int lfs_deinit(lfs_t *lfs) { | ||||||
| @@ -2809,19 +2865,19 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs_mdir_t dir; |     lfs_mdir_t dir; | ||||||
|     err = lfs_dir_alloc(lfs, &dir); |     err = lfs_dir_alloc(lfs, &dir); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // write root directory |     // write root directory | ||||||
|     lfs_mdir_t root; |     lfs_mdir_t root; | ||||||
|     err = lfs_dir_alloc(lfs, &root); |     err = lfs_dir_alloc(lfs, &root); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = lfs_dir_commit(lfs, &root, NULL); |     err = lfs_dir_commit(lfs, &root, NULL); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     lfs->root[0] = root.pair[0]; |     lfs->root[0] = root.pair[0]; | ||||||
| @@ -2850,16 +2906,18 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs_pairfromle32(lfs->root); |     lfs_pairfromle32(lfs->root); | ||||||
|     lfs_superblockfromle32(&superblock); |     lfs_superblockfromle32(&superblock); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // sanity check that fetch works |     // sanity check that fetch works | ||||||
|     err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); |     err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1}); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return lfs_deinit(lfs); | cleanup: | ||||||
|  |     lfs_deinit(lfs); | ||||||
|  |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | ||||||
| @@ -2878,7 +2936,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs_mdir_t superdir; |     lfs_mdir_t superdir; | ||||||
|     err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1}); |     err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1}); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     lfs_superblock_t superblock; |     lfs_superblock_t superblock; | ||||||
| @@ -2886,7 +2944,8 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|             LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), |             LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)), | ||||||
|             &superblock); |             &superblock); | ||||||
|     if (res < 0) { |     if (res < 0) { | ||||||
|         return res; |         err = res; | ||||||
|  |         goto cleanup; | ||||||
|     } |     } | ||||||
|     lfs_superblockfromle32(&superblock); |     lfs_superblockfromle32(&superblock); | ||||||
|  |  | ||||||
| @@ -2899,24 +2958,28 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     uint16_t minor_version = (0xffff & (superblock.version >>  0)); |     uint16_t minor_version = (0xffff & (superblock.version >>  0)); | ||||||
|     if ((major_version != LFS_DISK_VERSION_MAJOR || |     if ((major_version != LFS_DISK_VERSION_MAJOR || | ||||||
|          minor_version > LFS_DISK_VERSION_MINOR)) { |          minor_version > LFS_DISK_VERSION_MINOR)) { | ||||||
|         LFS_ERROR("Invalid version %d.%d", major_version, minor_version); |         LFS_ERROR("Invalid version %"PRIu32".%"PRIu32, | ||||||
|         return LFS_ERR_INVAL; |                 major_version, minor_version); | ||||||
|  |         err = LFS_ERR_INVAL; | ||||||
|  |         goto cleanup; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     res = lfs_dir_get(lfs, &superdir, 0x7ffff000, |     res = lfs_dir_get(lfs, &superdir, 0x7ffff000, | ||||||
|             LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)), |             LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)), | ||||||
|             &lfs->root); |             &lfs->root); | ||||||
|     if (res < 0) { |     if (res < 0) { | ||||||
|         return res; |         err = res; | ||||||
|  |         goto cleanup; | ||||||
|     } |     } | ||||||
|     lfs_pairfromle32(lfs->root); |     lfs_pairfromle32(lfs->root); | ||||||
|  |  | ||||||
|     // check superblock configuration |     // check superblock configuration | ||||||
|     if (superblock.attr_max) { |     if (superblock.attr_max) { | ||||||
|         if (superblock.attr_max > lfs->attr_max) { |         if (superblock.attr_max > lfs->attr_max) { | ||||||
|             LFS_ERROR("Unsupported attr_max (%d > %d)", |             LFS_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")", | ||||||
|                     superblock.attr_max, lfs->attr_max); |                     superblock.attr_max, lfs->attr_max); | ||||||
|             return LFS_ERR_INVAL; |             err = LFS_ERR_INVAL; | ||||||
|  |             goto cleanup; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         lfs->attr_max = superblock.attr_max; |         lfs->attr_max = superblock.attr_max; | ||||||
| @@ -2924,9 +2987,10 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|  |  | ||||||
|     if (superblock.name_max) { |     if (superblock.name_max) { | ||||||
|         if (superblock.name_max > lfs->name_max) { |         if (superblock.name_max > lfs->name_max) { | ||||||
|             LFS_ERROR("Unsupported name_max (%d > %d)", |             LFS_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")", | ||||||
|                     superblock.name_max, lfs->name_max); |                     superblock.name_max, lfs->name_max); | ||||||
|             return LFS_ERR_INVAL; |             err = LFS_ERR_INVAL; | ||||||
|  |             goto cleanup; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         lfs->name_max = superblock.name_max; |         lfs->name_max = superblock.name_max; | ||||||
| @@ -2934,9 +2998,10 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|  |  | ||||||
|     if (superblock.inline_max) { |     if (superblock.inline_max) { | ||||||
|         if (superblock.inline_max > lfs->inline_max) { |         if (superblock.inline_max > lfs->inline_max) { | ||||||
|             LFS_ERROR("Unsupported inline_max (%d > %d)", |             LFS_ERROR("Unsupported inline_max (%"PRIu32" > %"PRIu32")", | ||||||
|                     superblock.inline_max, lfs->inline_max); |                     superblock.inline_max, lfs->inline_max); | ||||||
|             return LFS_ERR_INVAL; |             err = LFS_ERR_INVAL; | ||||||
|  |             goto cleanup; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         lfs->inline_max = superblock.inline_max; |         lfs->inline_max = superblock.inline_max; | ||||||
| @@ -2945,9 +3010,10 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     // scan for any global updates |     // scan for any global updates | ||||||
|     lfs_mdir_t dir = {.tail = {0, 1}}; |     lfs_mdir_t dir = {.tail = {0, 1}}; | ||||||
|     while (!lfs_pairisnull(dir.tail)) { |     while (!lfs_pairisnull(dir.tail)) { | ||||||
|         int err = lfs_dir_fetch(lfs, &dir, dir.tail); |         err = lfs_dir_fetch(lfs, &dir, dir.tail); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             err = LFS_ERR_INVAL; | ||||||
|  |             goto cleanup; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // xor together indirect deletes |         // xor together indirect deletes | ||||||
| @@ -2959,13 +3025,17 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs_globalxor(&lfs->globals, &lfs->locals); |     lfs_globalxor(&lfs->globals, &lfs->locals); | ||||||
|     lfs_globalzero(&lfs->locals); |     lfs_globalzero(&lfs->locals); | ||||||
|     if (!lfs_pairisnull(lfs->globals.s.movepair)) { |     if (!lfs_pairisnull(lfs->globals.s.movepair)) { | ||||||
|         LFS_DEBUG("Found move %d %d %d", |         LFS_DEBUG("Found move %"PRIu32" %"PRIu32" %"PRIu32, | ||||||
|                 lfs->globals.s.movepair[0], |                 lfs->globals.s.movepair[0], | ||||||
|                 lfs->globals.s.movepair[1], |                 lfs->globals.s.movepair[1], | ||||||
|                 lfs->globals.s.moveid); |                 lfs->globals.s.moveid); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|  | cleanup: | ||||||
|  |     lfs_unmount(lfs); | ||||||
|  |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| int lfs_unmount(lfs_t *lfs) { | int lfs_unmount(lfs_t *lfs) { | ||||||
| @@ -3009,7 +3079,7 @@ int lfs_fs_traverse(lfs_t *lfs, | |||||||
|             lfs_ctzfromle32(&ctz); |             lfs_ctzfromle32(&ctz); | ||||||
|  |  | ||||||
|             if (lfs_tagtype(tag) == LFS_TYPE_CTZSTRUCT) { |             if (lfs_tagtype(tag) == LFS_TYPE_CTZSTRUCT) { | ||||||
|                 int err = lfs_ctztraverse(lfs, &lfs->rcache, NULL, |                 err = lfs_ctztraverse(lfs, &lfs->rcache, NULL, | ||||||
|                         ctz.head, ctz.size, cb, data); |                         ctz.head, ctz.size, cb, data); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
| @@ -3099,7 +3169,8 @@ static int lfs_fs_relocate(lfs_t *lfs, | |||||||
|         const lfs_block_t oldpair[2], lfs_block_t newpair[2]) { |         const lfs_block_t oldpair[2], lfs_block_t newpair[2]) { | ||||||
|     // update internal root |     // update internal root | ||||||
|     if (lfs_paircmp(oldpair, lfs->root) == 0) { |     if (lfs_paircmp(oldpair, lfs->root) == 0) { | ||||||
|         LFS_DEBUG("Relocating root %d %d", newpair[0], newpair[1]); |         LFS_DEBUG("Relocating root %"PRIu32" %"PRIu32, | ||||||
|  |                 newpair[0], newpair[1]); | ||||||
|         lfs->root[0] = newpair[0]; |         lfs->root[0] = newpair[0]; | ||||||
|         lfs->root[1] = newpair[1]; |         lfs->root[1] = newpair[1]; | ||||||
|     } |     } | ||||||
| @@ -3144,7 +3215,7 @@ static int lfs_fs_relocate(lfs_t *lfs, | |||||||
|         // just replace bad pair, no desync can occur |         // just replace bad pair, no desync can occur | ||||||
|         parent.tail[0] = newpair[0]; |         parent.tail[0] = newpair[0]; | ||||||
|         parent.tail[1] = newpair[1]; |         parent.tail[1] = newpair[1]; | ||||||
|         int err = lfs_dir_commit(lfs, &parent, |         err = lfs_dir_commit(lfs, &parent, | ||||||
|                 LFS_MKATTR(LFS_TYPE_TAIL + parent.split, 0x3ff, |                 LFS_MKATTR(LFS_TYPE_TAIL + parent.split, 0x3ff, | ||||||
|                     parent.tail, sizeof(parent.tail), |                     parent.tail, sizeof(parent.tail), | ||||||
|                 NULL)); |                 NULL)); | ||||||
| @@ -3158,7 +3229,7 @@ static int lfs_fs_relocate(lfs_t *lfs, | |||||||
|  |  | ||||||
| static int lfs_fs_forceconsistency(lfs_t *lfs) { | static int lfs_fs_forceconsistency(lfs_t *lfs) { | ||||||
|     if (!lfs->globals.s.deorphaned) { |     if (!lfs->globals.s.deorphaned) { | ||||||
|         LFS_DEBUG("Found orphans %d", |         LFS_DEBUG("Found orphans %"PRIu32, | ||||||
|                 lfs->globals.s.deorphaned); |                 lfs->globals.s.deorphaned); | ||||||
|  |  | ||||||
|         // Fix any orphans |         // Fix any orphans | ||||||
| @@ -3183,7 +3254,7 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) { | |||||||
|  |  | ||||||
|                 if (tag == LFS_ERR_NOENT) { |                 if (tag == LFS_ERR_NOENT) { | ||||||
|                     // we are an orphan |                     // we are an orphan | ||||||
|                     LFS_DEBUG("Fixing orphan %d %d", |                     LFS_DEBUG("Fixing orphan %"PRIu32" %"PRIu32, | ||||||
|                             pdir.tail[0], pdir.tail[1]); |                             pdir.tail[0], pdir.tail[1]); | ||||||
|  |  | ||||||
|                     pdir.tail[0] = dir.tail[0]; |                     pdir.tail[0] = dir.tail[0]; | ||||||
| @@ -3208,7 +3279,8 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) { | |||||||
|  |  | ||||||
|                 if (!lfs_pairsync(pair, pdir.tail)) { |                 if (!lfs_pairsync(pair, pdir.tail)) { | ||||||
|                     // we have desynced |                     // we have desynced | ||||||
|                     LFS_DEBUG("Fixing half-orphan %d %d", pair[0], pair[1]); |                     LFS_DEBUG("Fixing half-orphan %"PRIu32" %"PRIu32, | ||||||
|  |                             pair[0], pair[1]); | ||||||
|  |  | ||||||
|                     pdir.tail[0] = pair[0]; |                     pdir.tail[0] = pair[0]; | ||||||
|                     pdir.tail[1] = pair[1]; |                     pdir.tail[1] = pair[1]; | ||||||
| @@ -3233,7 +3305,7 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) { | |||||||
|  |  | ||||||
|     if (lfs->globals.s.moveid != 0x3ff) { |     if (lfs->globals.s.moveid != 0x3ff) { | ||||||
|         // Fix bad moves |         // Fix bad moves | ||||||
|         LFS_DEBUG("Fixing move %d %d %d", |         LFS_DEBUG("Fixing move %"PRIu32" %"PRIu32" %"PRIu32, | ||||||
|                 lfs->globals.s.movepair[0], |                 lfs->globals.s.movepair[0], | ||||||
|                 lfs->globals.s.movepair[1], |                 lfs->globals.s.movepair[1], | ||||||
|                 lfs->globals.s.moveid); |                 lfs->globals.s.moveid); | ||||||
| @@ -3291,6 +3363,7 @@ int lfs_fs_setattr(lfs_t *lfs, | |||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_fs_size_count(void *p, lfs_block_t block) { | static int lfs_fs_size_count(void *p, lfs_block_t block) { | ||||||
|  |     (void)block; | ||||||
|     lfs_size_t *size = p; |     lfs_size_t *size = p; | ||||||
|     *size += 1; |     *size += 1; | ||||||
|     return 0; |     return 0; | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -1,19 +1,8 @@ | |||||||
| /* | /* | ||||||
|  * The little filesystem |  * The little filesystem | ||||||
|  * |  * | ||||||
|  * Copyright (c) 2017 ARM Limited |  * Copyright (c) 2017, Arm Limited. All rights reserved. | ||||||
|  * |  * SPDX-License-Identifier: BSD-3-Clause | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  */ | ||||||
| #ifndef LFS_H | #ifndef LFS_H | ||||||
| #define LFS_H | #define LFS_H | ||||||
| @@ -21,6 +10,11 @@ | |||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" | ||||||
|  | { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Version info /// | /// Version info /// | ||||||
|  |  | ||||||
| @@ -481,7 +475,6 @@ int lfs_setattr(lfs_t *lfs, const char *path, | |||||||
| int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | ||||||
|         const char *path, int flags); |         const char *path, int flags); | ||||||
|  |  | ||||||
|  |  | ||||||
| // Open a file with extra configuration | // Open a file with extra configuration | ||||||
| // | // | ||||||
| // The mode that the file is opened in is determined by the flags, which | // The mode that the file is opened in is determined by the flags, which | ||||||
| @@ -653,4 +646,8 @@ int lfs_fs_setattr(lfs_t *lfs, | |||||||
|         uint8_t type, const void *buffer, lfs_size_t size); |         uint8_t type, const void *buffer, lfs_size_t size); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } /* extern "C" */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								lfs_util.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								lfs_util.c
									
									
									
									
									
								
							| @@ -1,19 +1,8 @@ | |||||||
| /* | /* | ||||||
|  * lfs util functions |  * lfs util functions | ||||||
|  * |  * | ||||||
|  * Copyright (c) 2017 ARM Limited |  * Copyright (c) 2017, Arm Limited. All rights reserved. | ||||||
|  * |  * SPDX-License-Identifier: BSD-3-Clause | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  */ | ||||||
| #include "lfs_util.h" | #include "lfs_util.h" | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								lfs_util.h
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								lfs_util.h
									
									
									
									
									
								
							| @@ -1,19 +1,8 @@ | |||||||
| /* | /* | ||||||
|  * lfs utility functions |  * lfs utility functions | ||||||
|  * |  * | ||||||
|  * Copyright (c) 2017 ARM Limited |  * Copyright (c) 2017, Arm Limited. All rights reserved. | ||||||
|  * |  * SPDX-License-Identifier: BSD-3-Clause | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  | ||||||
|  * you may not use this file except in compliance with the License. |  | ||||||
|  * You may obtain a copy of the License at |  | ||||||
|  * |  | ||||||
|  *     http://www.apache.org/licenses/LICENSE-2.0 |  | ||||||
|  * |  | ||||||
|  * Unless required by applicable law or agreed to in writing, software |  | ||||||
|  * distributed under the License is distributed on an "AS IS" BASIS, |  | ||||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |  | ||||||
|  * See the License for the specific language governing permissions and |  | ||||||
|  * limitations under the License. |  | ||||||
|  */ |  */ | ||||||
| #ifndef LFS_UTIL_H | #ifndef LFS_UTIL_H | ||||||
| #define LFS_UTIL_H | #define LFS_UTIL_H | ||||||
| @@ -34,6 +23,7 @@ | |||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <inttypes.h> | ||||||
|  |  | ||||||
| #ifndef LFS_NO_MALLOC | #ifndef LFS_NO_MALLOC | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| @@ -45,6 +35,11 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" | ||||||
|  | { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| // Macros, may be replaced by system specific wrappers. Arguments to these | // Macros, may be replaced by system specific wrappers. Arguments to these | ||||||
| // macros must not have side-effects as the macros can be removed for a smaller | // macros must not have side-effects as the macros can be removed for a smaller | ||||||
| @@ -199,6 +194,7 @@ static inline void *lfs_malloc(size_t size) { | |||||||
| #ifndef LFS_NO_MALLOC | #ifndef LFS_NO_MALLOC | ||||||
|     return malloc(size); |     return malloc(size); | ||||||
| #else | #else | ||||||
|  |     (void)size; | ||||||
|     return NULL; |     return NULL; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @@ -207,9 +203,15 @@ static inline void *lfs_malloc(size_t size) { | |||||||
| static inline void lfs_free(void *p) { | static inline void lfs_free(void *p) { | ||||||
| #ifndef LFS_NO_MALLOC | #ifndef LFS_NO_MALLOC | ||||||
|     free(p); |     free(p); | ||||||
|  | #else | ||||||
|  |     (void)p; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } /* extern "C" */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ TEST | |||||||
|  |  | ||||||
| w_test() { | w_test() { | ||||||
| tests/test.py << TEST | tests/test.py << TEST | ||||||
|     lfs_size_t size = $1; |     size = $1; | ||||||
|     lfs_size_t chunk = 31; |     lfs_size_t chunk = 31; | ||||||
|     srand(0); |     srand(0); | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
| @@ -50,7 +50,7 @@ TEST | |||||||
|  |  | ||||||
| r_test() { | r_test() { | ||||||
| tests/test.py << TEST | tests/test.py << TEST | ||||||
|     lfs_size_t size = $1; |     size = $1; | ||||||
|     lfs_size_t chunk = 29; |     lfs_size_t chunk = 29; | ||||||
|     srand(0); |     srand(0); | ||||||
|     lfs_mount(&lfs, &cfg) => 0; |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|   | |||||||
| @@ -153,7 +153,7 @@ tests/test.py << TEST | |||||||
|     lfs_file_read(&lfs, &file[0], buffer, size) => size; |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|     memcmp(buffer, "kittycatcat", size) => 0; |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|     lfs_size_t size = lfs_file_size(&lfs, &file[0]); |     size = lfs_file_size(&lfs, &file[0]); | ||||||
|     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|     lfs_file_close(&lfs, &file[0]) => 0; |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
| @@ -202,7 +202,7 @@ tests/test.py << TEST | |||||||
|     lfs_file_read(&lfs, &file[0], buffer, size) => size; |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|     memcmp(buffer, "kittycatcat", size) => 0; |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|     lfs_size_t size = lfs_file_size(&lfs, &file[0]); |     size = lfs_file_size(&lfs, &file[0]); | ||||||
|     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|     lfs_file_close(&lfs, &file[0]) => 0; |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
| @@ -243,7 +243,7 @@ tests/test.py << TEST | |||||||
|     lfs_file_read(&lfs, &file[0], buffer, size) => size; |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|     memcmp(buffer, "kittycatcat", size) => 0; |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|     lfs_size_t size = lfs_file_size(&lfs, &file[0]); |     size = lfs_file_size(&lfs, &file[0]); | ||||||
|     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|     lfs_file_close(&lfs, &file[0]) => 0; |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
| @@ -286,7 +286,7 @@ tests/test.py << TEST | |||||||
|     lfs_file_read(&lfs, &file[0], buffer, size) => size; |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|     memcmp(buffer, "kittycatcat", size) => 0; |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|     lfs_size_t size = lfs_file_size(&lfs, &file[0]); |     size = lfs_file_size(&lfs, &file[0]); | ||||||
|     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|     lfs_file_close(&lfs, &file[0]) => 0; |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user