diff --git a/source/fs/mufs/dir.c b/source/fs/mufs/dir.c index b64dfd6..8927fd1 100644 --- a/source/fs/mufs/dir.c +++ b/source/fs/mufs/dir.c @@ -87,27 +87,28 @@ err_free_dir: return NULL; } -struct mufs_tree *resolve_path(struct mufs *fs, const char *path, +int resolve_path(struct mufs *fs, const char *path, struct mufs_tree **tree, struct mufs_stat *stat) { struct mufs_dir *dir = NULL; struct mufs_dirent entry; - struct mufs_tree *tree = NULL; char *s, *p, *end; int ret; if (!(s = mufs_abspath(path))) - return NULL; + return -1; if (strcmp(s, "/") == 0) { - tree = &fs->root; - if (stat) { stat->type = MUFS_DIR; - stat->file_size = tree->file_size; + stat->file_size = fs->root.file_size; } - goto err_free_s; + if (tree) + *tree = &fs->root; + + free(s); + return 0; } if (!(dir = open_dirent(fs, NULL))) @@ -124,8 +125,10 @@ struct mufs_tree *resolve_path(struct mufs *fs, const char *path, break; } + mufs_closedir(dir); + if (ret < 0) - goto err_closedir; + goto err_free_s; if (!(dir = open_dirent(fs, &entry))) goto err_free_s; @@ -134,19 +137,23 @@ struct mufs_tree *resolve_path(struct mufs *fs, const char *path, if (!dir) goto err_free_s; - tree = dir->tree; - dir->tree = NULL; - if (stat) { stat->type = entry.type; - stat->file_size = tree->file_size; + stat->file_size = dir->tree->file_size; + } + + if (tree) { + *tree = dir->tree; + dir->tree = NULL; } -err_closedir: mufs_closedir(dir); + free(s); + return 0; + err_free_s: free(s); - return tree; + return -1; } struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path) @@ -159,7 +166,7 @@ struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path) dir->fs = fs; - if (!(dir->tree = resolve_path(fs, path, &stat)) || stat.type != MUFS_DIR) + if (resolve_path(fs, path, &dir->tree, &stat) < 0 || stat.type != MUFS_DIR) goto err_free_dir; dir->va = 0; @@ -176,9 +183,7 @@ void mufs_closedir(struct mufs_dir *dir) if (!dir) return; - if (dir->tree && dir->tree != &dir->fs->root) - free(dir->tree); - + mufs_del_tree(dir->tree); free(dir); } diff --git a/source/fs/mufs/dir.h b/source/fs/mufs/dir.h index a9f09d0..4a5b543 100644 --- a/source/fs/mufs/dir.h +++ b/source/fs/mufs/dir.h @@ -18,7 +18,7 @@ struct mufs_dentry { uint16_t path_len; } __attribute__((packed)); -struct mufs_tree *resolve_path(struct mufs *fs, const char *path, +int resolve_path(struct mufs *fs, const char *path, struct mufs_tree **tree, struct mufs_stat *stat); size_t find_dirent_size(struct mufs *fs, struct mufs_tree *tree, uint32_t va); diff --git a/source/fs/mufs/file.c b/source/fs/mufs/file.c index dfa8567..6d5d2f0 100644 --- a/source/fs/mufs/file.c +++ b/source/fs/mufs/file.c @@ -34,25 +34,27 @@ struct mufs_file *mufs_open(struct mufs *fs, const char *path, int mode) file->fs = fs; - if (!(file->tree = resolve_path(fs, path, &stat))) { + if (resolve_path(fs, path, &file->tree, &stat) < 0) { if (!(mode & MUFS_WRITE)) goto err_free_file; if (mufs_create(fs, path) < 0) goto err_free_file; - if (!(file->tree = resolve_path(fs, path, &stat))) + if (resolve_path(fs, path, &file->tree, &stat) < 0) goto err_free_file; } if (stat.type != MUFS_FILE) - goto err_free_file; + goto err_del_tree; file->mode = mode; file->va = 0; return file; +err_del_tree: + mufs_del_tree(file->tree); err_free_file: free(file); return NULL; @@ -140,14 +142,22 @@ int mufs_unlink(struct mufs *fs, const char *path) struct mufs_stat stat; struct mufs_tree *tree; - if (!(tree = resolve_path(fs, path, &stat))) + if (resolve_path(fs, path, &tree, &stat) < 0) return -1; if (stat.type != MUFS_FILE) - return -1; + goto err_del_tree; if (mufs_shrink_tree(tree, 0) < 0) - return -1; + goto err_del_tree; + + if (mufs_rmpath(fs, path) < 0) + goto err_del_tree; + + mufs_del_tree(tree); + return 0; - return mufs_rmpath(fs, path); +err_del_tree: + mufs_del_tree(tree); + return -1; } diff --git a/source/fs/mufs/path.c b/source/fs/mufs/path.c index 1d8a27e..b58f9c0 100644 --- a/source/fs/mufs/path.c +++ b/source/fs/mufs/path.c @@ -19,15 +19,16 @@ int mufs_mkpath(struct mufs *fs, const char *path, struct mufs_tree *subtree, struct mufs_stat stat; struct mufs_dirent dirent; struct mufs_tree *tree; - size_t len; char *s; char *name; + size_t len; + int ret; if (!(s = mufs_abspath(path))) return -1; /* TODO: already exists. */ - if (resolve_path(fs, s, NULL)) { + if (resolve_path(fs, s, NULL, NULL) == 0) { free(s); return 0; } @@ -41,7 +42,7 @@ int mufs_mkpath(struct mufs *fs, const char *path, struct mufs_tree *subtree, if (*name == '\0') return -1; - if (!(tree = resolve_path(fs, s, &stat)) || stat.type != MUFS_DIR) + if (resolve_path(fs, s, &tree, &stat) < 0 || stat.type != MUFS_DIR) return -1; memset(&dirent, 0, sizeof dirent); @@ -62,14 +63,16 @@ int mufs_mkpath(struct mufs *fs, const char *path, struct mufs_tree *subtree, tree->file_size = find_dirent_size(fs, tree, tree->file_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) { + mufs_del_tree(tree); return 0; + } - if (write_dirent(tree, align_up(tree->file_size, - fs->dev->log2_block_size), &dirent) > 0) - return 0; + ret = write_dirent(tree, align_up(tree->file_size, + fs->dev->log2_block_size), &dirent); + mufs_del_tree(tree); - return -1; + return ret; } static int remove_page(struct mufs_tree *tree, uint32_t va) @@ -113,11 +116,11 @@ int mufs_rmpath(struct mufs *fs, const char *path) name = strrchr(s, '/'); *name++ = '\0'; - if (!(tree = resolve_path(fs, s, NULL))) + if (resolve_path(fs, s, &tree, NULL) < 0) goto err_free_s; if (!(dir = mufs_opendir(fs, s))) - goto err_free_s; + goto err_del_tree; for (va = dir->va; (ret = mufs_readdir(dir, &ent)) == 0; va = dir->va) { if (strcmp(ent.path, name) == 0) @@ -127,31 +130,39 @@ int mufs_rmpath(struct mufs *fs, const char *path) mufs_closedir(dir); if (ret < 0) - goto err_free_s; + goto err_del_tree; offset = va & ((UINT32_C(1) << dev->log2_block_size) - 1); va = align(va, dev->log2_block_size); if (mufs_tree_read(tree, data, va, 1 << dev->log2_block_size) == 0) - return -1; + goto err_del_tree; entry = (struct mufs_dentry *)(data + offset); len = sizeof *entry + entry->path_len; next = (struct mufs_dentry *)(data + offset + len); if (!offset && (len == (UINT32_C(1) << dev->log2_block_size) || - !next->type)) - return remove_page(tree, va); + !next->type)) { + ret = remove_page(tree, va); + mufs_del_tree(tree); + free(s); + + return ret; + } memmove(data + offset, data + offset + len, (UINT32_C(1) << dev->log2_block_size) - offset - len); if (mufs_tree_write(tree, data, va, 1 << dev->log2_block_size) == 0) - return -1; + goto err_del_tree; + mufs_del_tree(tree); free(s); return 0; +err_del_tree: + mufs_del_tree(tree); err_free_s: free(s); return -1; @@ -159,10 +170,7 @@ err_free_s: int mufs_stat(struct mufs *fs, const char *path, struct mufs_stat *stat) { - if (!resolve_path(fs, path, stat)) - return -1; - - return 0; + return resolve_path(fs, path, NULL, stat); } int mufs_rename(struct mufs *fs, const char *old, const char *new) @@ -171,25 +179,28 @@ int mufs_rename(struct mufs *fs, const char *old, const char *new) struct mufs_tree *subtree; char *path; unsigned type; + int ret; if (!(path = mufs_abspath(old))) return -1; - if (!(subtree = resolve_path(fs, path, &stat))) - goto err_free_path; + ret = resolve_path(fs, path, &subtree, &stat); + free(path); + + if (ret < 0) + return -1; type = stat.type; - free(path); if (mufs_mkpath(fs, new, subtree, type) < 0) - goto err_free_path; + goto err_del_subtree; if (mufs_rmpath(fs, old) < 0) - return -1; + goto err_del_subtree; return 0; -err_free_path: - free(path); +err_del_subtree: + mufs_del_tree(subtree); return -1; }