mufs: return tree as an argument in resolve_path() and free tree objects where necessary
This commit is contained in:
parent
4ed40e75c6
commit
59a71a4608
4 changed files with 79 additions and 53 deletions
|
@ -87,27 +87,28 @@ err_free_dir:
|
||||||
return NULL;
|
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_stat *stat)
|
||||||
{
|
{
|
||||||
struct mufs_dir *dir = NULL;
|
struct mufs_dir *dir = NULL;
|
||||||
struct mufs_dirent entry;
|
struct mufs_dirent entry;
|
||||||
struct mufs_tree *tree = NULL;
|
|
||||||
char *s, *p, *end;
|
char *s, *p, *end;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!(s = mufs_abspath(path)))
|
if (!(s = mufs_abspath(path)))
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
if (strcmp(s, "/") == 0) {
|
if (strcmp(s, "/") == 0) {
|
||||||
tree = &fs->root;
|
|
||||||
|
|
||||||
if (stat) {
|
if (stat) {
|
||||||
stat->type = MUFS_DIR;
|
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)))
|
if (!(dir = open_dirent(fs, NULL)))
|
||||||
|
@ -124,8 +125,10 @@ struct mufs_tree *resolve_path(struct mufs *fs, const char *path,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mufs_closedir(dir);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_closedir;
|
goto err_free_s;
|
||||||
|
|
||||||
if (!(dir = open_dirent(fs, &entry)))
|
if (!(dir = open_dirent(fs, &entry)))
|
||||||
goto err_free_s;
|
goto err_free_s;
|
||||||
|
@ -134,19 +137,23 @@ struct mufs_tree *resolve_path(struct mufs *fs, const char *path,
|
||||||
if (!dir)
|
if (!dir)
|
||||||
goto err_free_s;
|
goto err_free_s;
|
||||||
|
|
||||||
tree = dir->tree;
|
|
||||||
dir->tree = NULL;
|
|
||||||
|
|
||||||
if (stat) {
|
if (stat) {
|
||||||
stat->type = entry.type;
|
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);
|
mufs_closedir(dir);
|
||||||
|
free(s);
|
||||||
|
return 0;
|
||||||
|
|
||||||
err_free_s:
|
err_free_s:
|
||||||
free(s);
|
free(s);
|
||||||
return tree;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path)
|
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;
|
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;
|
goto err_free_dir;
|
||||||
|
|
||||||
dir->va = 0;
|
dir->va = 0;
|
||||||
|
@ -176,9 +183,7 @@ void mufs_closedir(struct mufs_dir *dir)
|
||||||
if (!dir)
|
if (!dir)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dir->tree && dir->tree != &dir->fs->root)
|
mufs_del_tree(dir->tree);
|
||||||
free(dir->tree);
|
|
||||||
|
|
||||||
free(dir);
|
free(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct mufs_dentry {
|
||||||
uint16_t path_len;
|
uint16_t path_len;
|
||||||
} __attribute__((packed));
|
} __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);
|
struct mufs_stat *stat);
|
||||||
size_t find_dirent_size(struct mufs *fs, struct mufs_tree *tree,
|
size_t find_dirent_size(struct mufs *fs, struct mufs_tree *tree,
|
||||||
uint32_t va);
|
uint32_t va);
|
||||||
|
|
|
@ -34,25 +34,27 @@ struct mufs_file *mufs_open(struct mufs *fs, const char *path, int mode)
|
||||||
|
|
||||||
file->fs = fs;
|
file->fs = fs;
|
||||||
|
|
||||||
if (!(file->tree = resolve_path(fs, path, &stat))) {
|
if (resolve_path(fs, path, &file->tree, &stat) < 0) {
|
||||||
if (!(mode & MUFS_WRITE))
|
if (!(mode & MUFS_WRITE))
|
||||||
goto err_free_file;
|
goto err_free_file;
|
||||||
|
|
||||||
if (mufs_create(fs, path) < 0)
|
if (mufs_create(fs, path) < 0)
|
||||||
goto err_free_file;
|
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;
|
goto err_free_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stat.type != MUFS_FILE)
|
if (stat.type != MUFS_FILE)
|
||||||
goto err_free_file;
|
goto err_del_tree;
|
||||||
|
|
||||||
file->mode = mode;
|
file->mode = mode;
|
||||||
file->va = 0;
|
file->va = 0;
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
|
|
||||||
|
err_del_tree:
|
||||||
|
mufs_del_tree(file->tree);
|
||||||
err_free_file:
|
err_free_file:
|
||||||
free(file);
|
free(file);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -140,14 +142,22 @@ int mufs_unlink(struct mufs *fs, const char *path)
|
||||||
struct mufs_stat stat;
|
struct mufs_stat stat;
|
||||||
struct mufs_tree *tree;
|
struct mufs_tree *tree;
|
||||||
|
|
||||||
if (!(tree = resolve_path(fs, path, &stat)))
|
if (resolve_path(fs, path, &tree, &stat) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (stat.type != MUFS_FILE)
|
if (stat.type != MUFS_FILE)
|
||||||
return -1;
|
goto err_del_tree;
|
||||||
|
|
||||||
if (mufs_shrink_tree(tree, 0) < 0)
|
if (mufs_shrink_tree(tree, 0) < 0)
|
||||||
return -1;
|
goto err_del_tree;
|
||||||
|
|
||||||
return mufs_rmpath(fs, path);
|
if (mufs_rmpath(fs, path) < 0)
|
||||||
|
goto err_del_tree;
|
||||||
|
|
||||||
|
mufs_del_tree(tree);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_del_tree:
|
||||||
|
mufs_del_tree(tree);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,16 @@ int mufs_mkpath(struct mufs *fs, const char *path, struct mufs_tree *subtree,
|
||||||
struct mufs_stat stat;
|
struct mufs_stat stat;
|
||||||
struct mufs_dirent dirent;
|
struct mufs_dirent dirent;
|
||||||
struct mufs_tree *tree;
|
struct mufs_tree *tree;
|
||||||
size_t len;
|
|
||||||
char *s;
|
char *s;
|
||||||
char *name;
|
char *name;
|
||||||
|
size_t len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!(s = mufs_abspath(path)))
|
if (!(s = mufs_abspath(path)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* TODO: already exists. */
|
/* TODO: already exists. */
|
||||||
if (resolve_path(fs, s, NULL)) {
|
if (resolve_path(fs, s, NULL, NULL) == 0) {
|
||||||
free(s);
|
free(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +42,7 @@ int mufs_mkpath(struct mufs *fs, const char *path, struct mufs_tree *subtree,
|
||||||
if (*name == '\0')
|
if (*name == '\0')
|
||||||
return -1;
|
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;
|
return -1;
|
||||||
|
|
||||||
memset(&dirent, 0, sizeof dirent);
|
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);
|
tree->file_size = find_dirent_size(fs, tree, tree->file_size);
|
||||||
|
|
||||||
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) {
|
||||||
|
mufs_del_tree(tree);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (write_dirent(tree, align_up(tree->file_size,
|
ret = write_dirent(tree, align_up(tree->file_size,
|
||||||
fs->dev->log2_block_size), &dirent) > 0)
|
fs->dev->log2_block_size), &dirent);
|
||||||
return 0;
|
mufs_del_tree(tree);
|
||||||
|
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int remove_page(struct mufs_tree *tree, uint32_t va)
|
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 = strrchr(s, '/');
|
||||||
*name++ = '\0';
|
*name++ = '\0';
|
||||||
|
|
||||||
if (!(tree = resolve_path(fs, s, NULL)))
|
if (resolve_path(fs, s, &tree, NULL) < 0)
|
||||||
goto err_free_s;
|
goto err_free_s;
|
||||||
|
|
||||||
if (!(dir = mufs_opendir(fs, 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) {
|
for (va = dir->va; (ret = mufs_readdir(dir, &ent)) == 0; va = dir->va) {
|
||||||
if (strcmp(ent.path, name) == 0)
|
if (strcmp(ent.path, name) == 0)
|
||||||
|
@ -127,31 +130,39 @@ int mufs_rmpath(struct mufs *fs, const char *path)
|
||||||
mufs_closedir(dir);
|
mufs_closedir(dir);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_free_s;
|
goto err_del_tree;
|
||||||
|
|
||||||
offset = va & ((UINT32_C(1) << dev->log2_block_size) - 1);
|
offset = va & ((UINT32_C(1) << dev->log2_block_size) - 1);
|
||||||
va = align(va, dev->log2_block_size);
|
va = align(va, dev->log2_block_size);
|
||||||
|
|
||||||
if (mufs_tree_read(tree, data, va, 1 << dev->log2_block_size) == 0)
|
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);
|
entry = (struct mufs_dentry *)(data + offset);
|
||||||
len = sizeof *entry + entry->path_len;
|
len = sizeof *entry + entry->path_len;
|
||||||
next = (struct mufs_dentry *)(data + offset + len);
|
next = (struct mufs_dentry *)(data + offset + len);
|
||||||
|
|
||||||
if (!offset && (len == (UINT32_C(1) << dev->log2_block_size) ||
|
if (!offset && (len == (UINT32_C(1) << dev->log2_block_size) ||
|
||||||
!next->type))
|
!next->type)) {
|
||||||
return remove_page(tree, va);
|
ret = remove_page(tree, va);
|
||||||
|
mufs_del_tree(tree);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
memmove(data + offset, data + offset + len,
|
memmove(data + offset, data + offset + len,
|
||||||
(UINT32_C(1) << dev->log2_block_size) - offset - len);
|
(UINT32_C(1) << dev->log2_block_size) - offset - len);
|
||||||
|
|
||||||
if (mufs_tree_write(tree, data, va, 1 << dev->log2_block_size) == 0)
|
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);
|
free(s);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_del_tree:
|
||||||
|
mufs_del_tree(tree);
|
||||||
err_free_s:
|
err_free_s:
|
||||||
free(s);
|
free(s);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -159,10 +170,7 @@ err_free_s:
|
||||||
|
|
||||||
int mufs_stat(struct mufs *fs, const char *path, struct mufs_stat *stat)
|
int mufs_stat(struct mufs *fs, const char *path, struct mufs_stat *stat)
|
||||||
{
|
{
|
||||||
if (!resolve_path(fs, path, stat))
|
return resolve_path(fs, path, NULL, stat);
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mufs_rename(struct mufs *fs, const char *old, const char *new)
|
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;
|
struct mufs_tree *subtree;
|
||||||
char *path;
|
char *path;
|
||||||
unsigned type;
|
unsigned type;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!(path = mufs_abspath(old)))
|
if (!(path = mufs_abspath(old)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!(subtree = resolve_path(fs, path, &stat)))
|
ret = resolve_path(fs, path, &subtree, &stat);
|
||||||
goto err_free_path;
|
|
||||||
|
|
||||||
type = stat.type;
|
|
||||||
free(path);
|
free(path);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
type = stat.type;
|
||||||
|
|
||||||
if (mufs_mkpath(fs, new, subtree, type) < 0)
|
if (mufs_mkpath(fs, new, subtree, type) < 0)
|
||||||
goto err_free_path;
|
goto err_del_subtree;
|
||||||
|
|
||||||
if (mufs_rmpath(fs, old) < 0)
|
if (mufs_rmpath(fs, old) < 0)
|
||||||
return -1;
|
goto err_del_subtree;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_free_path:
|
err_del_subtree:
|
||||||
free(path);
|
mufs_del_tree(subtree);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue