Ver código fonte

Separated out version of dir remove/append for non-entries

This allows updates to directories without needing to allocate an entry
struct for every call.
Christopher Haster 7 anos atrás
pai
commit
03b262b1e8
1 arquivos alterados com 91 adições e 86 exclusões
  1. 91 86
      lfs.c

+ 91 - 86
lfs.c

@@ -677,15 +677,14 @@ relocate:
     return 0;
 }
 
-static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
-        lfs_entry_t *entry, struct lfs_region *regions) {
+static int lfs_dir_append_(lfs_t *lfs, lfs_dir_t *dir,
+        lfs_off_t *off, lfs_size_t size, struct lfs_region *regions) {
     // check if we fit, if top bit is set we do not and move on
     while (true) {
-        if ((0x7fffffff & dir->d.size) + lfs_entry_size(entry)
-                <= lfs->cfg->block_size) {
-            entry->off = dir->d.size - 4;
+        if ((0x7fffffff & dir->d.size) + size <= lfs->cfg->block_size) {
+            *off = dir->d.size - 4;
             for (struct lfs_region *r = regions; r; r = r->next) {
-                r->off += entry->off;
+                r->off += *off;
             }
 
             return lfs_dir_commit(lfs, dir, regions);
@@ -701,9 +700,9 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
 
             dir->d.tail[0] = olddir.d.tail[0];
             dir->d.tail[1] = olddir.d.tail[1];
-            entry->off = dir->d.size - 4;
+            *off = dir->d.size - 4;
             for (struct lfs_region *r = regions; r; r = r->next) {
-                r->off += entry->off;
+                r->off += *off;
             }
 
             err = lfs_dir_commit(lfs, dir, regions);
@@ -724,9 +723,70 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
     }
 }
 
+static int lfs_dir_remove_(lfs_t *lfs, lfs_dir_t *dir,
+        lfs_off_t off, lfs_size_t size) {
+    // check if we should just drop the directory block
+    if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + size) {
+        lfs_dir_t pdir;
+        int res = lfs_pred(lfs, dir->pair, &pdir);
+        if (res < 0) {
+            return res;
+        }
+
+        if (pdir.d.size & 0x80000000) {
+            pdir.d.size &= dir->d.size | 0x7fffffff;
+            pdir.d.tail[0] = dir->d.tail[0];
+            pdir.d.tail[1] = dir->d.tail[1];
+            return lfs_dir_commit(lfs, &pdir, NULL);
+        }
+    }
+
+    // shift out the entry
+    int err = lfs_dir_commit(lfs, dir,
+            &(struct lfs_region){
+                off, -size,
+                lfs_commit_mem, NULL, 0});
+    if (err) {
+        return err;
+    }
+
+    // shift over any files/directories that are affected
+    for (lfs_file_t *f = lfs->files; f; f = f->next) {
+        if (lfs_paircmp(f->pair, dir->pair) == 0) {
+            if (f->poff == off) {
+                f->pair[0] = 0xffffffff;
+                f->pair[1] = 0xffffffff;
+            } else if (f->poff > off) {
+                f->poff -= size;
+            }
+        }
+    }
+
+    for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
+        if (lfs_paircmp(d->pair, dir->pair) == 0) {
+            if (d->off > off) {
+                d->off -= size;
+                d->pos -= size;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
+        lfs_entry_t *entry, struct lfs_region *regions) {
+    return lfs_dir_append_(lfs, dir,
+            &entry->off, lfs_entry_size(entry), regions);
+}
+
+static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
+    return lfs_dir_remove_(lfs, dir,
+            entry->off, lfs_entry_size(entry));
+}
+
 static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
         lfs_entry_t *entry, struct lfs_region *regions) {
-    lfs_off_t oldoff = entry->off; // <- TODO rm me?
     lfs_ssize_t diff = 0;
     for (struct lfs_region *r = regions; r; r = r->next) {
         diff += r->diff;
@@ -742,6 +802,24 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
         if (err) {
             return err;
         }
+
+        // shift over any files/directories that are affected
+        for (lfs_file_t *f = lfs->files; f; f = f->next) {
+            if (lfs_paircmp(f->pair, dir->pair) == 0) {
+                if (f->poff > entry->off) {
+                    f->poff += diff;
+                }
+            }
+        }
+
+        for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
+            if (lfs_paircmp(d->pair, dir->pair) == 0) {
+                if (d->off > entry->off) {
+                    d->off += diff;
+                    d->pos += diff;
+                }
+            }
+        }
     } else {
         lfs_dir_t olddir = *dir;
         lfs_off_t oldoff = entry->off;
@@ -756,9 +834,9 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
         if (err) {
             return err;
         }
+        entry->d.type &= LFS_STRUCT_MOVED;
 
         // append updated entry
-        entry->d.type &= LFS_STRUCT_MOVED;
         err = lfs_dir_append(lfs, dir, entry,
                 &(struct lfs_region){
                     0, +lfs_entry_size(entry),
@@ -769,86 +847,13 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
         }
 
         // remove old entry
-        err = lfs_dir_commit(lfs, &olddir,
-                &(struct lfs_region){
-                    oldoff, -oldsize,
-                    lfs_commit_mem, NULL, 0});
+        err = lfs_dir_remove_(lfs, dir, oldoff, oldsize);
         if (err) {
             return err;
         }
-    }
 
-    // TODO move to dir_commit?
-    // TODO this doesn't work...
-    // shift over any files/directories that are affected
-    for (lfs_file_t *f = lfs->files; f; f = f->next) {
-        if (lfs_paircmp(f->pair, dir->pair) == 0) {
-            if (f->poff == oldoff) {
-                f->poff = entry->off;
-            } else if (f->poff > entry->off) {
-                f->poff += diff;
-            }
-        }
-    }
-
-    for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
-        if (lfs_paircmp(d->pair, dir->pair) == 0) {
-            if (d->off > entry->off) {
-                d->off += diff;
-                d->pos += diff;
-            }
-        }
-    }
-
-    return 0;
-}
-
-static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
-    // check if we should just drop the directory block
-    if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4
-            + lfs_entry_size(entry)) {
-        lfs_dir_t pdir;
-        int res = lfs_pred(lfs, dir->pair, &pdir);
-        if (res < 0) {
-            return res;
-        }
-
-        if (pdir.d.size & 0x80000000) {
-            pdir.d.size &= dir->d.size | 0x7fffffff;
-            pdir.d.tail[0] = dir->d.tail[0];
-            pdir.d.tail[1] = dir->d.tail[1];
-            return lfs_dir_commit(lfs, &pdir, NULL);
-        }
-    }
-
-    // shift out the entry
-    int err = lfs_dir_commit(lfs, dir,
-            &(struct lfs_region){
-                entry->off, -lfs_entry_size(entry),
-                lfs_commit_mem, NULL, 0});
-    if (err) {
-        return err;
-    }
-
-    // shift over any files/directories that are affected
-    for (lfs_file_t *f = lfs->files; f; f = f->next) {
-        if (lfs_paircmp(f->pair, dir->pair) == 0) {
-            if (f->poff == entry->off) {
-                f->pair[0] = 0xffffffff;
-                f->pair[1] = 0xffffffff;
-            } else if (f->poff > entry->off) {
-                f->poff -= lfs_entry_size(entry);
-            }
-        }
-    }
-
-    for (lfs_dir_t *d = lfs->dirs; d; d = d->next) {
-        if (lfs_paircmp(d->pair, dir->pair) == 0) {
-            if (d->off > entry->off) {
-                d->off -= lfs_entry_size(entry);
-                d->pos -= lfs_entry_size(entry);
-            }
-        }
+        // TODO remove file under file?
+        // TODO need to shift entries?
     }
 
     return 0;