#include #include #include #include #include #include #include #include "dir.h" #include "path.h" #include "tree.h" struct mufs_file { struct mufs *fs; struct mufs_tree *tree; int mode; uint32_t va; }; int mufs_create(struct mufs *fs, const char *path) { return mufs_mkpath(fs, path, NULL, MUFS_FILE); } struct mufs_file *mufs_open(struct mufs *fs, const char *path, int mode) { struct mufs_stat stat; struct mufs_file *file; if (!(file = malloc(sizeof(*file)))) return NULL; file->fs = fs; 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 (resolve_path(fs, path, &file->tree, &stat) < 0) goto err_free_file; } if (stat.type != MUFS_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; } void mufs_close(struct mufs_file *file) { if (!file) return; mufs_del_tree(file->tree); free(file); } long mufs_seek(struct mufs_file *file, long offset, int whence) { if (!file) return -1; switch (whence) { case SEEK_SET: break; case SEEK_CUR: offset += file->va; break; case SEEK_END: offset += file->tree->file_size; break; default: return -1; } if (offset > (long)file->tree->file_size || offset >= (long)UINT32_MAX) return -1; file->va = offset; return offset; } size_t mufs_read(struct mufs_file *file, void *data, size_t len) { size_t ret; if (!file || !data || !len) return 0; if (!(file->mode & MUFS_READ)) return 0; if (file->va >= file->tree->file_size) return 0; if (!(ret = mufs_tree_read(file->tree, data, file->va, len))) return 0; ret = min(ret, file->tree->file_size - file->va); 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 (!(file->mode & MUFS_WRITE)) return 0; if (file->mode & MUFS_APPEND) file->va = file->tree->file_size; if (!(ret = mufs_tree_write(file->tree, (void *)data, file->va, len))) return 0; file->va += ret; if (file->tree->file_size <= file->va) { file->tree->file_size = file->va; if (mufs_sync_tree(file->tree) < 0) return 0; } return ret; } int mufs_unlink(struct mufs *fs, const char *path) { struct mufs_stat stat; struct mufs_tree *tree; if (resolve_path(fs, path, &tree, &stat) < 0) return -1; if (stat.type != MUFS_FILE) goto err_del_tree; if (mufs_shrink_tree(tree, 0) < 0) goto err_del_tree; 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; }