You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
2.7 KiB
164 lines
2.7 KiB
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <flash.h>
|
|
#include <macros.h>
|
|
#include <mufs.h>
|
|
|
|
#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;
|
|
}
|
|
|