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) {
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;
lfs_size_t namelen;
int32_t tag;
*path = NULL;
// 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) {
nextname:
// skip slashes
name += strspn(name, "/");
namelen = strcspn(name, "/");
if (name[0] == '\0') {
// special case for root dir
return LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0);
}
lfs_size_t namelen = strcspn(name, "/");
// skip '.' and root '..'
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;
}
// update what we've found
*path = name;
// found path
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) {
tag = lfs_dir_find(lfs, dir, pair, 0x7c000fff,
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) {
// couldn't find it
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];
}
// to next name
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;
int32_t res = lfs_dir_lookup(lfs, &cwd, &path);
if (res != LFS_ERR_NOENT || strchr(path, '/') != NULL) {
if (res >= 0) {
return LFS_ERR_EXIST;
}
return res;
if (res != LFS_ERR_NOENT || !path) {
return (res < 0) ? res : LFS_ERR_EXIST;
}
// 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
lfs_mdir_t cwd;
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;
}

View File

@@ -90,6 +90,22 @@ tests/test.py << TEST
lfs_unmount(&lfs) => 0;
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 ---"
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;