diff --git a/Makefile b/Makefile index c579ff4..b00d018 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ obj-y += source/core/flash.o obj-y += source/fs/mufs/block.o obj-y += source/fs/mufs/dir.o +obj-y += source/fs/mufs/file.o obj-y += source/fs/mufs/super.o obj-y += source/fs/mufs/tree.o diff --git a/include/fs/mufs.h b/include/fs/mufs.h index 65c3638..9e02382 100644 --- a/include/fs/mufs.h +++ b/include/fs/mufs.h @@ -3,6 +3,7 @@ struct flash_dev; struct mufs; struct mufs_dir; +struct mufs_file; struct mufs_tree { struct mufs *fs; @@ -33,3 +34,9 @@ struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path); void mufs_closedir(struct mufs_dir *dir); int mufs_readdir(struct mufs_dir *dir, struct mufs_dirent *dirent); int mufs_mkdir(struct mufs *fs, const char *path); + +int mufs_create(struct mufs *fs, const char *path); +struct mufs_file *mufs_open(struct mufs *fs, const char *path); +void mufs_close(struct mufs_file *file); +size_t mufs_read(struct mufs_file *file, void *data, size_t len); +size_t mufs_write(struct mufs_file *file, const void *data, size_t len); diff --git a/source/fs/mufs/file.c b/source/fs/mufs/file.c new file mode 100644 index 0000000..4786b3c --- /dev/null +++ b/source/fs/mufs/file.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include + +#include +#include + +#include + +#include "dir.h" +#include "tree.h" + +struct mufs_file { + struct mufs *fs; + struct mufs_tree *tree; + uint32_t va; +}; + +int mufs_create(struct mufs *fs, const char *path) +{ + struct mufs_dirent dirent; + struct mufs_tree *tree; + size_t len; + char *s; + char *name; + + if (!path || *path == '\0') + return -1; + + if (!(s = mufs_abspath(path))) + return -1; + + /* TODO: already exists. */ + if (resolve_path(fs, s)) { + free(s); + return 0; + } + + if (!(name = strrchr(s, '/'))) { + name = s; + s = "/"; + } else { + *name++ = '\0'; + } + + if (*name == '\0') + return -1; + + if (!(tree = resolve_path(fs, s))) + return -1; + + len = min(strlen(name), sizeof(dirent.path) - 1); + memcpy(dirent.path, name, len); + dirent.path[len] = '\0'; + dirent.type = MUFS_FILE; + + dirent.tree.fs = fs; + dirent.tree.file_size = 0; + 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) + return 0; + + if (write_dirent(tree, align_up(tree->file_size, + fs->dev->log2_block_size), &dirent) > 0) + return 0; + + return -1; +} + +struct mufs_file *mufs_open(struct mufs *fs, const char *path) +{ + struct mufs_file *file; + + if (!(file = malloc(sizeof(*file)))) + return NULL; + + file->fs = fs; + + if (!(file->tree = resolve_path(fs, path))) + goto err_free_file; + + file->va = 0; + + return file; + +err_free_file: + free(file); + return NULL; +} + +void mufs_close(struct mufs_file *file) +{ + if (!file) + return; + + free(file); +} + +size_t mufs_read(struct mufs_file *file, void *data, size_t len) +{ + size_t ret; + + if (!file || !data || !len) + return 0; + + if (!(ret = mufs_tree_read(file->tree, data, file->va, len))) + return 0; + + file->va += ret; + + return ret; +} + +size_t mufs_write(struct mufs_file *file, const void *data, size_t len) +{ + size_t ret; + + if (!file || !data || !len) + return 0; + + if (!(ret = mufs_tree_write(file->tree, (void *)data, file->va, len))) + return 0; + + file->va += ret; + + if (file->tree->file_size <= file->va) { + struct mufs_dtree dtree; + + dtree.file_size = file->tree->file_size; + dtree.root = file->tree->root; + dtree.depth = file->tree->depth; + + if (flash_write(file->fs->dev, file->tree->va, &dtree, + sizeof dtree) == 0) + return 0; + } + + return ret; +}