From 0e9474d3772d6662f6f3141f37f0e5f8894847cd Mon Sep 17 00:00:00 2001 From: "S.J.R. van Schaik" Date: Fri, 9 Jun 2017 16:29:37 +0200 Subject: [PATCH] mufs: add support for path resolution --- source/fs/mufs/dir.c | 127 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 103 insertions(+), 24 deletions(-) diff --git a/source/fs/mufs/dir.c b/source/fs/mufs/dir.c index 17248dc..189ad5f 100644 --- a/source/fs/mufs/dir.c +++ b/source/fs/mufs/dir.c @@ -17,18 +17,7 @@ struct mufs_dir { uint32_t va; }; -static int resolve(struct mufs *fs, struct mufs_tree *tree, const char *path) -{ - 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) +static struct mufs_dir *mufs_opendir2(struct mufs *fs, struct mufs_dirent *entry) { struct mufs_dir *dir; @@ -36,13 +25,101 @@ struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path) return NULL; 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; return dir; + +err_free_dir: + free(dir); + return NULL; } 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; - 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; dirent->tree.fs = fs; @@ -130,8 +208,6 @@ static size_t write_dirent(struct mufs_tree *tree, dtree.root = tree->root; dtree.depth = tree->depth; - printf("tree->va=%u\n", tree->va); - if (flash_write(tree->fs->dev, tree->va, &dtree, sizeof dtree) == 0) return 0; @@ -157,14 +233,13 @@ int mufs_readdir(struct mufs_dir *dir, struct mufs_dirent *dirent) return 0; } - printf("return?\n"); return -1; } int mufs_mkdir(struct mufs *fs, const char *path) { struct mufs_dirent dirent; - struct mufs_tree tree; + struct mufs_tree *tree; size_t len; char *s; char *name; @@ -172,6 +247,10 @@ int mufs_mkdir(struct mufs *fs, const char *path) if (!path) return -1; + /* TODO: already exists. */ + if (resolve_path(fs, path)) + return 0; + if (!(s = strdup(path))) return -1; @@ -185,7 +264,7 @@ int mufs_mkdir(struct mufs *fs, const char *path) if (*name == '\0') return -1; - if (resolve(fs, &tree, s) < 0) + if (!(tree = resolve_path(fs, s))) return -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.depth = 0; - if (!is_aligned(tree.file_size, fs->dev->log2_block_size) && - write_dirent(&tree, tree.file_size, &dirent) > 0) + if (!is_aligned(tree->file_size, fs->dev->log2_block_size) && + write_dirent(tree, tree->file_size, &dirent) > 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) return 0;