mufs: add support for path resolution
This commit is contained in:
parent
e18107d2d5
commit
0e9474d377
1 changed files with 103 additions and 24 deletions
|
@ -17,18 +17,7 @@ struct mufs_dir {
|
||||||
uint32_t va;
|
uint32_t va;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int resolve(struct mufs *fs, struct mufs_tree *tree, const char *path)
|
static struct mufs_dir *mufs_opendir2(struct mufs *fs, struct mufs_dirent *entry)
|
||||||
{
|
|
||||||
if (!path || *path == '\0') {
|
|
||||||
memcpy(tree, &fs->root, sizeof *tree);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: resolve directories. */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path)
|
|
||||||
{
|
{
|
||||||
struct mufs_dir *dir;
|
struct mufs_dir *dir;
|
||||||
|
|
||||||
|
@ -36,13 +25,101 @@ struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dir->fs = fs;
|
dir->fs = fs;
|
||||||
|
dir->va = 0;
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
if (!(dir->tree = malloc(sizeof *dir->tree)))
|
||||||
|
goto err_free_dir;
|
||||||
|
|
||||||
|
memcpy(dir->tree, &entry->tree, sizeof *dir->tree);
|
||||||
|
} else {
|
||||||
|
dir->tree = &fs->root;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
|
||||||
|
err_free_dir:
|
||||||
|
free(dir);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mufs_tree *resolve_path(struct mufs *fs, const char *path)
|
||||||
|
{
|
||||||
|
struct mufs_dir *dir;
|
||||||
|
struct mufs_dirent entry;
|
||||||
|
struct mufs_tree *tree;
|
||||||
|
char *s, *p, *end;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!path || *path == '\0')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (*path == '/')
|
||||||
|
++path;
|
||||||
|
|
||||||
|
if (*path == '\0')
|
||||||
|
return &fs->root;
|
||||||
|
|
||||||
|
if (!(s = strdup(path)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(dir = mufs_opendir2(fs, NULL)))
|
||||||
|
goto err_free_s;
|
||||||
|
|
||||||
|
for (p = s; *p != '\0'; p = end) {
|
||||||
|
end = p + strcspn(p, "/");
|
||||||
|
|
||||||
|
while (*end == '/')
|
||||||
|
*end++ = '\0';
|
||||||
|
|
||||||
|
while ((ret = mufs_readdir(dir, &entry)) == 0) {
|
||||||
|
if (strcmp(entry.path, p) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mufs_closedir(dir);
|
||||||
|
|
||||||
|
if (!(dir = mufs_opendir2(fs, &entry)))
|
||||||
|
goto err_free_s;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_close_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree = dir->tree;
|
||||||
|
|
||||||
|
mufs_closedir(dir);
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
|
||||||
|
err_close_dir:
|
||||||
|
mufs_closedir(dir);
|
||||||
|
err_free_s:
|
||||||
|
free(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path)
|
||||||
|
{
|
||||||
|
struct mufs_dir *dir;
|
||||||
|
|
||||||
|
if (!(dir = malloc(sizeof(*dir))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dir->fs = fs;
|
||||||
|
|
||||||
|
if (!(dir->tree = resolve_path(fs, path)))
|
||||||
|
goto err_free_dir;
|
||||||
|
|
||||||
/* TODO: resolve path */
|
|
||||||
(void)path;
|
|
||||||
memcpy(&dir->tree, &fs->root, sizeof dir->tree);
|
|
||||||
dir->va = 0;
|
dir->va = 0;
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
|
|
||||||
|
err_free_dir:
|
||||||
|
free(dir);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mufs_closedir(struct mufs_dir *dir)
|
void mufs_closedir(struct mufs_dir *dir)
|
||||||
|
@ -87,7 +164,8 @@ static size_t read_dirent(struct mufs *fs, struct mufs_tree *tree,
|
||||||
|
|
||||||
struct flash_dev *dev = fs->dev;
|
struct flash_dev *dev = fs->dev;
|
||||||
|
|
||||||
if (mufs_lookup_page(tree, &dirent->tree.va, base & ~((UINT32_C(1) << dev->log2_block_size) - 1)) < 0)
|
if (mufs_lookup_page(tree, &dirent->tree.va,
|
||||||
|
base & ~((UINT32_C(1) << dev->log2_block_size) - 1)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dirent->tree.fs = fs;
|
dirent->tree.fs = fs;
|
||||||
|
@ -130,8 +208,6 @@ static size_t write_dirent(struct mufs_tree *tree,
|
||||||
dtree.root = tree->root;
|
dtree.root = tree->root;
|
||||||
dtree.depth = tree->depth;
|
dtree.depth = tree->depth;
|
||||||
|
|
||||||
printf("tree->va=%u\n", tree->va);
|
|
||||||
|
|
||||||
if (flash_write(tree->fs->dev, tree->va, &dtree, sizeof dtree) == 0)
|
if (flash_write(tree->fs->dev, tree->va, &dtree, sizeof dtree) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -157,14 +233,13 @@ int mufs_readdir(struct mufs_dir *dir, struct mufs_dirent *dirent)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("return?\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mufs_mkdir(struct mufs *fs, const char *path)
|
int mufs_mkdir(struct mufs *fs, const char *path)
|
||||||
{
|
{
|
||||||
struct mufs_dirent dirent;
|
struct mufs_dirent dirent;
|
||||||
struct mufs_tree tree;
|
struct mufs_tree *tree;
|
||||||
size_t len;
|
size_t len;
|
||||||
char *s;
|
char *s;
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -172,6 +247,10 @@ int mufs_mkdir(struct mufs *fs, const char *path)
|
||||||
if (!path)
|
if (!path)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* TODO: already exists. */
|
||||||
|
if (resolve_path(fs, path))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!(s = strdup(path)))
|
if (!(s = strdup(path)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -185,7 +264,7 @@ int mufs_mkdir(struct mufs *fs, const char *path)
|
||||||
if (*name == '\0')
|
if (*name == '\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (resolve(fs, &tree, s) < 0)
|
if (!(tree = resolve_path(fs, s)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
len = min(strlen(name), sizeof(dirent.path) - 1);
|
len = min(strlen(name), sizeof(dirent.path) - 1);
|
||||||
|
@ -198,11 +277,11 @@ int mufs_mkdir(struct mufs *fs, const char *path)
|
||||||
dirent.tree.root = 0;
|
dirent.tree.root = 0;
|
||||||
dirent.tree.depth = 0;
|
dirent.tree.depth = 0;
|
||||||
|
|
||||||
if (!is_aligned(tree.file_size, fs->dev->log2_block_size) &&
|
if (!is_aligned(tree->file_size, fs->dev->log2_block_size) &&
|
||||||
write_dirent(&tree, tree.file_size, &dirent) > 0)
|
write_dirent(tree, tree->file_size, &dirent) > 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (write_dirent(&tree, align_up(tree.file_size,
|
if (write_dirent(tree, align_up(tree->file_size,
|
||||||
fs->dev->log2_block_size), &dirent) > 0)
|
fs->dev->log2_block_size), &dirent) > 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue