Skip to content

Commit 3914cdf

Browse files
committed
Pulled in fixes for additional path corner cases
Pulled in 015b86b. Merging this now avoids duplicate effort restructuring the path lookup logic.
1 parent 392b2ac commit 3914cdf

File tree

2 files changed

+53
-38
lines changed

2 files changed

+53
-38
lines changed

lfs.c

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,21 +1273,19 @@ static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir,
12731273
}
12741274

12751275
static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) {
1276-
lfs_block_t pair[2] = {lfs->root[0], lfs->root[1]};
1276+
// we reduce path to a single name if we can find it
12771277
const char *name = *path;
1278-
lfs_size_t namelen;
1279-
int32_t tag;
1278+
*path = NULL;
1279+
1280+
// default to root dir
1281+
int32_t tag = LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0);
1282+
lfs_block_t pair[2] = {lfs->root[0], lfs->root[1]};
12801283

12811284
while (true) {
1282-
nextname:
1285+
nextname:
12831286
// skip slashes
12841287
name += strspn(name, "/");
1285-
namelen = strcspn(name, "/");
1286-
1287-
if (name[0] == '\0') {
1288-
// special case for root dir
1289-
return LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0);
1290-
}
1288+
lfs_size_t namelen = strcspn(name, "/");
12911289

12921290
// skip '.' and root '..'
12931291
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) {
13201318
suffix += sufflen;
13211319
}
13221320

1323-
// update what we've found
1324-
*path = name;
1321+
// found path
1322+
if (name[0] == '\0') {
1323+
return tag;
1324+
}
13251325

1326-
// find path
1326+
// update what we've found if path is only a name
1327+
if (strchr(name, '/') == NULL) {
1328+
*path = name;
1329+
}
1330+
1331+
// only continue if we hit a directory
1332+
if (lfs_tagtype(tag) != LFS_TYPE_DIR) {
1333+
return LFS_ERR_NOTDIR;
1334+
}
1335+
1336+
// grab the entry data
1337+
if (lfs_tagid(tag) != 0x3ff) {
1338+
int32_t res = lfs_dir_get(lfs, dir, 0x7c3ff000,
1339+
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tagid(tag), 8), pair);
1340+
if (res < 0) {
1341+
return res;
1342+
}
1343+
}
1344+
1345+
// find entry matching name
13271346
while (true) {
13281347
tag = lfs_dir_find(lfs, dir, pair, 0x7c000fff,
13291348
LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), name);
@@ -1337,33 +1356,16 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) {
13371356
}
13381357

13391358
if (!dir->split) {
1359+
// couldn't find it
13401360
return LFS_ERR_NOENT;
13411361
}
13421362

13431363
pair[0] = dir->tail[0];
13441364
pair[1] = dir->tail[1];
13451365
}
13461366

1367+
// to next name
13471368
name += namelen;
1348-
name += strspn(name, "/");
1349-
if (name[0] == '\0') {
1350-
return tag;
1351-
}
1352-
1353-
// don't continue on if we didn't hit a directory
1354-
// TODO update with what's on master?
1355-
if (lfs_tagtype(tag) != LFS_TYPE_DIR) {
1356-
return LFS_ERR_NOTDIR;
1357-
}
1358-
1359-
// TODO optimize grab for inline files and like?
1360-
// TODO would this mean more code?
1361-
// grab the entry data
1362-
int32_t res = lfs_dir_get(lfs, dir, 0x7c3ff000,
1363-
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tagid(tag), 8), pair);
1364-
if (res < 0) {
1365-
return res;
1366-
}
13671369
}
13681370
}
13691371

@@ -1408,11 +1410,8 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
14081410

14091411
lfs_mdir_t cwd;
14101412
int32_t res = lfs_dir_lookup(lfs, &cwd, &path);
1411-
if (res != LFS_ERR_NOENT || strchr(path, '/') != NULL) {
1412-
if (res >= 0) {
1413-
return LFS_ERR_EXIST;
1414-
}
1415-
return res;
1413+
if (res != LFS_ERR_NOENT || !path) {
1414+
return (res < 0) ? res : LFS_ERR_EXIST;
14161415
}
14171416

14181417
// check that name fits
@@ -1806,7 +1805,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
18061805
// allocate entry for file if it doesn't exist
18071806
lfs_mdir_t cwd;
18081807
int32_t tag = lfs_dir_lookup(lfs, &cwd, &path);
1809-
if (tag < 0 && (tag != LFS_ERR_NOENT || strchr(path, '/') != NULL)) {
1808+
if (tag < 0 && (tag != LFS_ERR_NOENT || !path)) {
18101809
return tag;
18111810
}
18121811

tests/test_paths.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,22 @@ tests/test.py << TEST
9090
lfs_unmount(&lfs) => 0;
9191
TEST
9292

93+
echo "--- Trailing dot path tests ---"
94+
tests/test.py << TEST
95+
lfs_mount(&lfs, &cfg) => 0;
96+
lfs_stat(&lfs, "tea/hottea/", &info) => 0;
97+
strcmp(info.name, "hottea") => 0;
98+
lfs_stat(&lfs, "tea/hottea/.", &info) => 0;
99+
strcmp(info.name, "hottea") => 0;
100+
lfs_stat(&lfs, "tea/hottea/./.", &info) => 0;
101+
strcmp(info.name, "hottea") => 0;
102+
lfs_stat(&lfs, "tea/hottea/..", &info) => 0;
103+
strcmp(info.name, "tea") => 0;
104+
lfs_stat(&lfs, "tea/hottea/../.", &info) => 0;
105+
strcmp(info.name, "tea") => 0;
106+
lfs_unmount(&lfs) => 0;
107+
TEST
108+
93109
echo "--- Root dot dot path tests ---"
94110
tests/test.py << TEST
95111
lfs_mount(&lfs, &cfg) => 0;

0 commit comments

Comments
 (0)