Pulled in fixes for additional path corner cases

Pulled in 015b86b. Merging this now avoids duplicate effort restructuring
the path lookup logic.
This commit is contained in:
Christopher Haster
2018-07-28 12:07:18 -05:00
parent 392b2ac79f
commit 3914cdf39f
2 changed files with 53 additions and 38 deletions

73
lfs.c
View File

@@ -1273,21 +1273,19 @@ static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir,
} }
static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) { static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) {
lfs_block_t pair[2] = {lfs->root[0], lfs->root[1]}; // we reduce path to a single name if we can find it
const char *name = *path; const char *name = *path;
lfs_size_t namelen; *path = NULL;
int32_t tag;
// default to root dir
int32_t tag = LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0);
lfs_block_t pair[2] = {lfs->root[0], lfs->root[1]};
while (true) { while (true) {
nextname: nextname:
// skip slashes // skip slashes
name += strspn(name, "/"); name += strspn(name, "/");
namelen = strcspn(name, "/"); lfs_size_t namelen = strcspn(name, "/");
if (name[0] == '\0') {
// special case for root dir
return LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0);
}
// skip '.' and root '..' // skip '.' and root '..'
if ((namelen == 1 && memcmp(name, ".", 1) == 0) || if ((namelen == 1 && memcmp(name, ".", 1) == 0) ||
@@ -1320,10 +1318,31 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) {
suffix += sufflen; suffix += sufflen;
} }
// update what we've found // found path
*path = name; if (name[0] == '\0') {
return tag;
}
// find path // update what we've found if path is only a name
if (strchr(name, '/') == NULL) {
*path = name;
}
// only continue if we hit a directory
if (lfs_tagtype(tag) != LFS_TYPE_DIR) {
return LFS_ERR_NOTDIR;
}
// grab the entry data
if (lfs_tagid(tag) != 0x3ff) {
int32_t res = lfs_dir_get(lfs, dir, 0x7c3ff000,
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tagid(tag), 8), pair);
if (res < 0) {
return res;
}
}
// find entry matching name
while (true) { while (true) {
tag = lfs_dir_find(lfs, dir, pair, 0x7c000fff, tag = lfs_dir_find(lfs, dir, pair, 0x7c000fff,
LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), name); LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), name);
@@ -1337,6 +1356,7 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) {
} }
if (!dir->split) { if (!dir->split) {
// couldn't find it
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
@@ -1344,26 +1364,8 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) {
pair[1] = dir->tail[1]; pair[1] = dir->tail[1];
} }
// to next name
name += namelen; name += namelen;
name += strspn(name, "/");
if (name[0] == '\0') {
return tag;
}
// don't continue on if we didn't hit a directory
// TODO update with what's on master?
if (lfs_tagtype(tag) != LFS_TYPE_DIR) {
return LFS_ERR_NOTDIR;
}
// TODO optimize grab for inline files and like?
// TODO would this mean more code?
// grab the entry data
int32_t res = lfs_dir_get(lfs, dir, 0x7c3ff000,
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tagid(tag), 8), pair);
if (res < 0) {
return res;
}
} }
} }
@@ -1408,11 +1410,8 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
lfs_mdir_t cwd; lfs_mdir_t cwd;
int32_t res = lfs_dir_lookup(lfs, &cwd, &path); int32_t res = lfs_dir_lookup(lfs, &cwd, &path);
if (res != LFS_ERR_NOENT || strchr(path, '/') != NULL) { if (res != LFS_ERR_NOENT || !path) {
if (res >= 0) { return (res < 0) ? res : LFS_ERR_EXIST;
return LFS_ERR_EXIST;
}
return res;
} }
// check that name fits // check that name fits
@@ -1806,7 +1805,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
// allocate entry for file if it doesn't exist // allocate entry for file if it doesn't exist
lfs_mdir_t cwd; lfs_mdir_t cwd;
int32_t tag = lfs_dir_lookup(lfs, &cwd, &path); int32_t tag = lfs_dir_lookup(lfs, &cwd, &path);
if (tag < 0 && (tag != LFS_ERR_NOENT || strchr(path, '/') != NULL)) { if (tag < 0 && (tag != LFS_ERR_NOENT || !path)) {
return tag; return tag;
} }

View File

@@ -90,6 +90,22 @@ tests/test.py << TEST
lfs_unmount(&lfs) => 0; lfs_unmount(&lfs) => 0;
TEST TEST
echo "--- Trailing dot path tests ---"
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;
lfs_stat(&lfs, "tea/hottea/", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "tea/hottea/.", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "tea/hottea/./.", &info) => 0;
strcmp(info.name, "hottea") => 0;
lfs_stat(&lfs, "tea/hottea/..", &info) => 0;
strcmp(info.name, "tea") => 0;
lfs_stat(&lfs, "tea/hottea/../.", &info) => 0;
strcmp(info.name, "tea") => 0;
lfs_unmount(&lfs) => 0;
TEST
echo "--- Root dot dot path tests ---" echo "--- Root dot dot path tests ---"
tests/test.py << TEST tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0; lfs_mount(&lfs, &cfg) => 0;