Source code for the Trusted Boot Module.
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.
 
 
 
tbm-mcu/source/fs/mufs/path.c

227 lines
4.5 KiB

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <flash.h>
#include <macros.h>
#include <fs/mufs.h>
#include "dir.h"
#include "path.h"
#include "tree.h"
int mufs_mkpath(struct mufs *fs, const char *path, struct mufs_tree *subtree,
unsigned type)
{
struct mufs_stat stat;
struct mufs_dirent dirent;
struct mufs_tree *tree;
size_t len;
char *s;
char *name;
if (!(s = mufs_abspath(path)))
return -1;
/* TODO: already exists. */
if (resolve_path(fs, s, NULL)) {
free(s);
return 0;
}
name = strrchr(s, '/');
*name++ = '\0';
if (*s == '\0')
s = "/";
if (*name == '\0')
return -1;
if (!(tree = resolve_path(fs, s, &stat)) || stat.type != MUFS_DIR)
return -1;
memset(&dirent, 0, sizeof dirent);
len = min(strlen(name), sizeof(dirent.path) - 1);
memcpy(dirent.path, name, len);
dirent.path[len] = '\0';
dirent.type = type;
dirent.tree.fs = fs;
if (subtree) {
dirent.tree.file_size = subtree->file_size;
dirent.tree.root = subtree->root;
dirent.tree.depth = subtree->depth;
}
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)
return 0;
if (write_dirent(tree, align_up(tree->file_size,
fs->dev->log2_block_size), &dirent) > 0)
return 0;
return -1;
}
static int remove_page(struct mufs_tree *tree, uint32_t va)
{
struct mufs *fs = tree->fs;
struct flash_dev *dev = fs->dev;
uint32_t last_va, page;
last_va = align(tree->file_size - 1, dev->log2_block_size);
if (mufs_lookup_page(tree, &page, last_va) < 0)
return -1;
mufs_free_page(tree, va);
if (va != last_va) {
mufs_unmap_page(tree, last_va);
mufs_map_page(tree, va, page);
}
tree->file_size = last_va;
return mufs_sync_tree(tree);
}
int mufs_rmpath(struct mufs *fs, const char *path)
{
struct flash_dev *dev = fs->dev;
char data[1 << dev->log2_block_size];
struct mufs_dentry *entry, *next;
struct mufs_dirent ent;
struct mufs_tree *tree;
struct mufs_dir *dir;
char *s, *name;
uint32_t va, offset, len;
int ret;
if (!(s = mufs_abspath(path)))
return -1;
name = strrchr(s, '/');
*name++ = '\0';
if (!(tree = resolve_path(fs, s, NULL)))
goto err_free_s;
if (!(dir = mufs_opendir(fs, s)))
goto err_free_s;
for (va = dir->va; (ret = mufs_readdir(dir, &ent)) == 0; va = dir->va) {
if (strcmp(ent.path, name) == 0)
break;
}
mufs_closedir(dir);
if (ret < 0)
goto err_free_s;
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;
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);
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;
free(s);
return 0;
err_free_s:
free(s);
return -1;
}
int mufs_stat(struct mufs *fs, const char *path, struct mufs_stat *stat)
{
if (!resolve_path(fs, path, stat))
return -1;
return 0;
}
int mufs_rename(struct mufs *fs, const char *old, const char *new)
{
struct mufs_stat stat;
struct mufs_dirent dirent;
struct mufs_tree *tree;
size_t len;
char *full_old, *full_new;
char *name;
int ret = -1;
if (!(full_new = mufs_abspath(new)))
return -1;
if (resolve_path(fs, full_new, NULL))
goto err_free_new;
if (!(full_old = mufs_abspath(old)))
goto err_free_new;
name = strrchr(full_new, '/');
*name++ = '\0';
if (*full_new == '\0')
full_new = "/";
if (*name == '\0')
goto err_free_old;
if (!(tree = resolve_path(fs, full_old, &stat)))
goto err_free_old;
len = min(strlen(name), sizeof(dirent.path) - 1);
memcpy(dirent.path, name, len);
dirent.path[len] = '\0';
dirent.type = stat.type;
dirent.tree.fs = fs;
dirent.tree.file_size = tree->file_size;
dirent.tree.root = tree->root;
dirent.tree.depth = tree->depth;
if (!is_aligned(tree->file_size, fs->dev->log2_block_size) &&
write_dirent(tree, tree->file_size, &dirent) > 0)
goto err_free_old;
if (write_dirent(tree, align_up(tree->file_size,
fs->dev->log2_block_size), &dirent) > 0)
goto err_free_old;
if (mufs_rmpath(fs, full_old) < 0)
goto err_free_old;
ret = 0;
err_free_old:
free(full_old);
err_free_new:
free(full_new);
return ret;
}