WIP fixed up dir find

This commit is contained in:
Christopher Haster
2018-05-20 14:01:11 -05:00
parent 57fbc52cfc
commit f4d6ca5552
2 changed files with 99 additions and 67 deletions

126
lfs.c
View File

@@ -720,7 +720,7 @@ static int lfs_commit_crc(lfs_t *lfs, struct lfs_commit *commit) {
lfs_crc(&crc, &tag, sizeof(tag)); lfs_crc(&crc, &tag, sizeof(tag));
tag = lfs_fromle32(tag) ^ ptag; tag = lfs_fromle32(tag) ^ ptag;
printf("tag %#010x (%x:%x %#010x)\n", tag, dir->pair[0], off, lfs_tag_type(ptag)); printf("tag %#010x (%x:%x)\n", tag, dir->pair[0], off);
// next commit not yet programmed // next commit not yet programmed
if (lfs_tag_type(ptag) == LFS_TYPE_CRC_ && lfs_tag_valid(tag)) { if (lfs_tag_type(ptag) == LFS_TYPE_CRC_ && lfs_tag_valid(tag)) {
@@ -1164,46 +1164,53 @@ int lfs_dir_setter(lfs_t *lfs, void *p, struct lfs_commit *commit) {
&(struct lfs_dir_setter){regions, count}); &(struct lfs_dir_setter){regions, count});
} }
struct lfs_dir_lookuper { struct lfs_dir_finder {
const char *name; const char *name;
lfs_size_t size; lfs_size_t len;
lfs_block_t pair[2];
uint32_t tag; int16_t id;
lfs_entry_t_ *entry;
lfs_block_t tail[2]; lfs_block_t tail[2];
}; };
static int lfs_dir_lookuper(lfs_t *lfs, void *p, struct lfs_region__ region) { static int lfs_dir_finder(lfs_t *lfs, void *p, struct lfs_region__ region) {
struct lfs_dir_lookuper *lookup = p; struct lfs_dir_finder *find = p;
if (lfs_tag_type(region.tag) == LFS_TYPE_NAME_ && if (lfs_tag_type(region.tag) == LFS_TYPE_NAME_ &&
lfs_tag_size(region.tag) == lookup->size) { lfs_tag_size(region.tag) == find->len) {
int res = lfs_bd_cmp(lfs, region.u.d.block, region.u.d.off, int res = lfs_bd_cmp(lfs, region.u.d.block, region.u.d.off,
lookup->name, lookup->size); find->name, find->len);
if (res < 0) { if (res < 0) {
return res; return res;
} }
if (res) { if (res) {
// found a match // found a match
lookup->tag = region.tag & ~0x80000000; find->id = lfs_tag_id(region.tag);
lookup->pair[0] = 0xffffffff; find->entry->tag = 0xffffffff;
lookup->pair[1] = 0xffffffff;
} }
} }
if (lfs_tag_valid(lookup->tag) && if (find->id >= 0 && lfs_tag_id(region.tag) == find->id &&
lfs_tag_id(region.tag) == lfs_tag_id(lookup->tag) && (lfs_tag_type(region.tag) & 0x1f0) >= LFS_TYPE_REG_ &&
lfs_tag_type(region.tag) == LFS_TYPE_DIR_) { (lfs_tag_type(region.tag) & 0x1f0) <= LFS_TYPE_DIR_) {
int err = lfs_bd_read(lfs, region.u.d.block, region.u.d.off, // TODO combine regions and entries?
lookup->pair, sizeof(lookup->pair)); find->entry->tag = ~0x80000000 & region.tag;
if (err) { if (lfs_tag_type(region.tag) & 0x00f) {
return err; int err = lfs_bd_read(lfs, region.u.d.block, region.u.d.off,
&find->entry->u, sizeof(find->entry->u));
if (err) {
return err;
}
} else {
find->entry->u.d.block = region.u.d.block;
find->entry->u.d.off = region.u.d.off;
} }
} }
if (lfs_tag_type(lookup->tag) == LFS_TYPE_TAIL_) { if (lfs_tag_type(region.tag) == LFS_TYPE_TAIL_) {
int err = lfs_bd_read(lfs, region.u.d.block, region.u.d.off, int err = lfs_bd_read(lfs, region.u.d.block, region.u.d.off,
lookup->tail, sizeof(lookup->tail)); find->tail, sizeof(find->tail));
if (err) { if (err) {
return err; return err;
} }
@@ -1212,87 +1219,88 @@ static int lfs_dir_lookuper(lfs_t *lfs, void *p, struct lfs_region__ region) {
return 0; return 0;
} }
/*static*/ int32_t lfs_dir_lookup_(lfs_t *lfs, lfs_dir_t_ *dir, /*static*/ int32_t lfs_dir_find_(lfs_t *lfs, lfs_dir_t_ *dir,
const char **path) { lfs_entry_t_ *entry, const char **path) {
struct lfs_dir_lookuper lookup = { struct lfs_dir_finder find = {
.name = *path, .name = *path,
.pair[0] = 4, // TODO make superblock .entry = entry,
.pair[1] = 5,
}; };
// TODO make superblock
entry->u.pair[0] = 4;
entry->u.pair[1] = 5;
while (true) { while (true) {
nextname: nextname:
// skip slashes // skip slashes
lookup.name += strspn(lookup.name, "/"); find.name += strspn(find.name, "/");
lookup.size = strcspn(lookup.name, "/"); find.len = strcspn(find.name, "/");
// special case for root dir // special case for root dir
if (lookup.name[0] == '\0') { if (find.name[0] == '\0') {
// TODO set up root? // TODO set up root?
// *entry = (lfs_entry_t){ entry->tag = LFS_STRUCT_DIR | LFS_TYPE_DIR;
// .d.type = LFS_STRUCT_DIR | LFS_TYPE_DIR, entry->u.pair[0] = lfs->root[0];
// .d.u.dir[0] = lfs->root[0], entry->u.pair[1] = lfs->root[1];
// .d.u.dir[1] = lfs->root[1],
// };
return lfs_mktag(LFS_TYPE_DIR_, 0x1ff, 0); return lfs_mktag(LFS_TYPE_DIR_, 0x1ff, 0);
} }
// skip '.' and root '..' // skip '.' and root '..'
if ((lookup.size == 1 && memcmp(lookup.name, ".", 1) == 0) || if ((find.len == 1 && memcmp(find.name, ".", 1) == 0) ||
(lookup.size == 2 && memcmp(lookup.name, "..", 2) == 0)) { (find.len == 2 && memcmp(find.name, "..", 2) == 0)) {
lookup.name += lookup.size; find.name += find.len;
goto nextname; goto nextname;
} }
// skip if matched by '..' in name // skip if matched by '..' in name
const char *suffix = lookup.name + lookup.size; const char *suffix = find.name + find.len;
lfs_size_t suffsize; lfs_size_t sufflen;
int depth = 1; int depth = 1;
while (true) { while (true) {
suffix += strspn(suffix, "/"); suffix += strspn(suffix, "/");
suffsize = strcspn(suffix, "/"); sufflen = strcspn(suffix, "/");
if (suffsize == 0) { if (sufflen == 0) {
break; break;
} }
if (suffsize == 2 && memcmp(suffix, "..", 2) == 0) { if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
depth -= 1; depth -= 1;
if (depth == 0) { if (depth == 0) {
lookup.name = suffix + suffsize; find.name = suffix + sufflen;
goto nextname; goto nextname;
} }
} else { } else {
depth += 1; depth += 1;
} }
suffix += suffsize; suffix += sufflen;
} }
// update what we've found // update what we've found
*path = lookup.name; *path = find.name;
// find path // TODO handle tails // find path // TODO handle tails
while (true) { while (true) {
lookup.tag = 0xffffffff; find.id = -1;
lookup.tail[0] = 0xffffffff; find.tail[0] = 0xffffffff;
lookup.tail[1] = 0xffffffff; find.tail[1] = 0xffffffff;
int err = lfs_dir_fetch_(lfs, dir, lookup.pair, int err = lfs_dir_fetch_(lfs, dir, entry->u.pair,
lfs_dir_lookuper, &lookup); lfs_dir_finder, &find);
if (err) { if (err) {
return err; return err;
} }
if (lfs_tag_valid(lookup.tag)) { if (find.id >= 0) {
// found it // found it
break; break;
} }
if (lfs_pairisnull(lookup.tail)) { if (lfs_pairisnull(find.tail)) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
lookup.pair[0] = lookup.tail[0]; entry->u.pair[0] = find.tail[0];
lookup.pair[1] = lookup.tail[1]; entry->u.pair[1] = find.tail[1];
} }
// TODO handle moves // TODO handle moves
@@ -1306,15 +1314,15 @@ static int lfs_dir_lookuper(lfs_t *lfs, void *p, struct lfs_region__ region) {
// entry->d.type &= ~LFS_STRUCT_MOVED; // entry->d.type &= ~LFS_STRUCT_MOVED;
// } // }
lookup.name += lookup.size; find.name += find.len;
lookup.name += strspn(lookup.name, "/"); find.name += strspn(find.name, "/");
if (lookup.name[0] == '\0') { if (find.name[0] == '\0') {
return lookup.tag; return 0;
} }
// continue on if we hit a directory // continue on if we hit a directory
// TODO update with what's on master? // TODO update with what's on master?
if (lfs_tag_type(lookup.tag) != LFS_TYPE_DIR_) { if (lfs_tag_type(entry->tag) != LFS_TYPE_DIR_) {
return LFS_ERR_NOTDIR; return LFS_ERR_NOTDIR;
} }
} }

40
lfs.h
View File

@@ -106,14 +106,23 @@ enum lfs_type {
LFS_STRUCT_INLINE = 0x30, LFS_STRUCT_INLINE = 0x30,
LFS_STRUCT_MOVED = 0x80, LFS_STRUCT_MOVED = 0x80,
LFS_TYPE_CTZ_ = 0x1, // file type
LFS_TYPE_DIR_ = 0x2, LFS_TYPE_REG_ = 0x020,
LFS_TYPE_INLINE_ = 0x3, LFS_TYPE_DIR_ = 0x030,
LFS_TYPE_ATTR_ = 0x4,
LFS_TYPE_NAME_ = 0x5, LFS_TYPE_NAME_ = 0x010,
LFS_TYPE_DROP_ = 0x7, LFS_TYPE_MOVE_ = 0x060,
LFS_TYPE_TAIL_ = 0xd, LFS_TYPE_DROP_ = 0x070,
LFS_TYPE_CRC_ = 0xe,
LFS_TYPE_SUPERBLOCK_ = 0x0c0,
LFS_TYPE_TAIL_ = 0x0d0,
LFS_TYPE_CRC_ = 0x0e0,
// on disk structure
LFS_STRUCT_ATTR_ = 0x100,
LFS_STRUCT_INLINE_ = 0x000,
LFS_STRUCT_CTZ_ = 0x00c,
LFS_STRUCT_DIR_ = 0x008,
// LFS_TYPE_DIR_ = 0x002, // LFS_TYPE_DIR_ = 0x002,
// LFS_TYPE_SUPERBLOCK_ = 0xff2, // LFS_TYPE_SUPERBLOCK_ = 0xff2,
@@ -285,6 +294,21 @@ typedef struct lfs_entry {
} d; } d;
} lfs_entry_t; } lfs_entry_t;
typedef struct lfs_entry_ {
uint32_t tag;
union {
lfs_block_t pair[2];
struct {
lfs_block_t head;
lfs_size_t size;
} ctz;
struct {
lfs_block_t block;
lfs_off_t off;
} d;
} u;
} lfs_entry_t_;
typedef struct lfs_entry_attr { typedef struct lfs_entry_attr {
struct lfs_disk_entry_attr { struct lfs_disk_entry_attr {
uint8_t type; uint8_t type;