Separated type/struct fields in dir entries

The separation of data-structure vs entry type has been implicit for a
while now, and even taken advantage of to simplify the traverse logic.
This commit is contained in:
Christopher Haster
2018-03-03 10:26:06 -06:00
parent 9637b96069
commit 2a738463b3
2 changed files with 38 additions and 32 deletions

58
lfs.c
View File

@@ -793,7 +793,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
// special case for root dir // special case for root dir
if (pathname[0] == '\0') { if (pathname[0] == '\0') {
*entry = (lfs_entry_t){ *entry = (lfs_entry_t){
.d.type = LFS_TYPE_DIR, .d.type = LFS_STRUCT_DIR | LFS_TYPE_DIR,
.d.elen = sizeof(entry->d) - 4, .d.elen = sizeof(entry->d) - 4,
.d.alen = 0, .d.alen = 0,
.d.nlen = 0, .d.nlen = 0,
@@ -844,8 +844,8 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
return err; return err;
} }
if (((0x7f & entry->d.type) != LFS_TYPE_REG && if (((0x7f & entry->d.type) != (LFS_STRUCT_CTZ | LFS_TYPE_REG) &&
(0x7f & entry->d.type) != LFS_TYPE_DIR) || (0x7f & entry->d.type) != (LFS_STRUCT_DIR | LFS_TYPE_DIR)) ||
entry->d.nlen != pathlen) { entry->d.nlen != pathlen) {
continue; continue;
} }
@@ -864,13 +864,13 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
} }
// check that entry has not been moved // check that entry has not been moved
if (entry->d.type & 0x80) { if (entry->d.type & LFS_STRUCT_MOVED) {
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;
} }
entry->d.type &= ~0x80; entry->d.type &= ~LFS_STRUCT_MOVED;
} }
pathname += pathlen; pathname += pathlen;
@@ -880,7 +880,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
} }
// continue on if we hit a directory // continue on if we hit a directory
if (entry->d.type != LFS_TYPE_DIR) { if ((0xf & entry->d.type) != LFS_TYPE_DIR) {
return LFS_ERR_NOTDIR; return LFS_ERR_NOTDIR;
} }
@@ -931,7 +931,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
return err; return err;
} }
entry.d.type = LFS_TYPE_DIR; entry.d.type = LFS_STRUCT_DIR | LFS_TYPE_DIR;
entry.d.elen = sizeof(entry.d) - 4; entry.d.elen = sizeof(entry.d) - 4;
entry.d.alen = 0; entry.d.alen = 0;
entry.d.nlen = strlen(path); entry.d.nlen = strlen(path);
@@ -963,7 +963,7 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
err = lfs_dir_find(lfs, dir, &entry, &path); err = lfs_dir_find(lfs, dir, &entry, &path);
if (err) { if (err) {
return err; return err;
} else if (entry.d.type != LFS_TYPE_DIR) { } else if (entry.d.type != (LFS_STRUCT_DIR | LFS_TYPE_DIR)) {
return LFS_ERR_NOTDIR; return LFS_ERR_NOTDIR;
} }
@@ -1021,13 +1021,13 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
return (err == LFS_ERR_NOENT) ? 0 : err; return (err == LFS_ERR_NOENT) ? 0 : err;
} }
if ((0x7f & entry.d.type) != LFS_TYPE_REG && if ((0x7f & entry.d.type) != (LFS_STRUCT_CTZ | LFS_TYPE_REG) &&
(0x7f & entry.d.type) != LFS_TYPE_DIR) { (0x7f & entry.d.type) != (LFS_STRUCT_DIR | LFS_TYPE_DIR)) {
continue; continue;
} }
// check that entry has not been moved // check that entry has not been moved
if (entry.d.type & 0x80) { if (entry.d.type & LFS_STRUCT_MOVED) {
int moved = lfs_moved(lfs, &entry.d.u); int moved = lfs_moved(lfs, &entry.d.u);
if (moved < 0) { if (moved < 0) {
return moved; return moved;
@@ -1037,13 +1037,13 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
continue; continue;
} }
entry.d.type &= ~0x80; entry.d.type &= ~LFS_STRUCT_MOVED;
} }
break; break;
} }
info->type = entry.d.type; info->type = 0xf & entry.d.type;
if (info->type == LFS_TYPE_REG) { if (info->type == LFS_TYPE_REG) {
info->size = entry.d.u.file.size; info->size = entry.d.u.file.size;
} }
@@ -1319,7 +1319,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
} }
// create entry to remember name // create entry to remember name
entry.d.type = LFS_TYPE_REG; entry.d.type = LFS_STRUCT_CTZ | LFS_TYPE_REG;
entry.d.elen = sizeof(entry.d) - 4; entry.d.elen = sizeof(entry.d) - 4;
entry.d.alen = 0; entry.d.alen = 0;
entry.d.nlen = strlen(path); entry.d.nlen = strlen(path);
@@ -1329,7 +1329,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
if (err) { if (err) {
return err; return err;
} }
} else if (entry.d.type == LFS_TYPE_DIR) { } else if ((0xf & entry.d.type) == LFS_TYPE_DIR) {
return LFS_ERR_ISDIR; return LFS_ERR_ISDIR;
} else if (flags & LFS_O_EXCL) { } else if (flags & LFS_O_EXCL) {
return LFS_ERR_EXIST; return LFS_ERR_EXIST;
@@ -1537,7 +1537,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
return err; return err;
} }
LFS_ASSERT(entry.d.type == LFS_TYPE_REG); LFS_ASSERT(entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG));
entry.d.u.file.head = file->head; entry.d.u.file.head = file->head;
entry.d.u.file.size = file->size; entry.d.u.file.size = file->size;
@@ -1826,7 +1826,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
} }
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
info->type = entry.d.type; info->type = 0xf & entry.d.type;
if (info->type == LFS_TYPE_REG) { if (info->type == LFS_TYPE_REG) {
info->size = entry.d.u.file.size; info->size = entry.d.u.file.size;
} }
@@ -1867,7 +1867,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
} }
lfs_dir_t dir; lfs_dir_t dir;
if (entry.d.type == LFS_TYPE_DIR) { if ((0xf & entry.d.type) == LFS_TYPE_DIR) {
// must be empty before removal, checking size // must be empty before removal, checking size
// without masking top bit checks for any case where // without masking top bit checks for any case where
// dir is not empty // dir is not empty
@@ -1886,7 +1886,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
} }
// if we were a directory, find pred, replace tail // if we were a directory, find pred, replace tail
if (entry.d.type == LFS_TYPE_DIR) { if ((0xf & entry.d.type) == LFS_TYPE_DIR) {
int res = lfs_pred(lfs, dir.pair, &cwd); int res = lfs_pred(lfs, dir.pair, &cwd);
if (res < 0) { if (res < 0) {
return res; return res;
@@ -1949,7 +1949,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
} }
lfs_dir_t dir; lfs_dir_t dir;
if (prevexists && preventry.d.type == LFS_TYPE_DIR) { if (prevexists && (0xf & preventry.d.type) == LFS_TYPE_DIR) {
// must be empty before removal, checking size // must be empty before removal, checking size
// without masking top bit checks for any case where // without masking top bit checks for any case where
// dir is not empty // dir is not empty
@@ -1962,7 +1962,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
} }
// mark as moving // mark as moving
oldentry.d.type |= 0x80; oldentry.d.type |= LFS_STRUCT_MOVED;
err = lfs_dir_update(lfs, &oldcwd, &oldentry, NULL); err = lfs_dir_update(lfs, &oldcwd, &oldentry, NULL);
if (err) { if (err) {
return err; return err;
@@ -1976,7 +1976,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
// 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;
newentry.d.type &= ~0x80; newentry.d.type &= ~LFS_STRUCT_MOVED;
newentry.d.nlen = strlen(newpath); newentry.d.nlen = strlen(newpath);
if (prevexists) { if (prevexists) {
@@ -2003,7 +2003,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
} }
// if we were a directory, find pred, replace tail // if we were a directory, find pred, replace tail
if (prevexists && preventry.d.type == LFS_TYPE_DIR) { if (prevexists && (0xf & preventry.d.type) == LFS_TYPE_DIR) {
int res = lfs_pred(lfs, dir.pair, &newcwd); int res = lfs_pred(lfs, dir.pair, &newcwd);
if (res < 0) { if (res < 0) {
return res; return res;
@@ -2134,7 +2134,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
// write superblocks // write superblocks
lfs_superblock_t superblock = { lfs_superblock_t superblock = {
.off = sizeof(superdir.d), .off = sizeof(superdir.d),
.d.type = LFS_TYPE_SUPERBLOCK, .d.type = LFS_STRUCT_DIR | LFS_TYPE_SUPERBLOCK,
.d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4,
.d.nlen = sizeof(superblock.d.magic), .d.nlen = sizeof(superblock.d.magic),
.d.version = LFS_DISK_VERSION, .d.version = LFS_DISK_VERSION,
@@ -2263,7 +2263,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
} }
dir.off += lfs_entry_size(&entry); dir.off += lfs_entry_size(&entry);
if ((0x70 & entry.d.type) == (0x70 & LFS_TYPE_REG)) { if ((0x70 & entry.d.type) == LFS_STRUCT_CTZ) {
err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL, err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL,
entry.d.u.file.head, entry.d.u.file.size, cb, data); entry.d.u.file.head, entry.d.u.file.size, cb, data);
if (err) { if (err) {
@@ -2353,7 +2353,7 @@ static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2],
break; break;
} }
if (((0x70 & entry->d.type) == (0x70 & LFS_TYPE_DIR)) && if (((0x70 & entry->d.type) == LFS_STRUCT_DIR) &&
lfs_paircmp(entry->d.u.dir, dir) == 0) { lfs_paircmp(entry->d.u.dir, dir) == 0) {
return true; return true;
} }
@@ -2393,7 +2393,7 @@ static int lfs_moved(lfs_t *lfs, const void *e) {
break; break;
} }
if (!(0x80 & entry.d.type) && if (!(LFS_STRUCT_MOVED & entry.d.type) &&
memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) { memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) {
return true; return true;
} }
@@ -2525,7 +2525,7 @@ int lfs_deorphan(lfs_t *lfs) {
} }
// found moved entry // found moved entry
if (entry.d.type & 0x80) { if (entry.d.type & LFS_STRUCT_MOVED) {
int moved = lfs_moved(lfs, &entry.d.u); int moved = lfs_moved(lfs, &entry.d.u);
if (moved < 0) { if (moved < 0) {
return moved; return moved;
@@ -2541,7 +2541,7 @@ int lfs_deorphan(lfs_t *lfs) {
} else { } else {
LFS_DEBUG("Found partial move %d %d", LFS_DEBUG("Found partial move %d %d",
entry.d.u.dir[0], entry.d.u.dir[1]); entry.d.u.dir[0], entry.d.u.dir[1]);
entry.d.type &= ~0x80; entry.d.type &= ~LFS_STRUCT_MOVED;
err = lfs_dir_update(lfs, &cwd, &entry, NULL); err = lfs_dir_update(lfs, &cwd, &entry, NULL);
if (err) { if (err) {
return err; return err;

12
lfs.h
View File

@@ -74,9 +74,15 @@ enum lfs_error {
// File types // File types
enum lfs_type { enum lfs_type {
LFS_TYPE_REG = 0x11, // file type
LFS_TYPE_DIR = 0x22, LFS_TYPE_REG = 0x01,
LFS_TYPE_SUPERBLOCK = 0x2e, LFS_TYPE_DIR = 0x02,
LFS_TYPE_SUPERBLOCK = 0x0e,
// on disk structure
LFS_STRUCT_CTZ = 0x10,
LFS_STRUCT_DIR = 0x20,
LFS_STRUCT_MOVED = 0x80,
}; };
// File open flags // File open flags