Explorar o código

Merge branch 'master' of https://github.com/geky/littlefs

xieyangrun %!s(int64=7) %!d(string=hai) anos
pai
achega
aea3d777de
Modificáronse 5 ficheiros con 120 adicións e 36 borrados
  1. 1 0
      .travis.yml
  2. 15 0
      README.md
  3. 35 33
      lfs.c
  4. 8 1
      lfs.h
  5. 61 2
      tests/test_dirs.sh

+ 1 - 0
.travis.yml

@@ -182,6 +182,7 @@ jobs:
                   -d "{
                   -d "{
                       \"tag_name\": \"$LFS_VERSION\",
                       \"tag_name\": \"$LFS_VERSION\",
                       \"name\": \"${LFS_VERSION%.0}\",
                       \"name\": \"${LFS_VERSION%.0}\",
+                      \"draft\": true,
                       \"body\": $(jq -sR '.' <<< "$CHANGES")
                       \"body\": $(jq -sR '.' <<< "$CHANGES")
                   }"
                   }"
             fi
             fi

+ 15 - 0
README.md

@@ -175,3 +175,18 @@ handy.
 [littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for
 [littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for
 littlefs. I'm not sure why you would want this, but it is handy for demos.
 littlefs. I'm not sure why you would want this, but it is handy for demos.
 You can see it in action [here](http://littlefs.geky.net/demo.html).
 You can see it in action [here](http://littlefs.geky.net/demo.html).
+
+[mklfs](https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src) -
+A command line tool built by the [Lua RTOS](https://github.com/whitecatboard/Lua-RTOS-ESP32)
+guys for making littlefs images from a host PC. Supports Windows, Mac OS,
+and Linux.
+
+[SPIFFS](https://github.com/pellepl/spiffs) - Another excellent embedded
+filesystem for NOR flash. As a more traditional logging filesystem with full
+static wear-leveling, SPIFFS will likely outperform littlefs on small
+memories such as the internal flash on microcontrollers.
+
+[Dhara](https://github.com/dlbeer/dhara) - An interesting NAND flash
+translation layer designed for small MCUs. It offers static wear-leveling and
+power-resilience with only a fixed O(|address|) pointer structure stored on
+each block and in RAM.

+ 35 - 33
lfs.c

@@ -888,7 +888,7 @@ nextname:
         }
         }
 
 
         // check that entry has not been moved
         // check that entry has not been moved
-        if (entry->d.type & 0x80) {
+        if (!lfs->moving && entry->d.type & 0x80) {
             int moved = lfs_moved(lfs, &entry->d.u);
             int moved = lfs_moved(lfs, &entry->d.u);
             if (moved < 0 || moved) {
             if (moved < 0 || moved) {
                 return (moved < 0) ? moved : LFS_ERR_NOENT;
                 return (moved < 0) ? moved : LFS_ERR_NOENT;
@@ -1644,6 +1644,11 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
         file->pos = file->size;
         file->pos = file->size;
     }
     }
 
 
+    if (file->pos + size > LFS_FILE_MAX) {
+        // larger than file limit?
+        return LFS_ERR_FBIG;
+    }
+
     if (!(file->flags & LFS_F_WRITING) && file->pos > file->size) {
     if (!(file->flags & LFS_F_WRITING) && file->pos > file->size) {
         // fill with zeros
         // fill with zeros
         lfs_off_t pos = file->pos;
         lfs_off_t pos = file->pos;
@@ -1730,24 +1735,24 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
         return err;
         return err;
     }
     }
 
 
-    // update pos
+    // find new pos
+    lfs_soff_t npos = file->pos;
     if (whence == LFS_SEEK_SET) {
     if (whence == LFS_SEEK_SET) {
-        file->pos = off;
+        npos = off;
     } else if (whence == LFS_SEEK_CUR) {
     } else if (whence == LFS_SEEK_CUR) {
-        if (off < 0 && (lfs_off_t)-off > file->pos) {
-            return LFS_ERR_INVAL;
-        }
-
-        file->pos = file->pos + off;
+        npos = file->pos + off;
     } else if (whence == LFS_SEEK_END) {
     } else if (whence == LFS_SEEK_END) {
-        if (off < 0 && (lfs_off_t)-off > file->size) {
-            return LFS_ERR_INVAL;
-        }
+        npos = file->size + off;
+    }
 
 
-        file->pos = file->size + off;
+    if (npos < 0 || npos > LFS_FILE_MAX) {
+        // file position out of range
+        return LFS_ERR_INVAL;
     }
     }
 
 
-    return file->pos;
+    // update pos
+    file->pos = npos;
+    return npos;
 }
 }
 
 
 int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
 int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
@@ -1922,7 +1927,14 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
     // find old entry
     // find old entry
     lfs_dir_t oldcwd;
     lfs_dir_t oldcwd;
     lfs_entry_t oldentry;
     lfs_entry_t oldentry;
-    int err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
+    int err = lfs_dir_find(lfs, &oldcwd, &oldentry, &(const char *){oldpath});
+    if (err) {
+        return err;
+    }
+
+    // mark as moving
+    oldentry.d.type |= 0x80;
+    err = lfs_dir_update(lfs, &oldcwd, &oldentry, NULL);
     if (err) {
     if (err) {
         return err;
         return err;
     }
     }
@@ -1935,11 +1947,9 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
         return err;
         return err;
     }
     }
 
 
-    bool prevexists = (err != LFS_ERR_NOENT);
-    bool samepair = (lfs_paircmp(oldcwd.pair, newcwd.pair) == 0);
-
     // must have same type
     // must have same type
-    if (prevexists && preventry.d.type != oldentry.d.type) {
+    bool prevexists = (err != LFS_ERR_NOENT);
+    if (prevexists && preventry.d.type != (0x7f & oldentry.d.type)) {
         return LFS_ERR_ISDIR;
         return LFS_ERR_ISDIR;
     }
     }
 
 
@@ -1956,18 +1966,6 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
         }
         }
     }
     }
 
 
