mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 00:38:29 +01:00
WIP consolidated find/parent scanning functions
This commit is contained in:
294
lfs.c
294
lfs.c
@@ -1415,64 +1415,85 @@ static int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
}
|
||||
|
||||
struct lfs_dir_find {
|
||||
const char *name;
|
||||
uint16_t len;
|
||||
int16_t id;
|
||||
int16_t tempid;
|
||||
uint8_t findtype;
|
||||
uint8_t tempfindtype;
|
||||
uint32_t mask;
|
||||
lfs_tag_t tag;
|
||||
const void *buffer;
|
||||
lfs_tag_t foundtag;
|
||||
lfs_tag_t temptag;
|
||||
};
|
||||
|
||||
static int lfs_dir_findscan(lfs_t *lfs, void *p, lfs_mattr_t attr) {
|
||||
struct lfs_dir_find *find = p;
|
||||
|
||||
if (lfs_tag_subtype(attr.tag) == LFS_TYPE_NAME &&
|
||||
lfs_tag_size(attr.tag) == find->len) {
|
||||
if ((attr.tag & find->mask) == (find->tag & find->mask)) {
|
||||
int res = lfs_bd_cmp(lfs, attr.u.d.block, attr.u.d.off,
|
||||
find->name, find->len);
|
||||
find->buffer, lfs_tag_size(attr.tag));
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
// found a match
|
||||
find->tempid = lfs_tag_id(attr.tag);
|
||||
find->tempfindtype = lfs_tag_type(attr.tag);
|
||||
find->temptag = attr.tag;
|
||||
}
|
||||
} else if (lfs_tag_type(attr.tag) == LFS_TYPE_DELETE) {
|
||||
if (lfs_tag_id(attr.tag) == find->tempid) {
|
||||
find->tempid = -1;
|
||||
} else if (lfs_tag_id(attr.tag) < find->tempid) {
|
||||
find->tempid -= 1;
|
||||
if (lfs_tag_id(attr.tag) == lfs_tag_id(find->temptag)) {
|
||||
find->temptag = 0xffffffff;
|
||||
} else if (lfs_tag_id(find->temptag) < 0x3ff &&
|
||||
lfs_tag_id(attr.tag) < lfs_tag_id(find->temptag)) {
|
||||
find->temptag -= lfs_mktag(0, 1, 0);
|
||||
}
|
||||
} else if (lfs_tag_type(attr.tag) == LFS_TYPE_CRC) {
|
||||
find->id = find->tempid;
|
||||
find->findtype = find->tempfindtype;
|
||||
find->foundtag = find->temptag;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir, const lfs_block_t *pair,
|
||||
uint32_t mask, lfs_tag_t tag,
|
||||
const void *buffer, lfs_tag_t *foundtag) {
|
||||
struct lfs_dir_find find = {
|
||||
.mask = mask,
|
||||
.tag = tag,
|
||||
.buffer = buffer,
|
||||
.foundtag = 0xffffffff,
|
||||
.temptag = 0xffffffff,
|
||||
};
|
||||
|
||||
int err = lfs_dir_fetchwith(lfs, dir, pair, lfs_dir_findscan, &find);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (find.foundtag == 0xffffffff) {
|
||||
return LFS_ERR_NOENT;
|
||||
}
|
||||
|
||||
*foundtag = find.foundtag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// TODO drop others, make this only return id, also make get take in only entry to populate (with embedded tag)
|
||||
static int lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
static int lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
const char **path, uint16_t *id, uint8_t *type) {
|
||||
lfs_mattr_t attr = {
|
||||
.u.pair[0] = lfs->root[0],
|
||||
.u.pair[1] = lfs->root[1],
|
||||
};
|
||||
|
||||
struct lfs_dir_find find = {
|
||||
.name = *path,
|
||||
};
|
||||
const char *name = *path;
|
||||
lfs_size_t namelen;
|
||||
|
||||
while (true) {
|
||||
nextname:
|
||||
// skip slashes
|
||||
find.name += strspn(find.name, "/");
|
||||
find.len = strcspn(find.name, "/");
|
||||
name += strspn(name, "/");
|
||||
namelen = strcspn(name, "/");
|
||||
|
||||
// special case for root dir
|
||||
if (find.name[0] == '\0') {
|
||||
if (name[0] == '\0') {
|
||||
// Return ISDIR when we hit root
|
||||
// TODO change this to -1 or 0x3ff?
|
||||
*type = LFS_TYPE_DIR;
|
||||
@@ -1480,14 +1501,14 @@ static int lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
}
|
||||
|
||||
// skip '.' and root '..'
|
||||
if ((find.len == 1 && memcmp(find.name, ".", 1) == 0) ||
|
||||
(find.len == 2 && memcmp(find.name, "..", 2) == 0)) {
|
||||
find.name += find.len;
|
||||
if ((namelen == 1 && memcmp(name, ".", 1) == 0) ||
|
||||
(namelen == 2 && memcmp(name, "..", 2) == 0)) {
|
||||
name += namelen;
|
||||
goto nextname;
|
||||
}
|
||||
|
||||
// skip if matched by '..' in name
|
||||
const char *suffix = find.name + find.len;
|
||||
const char *suffix = name + namelen;
|
||||
lfs_size_t sufflen;
|
||||
int depth = 1;
|
||||
while (true) {
|
||||
@@ -1500,7 +1521,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
|
||||
depth -= 1;
|
||||
if (depth == 0) {
|
||||
find.name = suffix + sufflen;
|
||||
name = suffix + sufflen;
|
||||
goto nextname;
|
||||
}
|
||||
} else {
|
||||
@@ -1511,21 +1532,22 @@ static int lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
}
|
||||
|
||||
// update what we've found
|
||||
*path = find.name;
|
||||
*path = name;
|
||||
|
||||
// find path
|
||||
while (true) {
|
||||
//printf("checking %d %d for %s\n", attr.u.pair[0], attr.u.pair[1], *path);
|
||||
find.id = -1;
|
||||
find.tempid = -1;
|
||||
int err = lfs_dir_fetchwith(lfs, dir, attr.u.pair,
|
||||
lfs_dir_findscan, &find);
|
||||
if (err) {
|
||||
lfs_tag_t foundtag = -1;
|
||||
int err = lfs_dir_find(lfs, dir, attr.u.pair,
|
||||
0x7c000fff, lfs_mktag(LFS_TYPE_NAME, 0, namelen),
|
||||
name, &foundtag);
|
||||
if (err && err != LFS_ERR_NOENT) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (find.id >= 0) {
|
||||
if (err != LFS_ERR_NOENT) {
|
||||
// found it
|
||||
*id = lfs_tag_id(foundtag);
|
||||
*type = lfs_tag_type(foundtag);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1537,17 +1559,15 @@ static int lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
attr.u.pair[1] = dir->tail[1];
|
||||
}
|
||||
|
||||
*id = find.id;
|
||||
*type = find.findtype;
|
||||
find.name += find.len;
|
||||
find.name += strspn(find.name, "/");
|
||||
if (find.name[0] == '\0') {
|
||||
name += namelen;
|
||||
name += strspn(name, "/");
|
||||
if (name[0] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// don't continue on if we didn't hit a directory
|
||||
// TODO update with what's on master?
|
||||
if (find.findtype != LFS_TYPE_DIR) {
|
||||
if (*type != LFS_TYPE_DIR) {
|
||||
return LFS_ERR_NOTDIR;
|
||||
}
|
||||
|
||||
@@ -1555,7 +1575,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
// TODO would this mean more code?
|
||||
// grab the entry data
|
||||
int err = lfs_dir_getentry(lfs, dir, 0x7c3ff000,
|
||||
lfs_mktag(LFS_TYPE_STRUCT, find.id, 0), &attr);
|
||||
lfs_mktag(LFS_TYPE_STRUCT, *id, 0), &attr);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -1573,7 +1593,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
|
||||
}
|
||||
|
||||
lfs_mdir_t cwd;
|
||||
int err = lfs_dir_find(lfs, &cwd, &path, &(uint16_t){0}, &(uint8_t){0});
|
||||
int err = lfs_dir_lookup(lfs, &cwd, &path, &(uint16_t){0}, &(uint8_t){0});
|
||||
if (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) {
|
||||
if (!err || err == LFS_ERR_ISDIR) {
|
||||
return LFS_ERR_EXIST;
|
||||
@@ -1626,7 +1646,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
|
||||
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
int err = lfs_dir_find(lfs, &dir->m, &path, &id, &type);
|
||||
int err = lfs_dir_lookup(lfs, &dir->m, &path, &id, &type);
|
||||
if (err && err != LFS_ERR_ISDIR) {
|
||||
return err;
|
||||
}
|
||||
@@ -1979,7 +1999,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
||||
lfs_mdir_t cwd;
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
int err = lfs_dir_find(lfs, &cwd, &path, &id, &type);
|
||||
int err = lfs_dir_lookup(lfs, &cwd, &path, &id, &type);
|
||||
if (err && (err != LFS_ERR_NOENT || strchr(path, '/') != NULL) &&
|
||||
err != LFS_ERR_ISDIR) {
|
||||
return err;
|
||||
@@ -2655,7 +2675,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
lfs_mdir_t cwd;
|
||||
uint16_t id;
|
||||
// TODO pass to getinfo?
|
||||
int err = lfs_dir_find(lfs, &cwd, &path, &id, &(uint8_t){0});
|
||||
int err = lfs_dir_lookup(lfs, &cwd, &path, &id, &(uint8_t){0});
|
||||
if (err && err != LFS_ERR_ISDIR) {
|
||||
return err;
|
||||
}
|
||||
@@ -2687,7 +2707,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
|
||||
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
err = lfs_dir_find(lfs, &cwd, &path, &id, &type);
|
||||
err = lfs_dir_lookup(lfs, &cwd, &path, &id, &type);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -2749,7 +2769,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
lfs_mdir_t oldcwd;
|
||||
uint16_t oldid;
|
||||
uint8_t oldtype;
|
||||
int err = lfs_dir_find(lfs, &oldcwd, &oldpath, &oldid, &oldtype);
|
||||
int err = lfs_dir_lookup(lfs, &oldcwd, &oldpath, &oldid, &oldtype);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -2758,7 +2778,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
lfs_mdir_t newcwd;
|
||||
uint16_t newid;
|
||||
uint8_t prevtype;
|
||||
err = lfs_dir_find(lfs, &newcwd, &newpath, &newid, &prevtype);
|
||||
err = lfs_dir_lookup(lfs, &newcwd, &newpath, &newid, &prevtype);
|
||||
if (err && err != LFS_ERR_NOENT) {
|
||||
return err;
|
||||
}
|
||||
@@ -2883,7 +2903,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
// }
|
||||
//
|
||||
// lfs_mattr_t entry;
|
||||
// err = lfs_dir_find(lfs, &cwd, &entry, &path);
|
||||
// err = lfs_dir_lookup(lfs, &cwd, &entry, &path);
|
||||
// if (err) {
|
||||
// return err;
|
||||
// }
|
||||
@@ -2900,7 +2920,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
// }
|
||||
//
|
||||
// lfs_mattr_t entry;
|
||||
// err = lfs_dir_find(lfs, &cwd, &entry, &path);
|
||||
// err = lfs_dir_lookup(lfs, &cwd, &entry, &path);
|
||||
// if (err) {
|
||||
// return err;
|
||||
// }
|
||||
@@ -3331,168 +3351,42 @@ static int lfs_pred(lfs_t *lfs, const lfs_block_t pair[2], lfs_mdir_t *pdir) {
|
||||
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
static int lfs_pred(lfs_t *lfs, const lfs_block_t dir[2], lfs_mdir_t *pdir) {
|
||||
if (lfs_pairisnull(lfs->root)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// iterate directories
|
||||
int err = lfs_dir_fetch(lfs, pdir, (const lfs_block_t[2]){0, 1});
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
while (!lfs_pairisnull(pdir->d.tail)) {
|
||||
if (lfs_paircmp(pdir->d.tail, dir) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
err = lfs_dir_fetch(lfs, pdir, pdir->d.tail);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// TODO combine parentscan and findscan?
|
||||
struct lfs_dir_parentscan {
|
||||
lfs_block_t pair[2];
|
||||
int16_t id;
|
||||
int16_t tempid;
|
||||
};
|
||||
|
||||
static int lfs_parentscan(lfs_t *lfs, void *p, lfs_mattr_t attr) {
|
||||
struct lfs_dir_parentscan *parentscan = p;
|
||||
|
||||
if (lfs_tag_type(attr.tag) == LFS_STRUCT_DIR) {
|
||||
int err = lfs_bd_read(lfs, attr.u.d.block, attr.u.d.off,
|
||||
&attr.u, sizeof(attr.u));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (lfs_paircmp(attr.u.pair, parentscan->pair) == 0) {
|
||||
// found a match
|
||||
parentscan->tempid = lfs_tag_id(attr.tag);
|
||||
}
|
||||
} else if (lfs_tag_type(attr.tag) == LFS_TYPE_DELETE) {
|
||||
if (lfs_tag_id(attr.tag) == parentscan->tempid) {
|
||||
parentscan->tempid = -1;
|
||||
} else if (lfs_tag_id(attr.tag) < parentscan->tempid) {
|
||||
parentscan->tempid -= 1;
|
||||
}
|
||||
} else if (lfs_tag_type(attr.tag) == LFS_TYPE_CRC) {
|
||||
parentscan->id = parentscan->tempid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_parent(lfs_t *lfs, const lfs_block_t pair[2],
|
||||
lfs_mdir_t *parent, lfs_mattr_t *attr) {
|
||||
// iterate over all directory directory entries
|
||||
parent->tail[0] = 0;
|
||||
parent->tail[1] = 1;
|
||||
while (!lfs_pairisnull(parent->tail)) {
|
||||
struct lfs_dir_parentscan parentscan = {
|
||||
.pair[0] = pair[0],
|
||||
.pair[1] = pair[1],
|
||||
.id = -1,
|
||||
.tempid = -1,
|
||||
};
|
||||
// search for both orderings so we can reuse the find function
|
||||
lfs_block_t child[2] = {pair[0], pair[1]};
|
||||
|
||||
int err = lfs_dir_fetchwith(lfs, parent, parent->tail,
|
||||
lfs_parentscan, &parentscan);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (parentscan.id != -1) {
|
||||
int err = lfs_dir_getentry(lfs, parent, 0x7ffff000,
|
||||
lfs_mktag(LFS_STRUCT_DIR, parentscan.id, 0), attr);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
//
|
||||
//static int lfs_parent(lfs_t *lfs, const lfs_block_t pair[2],
|
||||
// lfs_mdir_t *parent, lfs_mattr_t *attr) {
|
||||
// // iterate over all directory directory entries
|
||||
// parent->tail[0] = 0;
|
||||
// parent->tail[1] = 1;
|
||||
// while (!lfs_pairisnull(parent->tail)) {
|
||||
// int err = lfs_dir_fetch(lfs, parent, parent->tail);
|
||||
// if (err) {
|
||||
// return err;
|
||||
// }
|
||||
//
|
||||
// // TODO make this O(n) by using fetchwith to match the pointers
|
||||
// for (uint16_t id = 0; id < parent->count; id++) {
|
||||
// int err = lfs_dir_getentry(lfs, parent, 0x43dff000,
|
||||
// lfs_mktag(LFS_STRUCT_DIR, id, 0), attr);
|
||||
// if (err) {
|
||||
// if (err == LFS_ERR_NOENT) {
|
||||
// continue;
|
||||
// }
|
||||
// return err;
|
||||
// }
|
||||
//
|
||||
// if (lfs_paircmp(attr->u.pair, pair) == 0) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
//}
|
||||
/*
|
||||
static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2],
|
||||
lfs_mdir_t *parent, lfs_mattr_t *attr) {
|
||||
if (lfs_pairisnull(lfs->root)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
parent->d.tail[0] = 0;
|
||||
parent->d.tail[1] = 1;
|
||||
|
||||
// iterate over all directory directory entries
|
||||
while (!lfs_pairisnull(parent->d.tail)) {
|
||||
int err = lfs_dir_fetch(lfs, parent, parent->d.tail);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
err = lfs_dir_next(lfs, parent, attr);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// iterate over all directory directory entries
|
||||
parent->tail[0] = 0;
|
||||
parent->tail[1] = 1;
|
||||
while (!lfs_pairisnull(parent->tail)) {
|
||||
lfs_tag_t foundtag = -1;
|
||||
int err = lfs_dir_find(lfs, parent, parent->tail,
|
||||
0x7fc00fff, lfs_mktag(LFS_STRUCT_DIR, 0, sizeof(child)),
|
||||
child, &foundtag);
|
||||
if (err && err != LFS_ERR_NOENT) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (err == LFS_ERR_NOENT) {
|
||||
break;
|
||||
}
|
||||
if (err != LFS_ERR_NOENT) {
|
||||
// found our parent
|
||||
int err = lfs_dir_getentry(lfs, parent,
|
||||
0x7ffff000, foundtag, attr);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (((0x70 & attr->d.type) == LFS_STRUCT_DIR) &&
|
||||
lfs_paircmp(attr->d.u.dir, dir) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
lfs_pairswap(child);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO rename to lfs_dir_relocate?
|
||||
static int lfs_relocate(lfs_t *lfs,
|
||||
@@ -3725,7 +3619,7 @@ int lfs_deorphan(lfs_t *lfs) {
|
||||
// }
|
||||
//
|
||||
// lfs_mattr_t entry;
|
||||
// err = lfs_dir_find(lfs, &cwd, &entry, &path);
|
||||
// err = lfs_dir_lookup(lfs, &cwd, &entry, &path);
|
||||
// if (err) {
|
||||
// return err;
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user