mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 00:38:29 +01:00
WIP fixed up dir find
This commit is contained in:
126
lfs.c
126
lfs.c
@@ -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
40
lfs.h
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user