-    // mark as moving
-    oldentry.d.type |= 0x80;
-    err = lfs_dir_update(lfs, &oldcwd, &oldentry, NULL);
-    if (err) {
-        return err;
-    }
-
-    // update pair if newcwd == oldcwd
-    if (samepair) {
-        newcwd = oldcwd;
-    }
-
     // move to new location
     // move to new location
     lfs_entry_t newentry = preventry;
     lfs_entry_t newentry = preventry;
     newentry.d = oldentry.d;
     newentry.d = oldentry.d;
@@ -1986,10 +1984,13 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
         }
         }
     }
     }
 
 
-    // update pair if newcwd == oldcwd
-    if (samepair) {
-        oldcwd = newcwd;
+    // fetch old pair again in case dir block changed
+    lfs->moving = true;
+    err = lfs_dir_find(lfs, &oldcwd, &oldentry, &oldpath);
+    if (err) {
+        return err;
     }
     }
+    lfs->moving = false;
 
 
     // remove old entry
     // remove old entry
     err = lfs_dir_remove(lfs, &oldcwd, &oldentry);
     err = lfs_dir_remove(lfs, &oldcwd, &oldentry);
@@ -2087,6 +2088,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
     lfs->files = NULL;
     lfs->files = NULL;
     lfs->dirs = NULL;
     lfs->dirs = NULL;
     lfs->deorphaned = false;
     lfs->deorphaned = false;
+    lfs->moving = false;
 
 
     return 0;
     return 0;
 
 

+ 8 - 1
lfs.h

@@ -21,7 +21,7 @@ extern "C"
 // Software library version
 // Software library version
 // Major (top-nibble), incremented on backwards incompatible changes
 // Major (top-nibble), incremented on backwards incompatible changes
 // Minor (bottom-nibble), incremented on feature additions
 // Minor (bottom-nibble), incremented on feature additions
-#define LFS_VERSION 0x00010006
+#define LFS_VERSION 0x00010007
 #define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
 #define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
 #define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >>  0))
 #define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >>  0))
 
 
@@ -49,6 +49,11 @@ typedef uint32_t lfs_block_t;
 #define LFS_NAME_MAX 255
 #define LFS_NAME_MAX 255
 #endif
 #endif
 
 
