Skip to content

Commit

Permalink
Fixed handling of root as target for create operations
Browse files Browse the repository at this point in the history
Before this patch, when calling lfs_mkdir or lfs_file_open with root
as the target, littlefs wouldn't find the path properly and happily
run into undefined behaviour.

The fix is to populate a directory entry for root in the lfs_dir_find
function. As an added plus, this allowed several special cases around
root to be completely dropped.
  • Loading branch information
geky committed Mar 1, 2018
1 parent 1476181 commit d9c3637
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 22 deletions.
44 changes: 22 additions & 22 deletions lfs.c
Expand Up @@ -780,6 +780,19 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
pathname += strspn(pathname, "/");
pathlen = strcspn(pathname, "/");

// special case for root dir
if (pathname[0] == '\0') {
*entry = (lfs_entry_t){
.d.type = LFS_TYPE_DIR,
.d.elen = sizeof(entry->d) - 4,
.d.alen = 0,
.d.nlen = 0,
.d.u.dir[0] = lfs->root[0],
.d.u.dir[1] = lfs->root[1],
};
return 0;
}

// skip '.' and root '..'
if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
(pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
Expand Down Expand Up @@ -936,15 +949,6 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
return err;
}

// check for root, can only be something like '/././../.'
if (strspn(path, "/.") == strlen(path)) {
dir->head[0] = dir->pair[0];
dir->head[1] = dir->pair[1];
dir->pos = sizeof(dir->d) - 2;
dir->off = sizeof(dir->d);
return 0;
}

lfs_entry_t entry;
err = lfs_dir_find(lfs, dir, &entry, &path);
if (err) {
Expand Down Expand Up @@ -1799,14 +1803,6 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {

/// General fs operations ///
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
// check for root, can only be something like '/././../.'
if (strspn(path, "/.") == strlen(path)) {
memset(info, 0, sizeof(*info));
info->type = LFS_TYPE_DIR;
strcpy(info->name, "/");
return 0;
}

lfs_dir_t cwd;
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
if (err) {
Expand All @@ -1825,11 +1821,15 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
info->size = entry.d.u.file.size;
}

err = lfs_bd_read(lfs, cwd.pair[0],
entry.off + 4+entry.d.elen+entry.d.alen,
info->name, entry.d.nlen);
if (err) {
return err;
if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) {
strcpy(info->name, "/");
} else {
err = lfs_bd_read(lfs, cwd.pair[0],
entry.off + 4+entry.d.elen+entry.d.alen,
info->name, entry.d.nlen);
if (err) {
return err;
}
}

return 0;
Expand Down
4 changes: 4 additions & 0 deletions tests/test_paths.sh
Expand Up @@ -108,6 +108,10 @@ tests/test.py << TEST
lfs_stat(&lfs, "/", &info) => 0;
info.type => LFS_TYPE_DIR;
strcmp(info.name, "/") => 0;
lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
lfs_file_open(&lfs, &file[0], "/", LFS_O_WRONLY | LFS_O_CREAT)
=> LFS_ERR_ISDIR;
lfs_unmount(&lfs) => 0;
TEST

Expand Down

0 comments on commit d9c3637

Please sign in to comment.