+// Max file size in bytes
+#ifndef LFS_FILE_MAX
+#define LFS_FILE_MAX 2147483647
+#endif
+
 // Possible error codes, these are negative to allow
 // Possible error codes, these are negative to allow
 // valid positive return values
 // valid positive return values
 enum lfs_error {
 enum lfs_error {
@@ -61,6 +66,7 @@ enum lfs_error {
     LFS_ERR_ISDIR    = -21,  // Entry is a dir
     LFS_ERR_ISDIR    = -21,  // Entry is a dir
     LFS_ERR_NOTEMPTY = -39,  // Dir is not empty
     LFS_ERR_NOTEMPTY = -39,  // Dir is not empty
     LFS_ERR_BADF     = -9,   // Bad file number
     LFS_ERR_BADF     = -9,   // Bad file number
+    LFS_ERR_FBIG     = -27,  // File too large
     LFS_ERR_INVAL    = -22,  // Invalid parameter
     LFS_ERR_INVAL    = -22,  // Invalid parameter
     LFS_ERR_NOSPC    = -28,  // No space left on device
     LFS_ERR_NOSPC    = -28,  // No space left on device
     LFS_ERR_NOMEM    = -12,  // No more memory available
     LFS_ERR_NOMEM    = -12,  // No more memory available
@@ -280,6 +286,7 @@ typedef struct lfs {
 
 
     lfs_free_t free;
     lfs_free_t free;
     bool deorphaned;
     bool deorphaned;
+    bool moving;
 } lfs_t;
 } lfs_t;
 
 
 
 

+ 61 - 2
tests/test_dirs.sh

@@ -326,13 +326,42 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 
 
+echo "--- Multi-block rename ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    for (int i = 0; i < $LARGESIZE; i++) {
+        sprintf((char*)buffer, "cactus/test%d", i);
+        sprintf((char*)wbuffer, "cactus/tedd%d", i);
+        lfs_rename(&lfs, (char*)buffer, (char*)wbuffer) => 0;
+    }
+    lfs_unmount(&lfs) => 0;
+TEST
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_dir_open(&lfs, &dir[0], "cactus") => 0;
+    lfs_dir_read(&lfs, &dir[0], &info) => 1;
+    strcmp(info.name, ".") => 0;
+    info.type => LFS_TYPE_DIR;
+    lfs_dir_read(&lfs, &dir[0], &info) => 1;
+    strcmp(info.name, "..") => 0;
+    info.type => LFS_TYPE_DIR;
+    for (int i = 0; i < $LARGESIZE; i++) {
+        sprintf((char*)buffer, "tedd%d", i);
+        lfs_dir_read(&lfs, &dir[0], &info) => 1;
+        strcmp(info.name, (char*)buffer) => 0;
+        info.type => LFS_TYPE_DIR;
+    }
+    lfs_dir_read(&lfs, &dir[0], &info) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+
 echo "--- Multi-block remove ---"
 echo "--- Multi-block remove ---"
 tests/test.py << TEST
 tests/test.py << TEST
     lfs_mount(&lfs, &cfg) => 0;
     lfs_mount(&lfs, &cfg) => 0;
     lfs_remove(&lfs, "cactus") => LFS_ERR_NOTEMPTY;
     lfs_remove(&lfs, "cactus") => LFS_ERR_NOTEMPTY;
 
 
     for (int i = 0; i < $LARGESIZE; i++) {
     for (int i = 0; i < $LARGESIZE; i++) {
-        sprintf((char*)buffer, "cactus/test%d", i);
+        sprintf((char*)buffer, "cactus/tedd%d", i);
         lfs_remove(&lfs, (char*)buffer) => 0;
         lfs_remove(&lfs, (char*)buffer) => 0;
     }
     }
 
 
@@ -391,13 +420,43 @@ tests/test.py << TEST
     lfs_unmount(&lfs) => 0;
     lfs_unmount(&lfs) => 0;
 TEST
 TEST
 
 
+echo "--- Multi-block rename with files ---"
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    for (int i = 0; i < $LARGESIZE; i++) {
+        sprintf((char*)buffer, "prickly-pear/test%d", i);
+        sprintf((char*)wbuffer, "prickly-pear/tedd%d", i);
+        lfs_rename(&lfs, (char*)buffer, (char*)wbuffer) => 0;
+    }
+    lfs_unmount(&lfs) => 0;
+TEST
+tests/test.py << TEST
+    lfs_mount(&lfs, &cfg) => 0;
+    lfs_dir_open(&lfs, &dir[0], "prickly-pear") => 0;
+    lfs_dir_read(&lfs, &dir[0], &info) => 1;
+    strcmp(info.name, ".") => 0;
+    info.type => LFS_TYPE_DIR;
+    lfs_dir_read(&lfs, &dir[0], &info) => 1;
+    strcmp(info.name, "..") => 0;
+    info.type => LFS_TYPE_DIR;
+    for (int i = 0; i < $LARGESIZE; i++) {
+        sprintf((char*)buffer, "tedd%d", i);
+        lfs_dir_read(&lfs, &dir[0], &info) => 1;
+        strcmp(info.name, (char*)buffer) => 0;
+        info.type => LFS_TYPE_REG;
+        info.size => 6;
+    }
+    lfs_dir_read(&lfs, &dir[0], &info) => 0;
+    lfs_unmount(&lfs) => 0;
+TEST
+
 echo "--- Multi-block remove with files ---"
 echo "--- Multi-block remove with files ---"
 tests/test.py << TEST
 tests/test.py << TEST
     lfs_mount(&lfs, &cfg) => 0;
     lfs_mount(&lfs, &cfg) => 0;
     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY;
     lfs_remove(&lfs, "prickly-pear") => LFS_ERR_NOTEMPTY;
 
 
     for (int i = 0; i < $LARGESIZE; i++) {
     for (int i = 0; i < $LARGESIZE; i++) {
-        sprintf((char*)buffer, "prickly-pear/test%d", i);
+        sprintf((char*)buffer, "prickly-pear/tedd%d", i);
         lfs_remove(&lfs, (char*)buffer) => 0;
         lfs_remove(&lfs, (char*)buffer) => 0;
     }
     }