parent
99e2229bbb
commit
e18107d2d5
@ -0,0 +1,210 @@ |
||||
#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 "tree.h" |
||||
|
||||
struct mufs_dir { |
||||
struct mufs *fs; |
||||
struct mufs_tree *tree; |
||||
uint32_t va; |
||||
}; |
||||
|
||||
static int resolve(struct mufs *fs, struct mufs_tree *tree, const char *path) |
||||
{ |
||||
if (!path || *path == '\0') { |
||||
memcpy(tree, &fs->root, sizeof *tree); |
||||
return 0; |
||||
} |
||||
|
||||
/* TODO: resolve directories. */ |
||||
return -1; |
||||
} |
||||
|
||||
struct mufs_dir *mufs_opendir(struct mufs *fs, const char *path) |
||||
{ |
||||
struct mufs_dir *dir; |
||||
|
||||
if (!(dir = malloc(sizeof *dir))) |
||||
return NULL; |
||||
|
||||
dir->fs = fs; |
||||
|
||||
/* TODO: resolve path */ |
||||
(void)path; |
||||
memcpy(&dir->tree, &fs->root, sizeof dir->tree); |
||||
dir->va = 0; |
||||
|
||||
return dir; |
||||
} |
||||
|
||||
void mufs_closedir(struct mufs_dir *dir) |
||||
{ |
||||
if (!dir) |
||||
return; |
||||
|
||||
free(dir); |
||||
} |
||||
|
||||
static size_t read_dirent(struct mufs *fs, struct mufs_tree *tree, |
||||
struct mufs_dirent *dirent, uint32_t va) |
||||
{ |
||||
struct mufs_dentry entry; |
||||
size_t ret = 0; |
||||
size_t len; |
||||
uint32_t base = va; |
||||
|
||||
if (va + sizeof(entry) > tree->file_size) |
||||
return 0; |
||||
|
||||
if (mufs_read(tree, &entry, va, sizeof entry) == 0) |
||||
return 0; |
||||
|
||||
if (!entry.type) |
||||
return 0; |
||||
|
||||
ret += sizeof entry; |
||||
va += sizeof entry; |
||||
len = min(entry.path_len, sizeof(dirent->path - 1)); |
||||
|
||||
if (va + len > tree->file_size) |
||||
return 0; |
||||
|
||||
if (mufs_read(tree, dirent->path, va, len) == 0) |
||||
return 0; |
||||
|
||||
dirent->path[len] = '\0'; |
||||
ret += len; |
||||
|
||||
dirent->type = entry.type; |
||||
|
||||
struct flash_dev *dev = fs->dev; |
||||
|
||||
if (mufs_lookup_page(tree, &dirent->tree.va, base & ~((UINT32_C(1) << dev->log2_block_size) - 1)) < 0) |
||||
return 0; |
||||
|
||||
dirent->tree.fs = fs; |
||||
dirent->tree.va |= base & ((UINT32_C(1) << dev->log2_block_size) - 1); |
||||
dirent->tree.file_size = entry.file_size; |
||||
dirent->tree.root = entry.root; |
||||
dirent->tree.depth = entry.depth; |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
struct mufs_dtree { |
||||
uint32_t file_size; |
||||
uint32_t root; |
||||
uint8_t depth; |
||||
} __attribute__((packed)); |
||||
|
||||
static size_t write_dirent(struct mufs_tree *tree, |
||||
uint32_t va, struct mufs_dirent *dirent) |
||||
{ |
||||
struct mufs_dtree dtree; |
||||
struct mufs_dentry entry; |
||||
|
||||
entry.type = dirent->type; |
||||
entry.file_size = dirent->tree.file_size; |
||||
entry.root = dirent->tree.root; |
||||
entry.depth = dirent->tree.depth; |
||||
entry.path_len = strlen(dirent->path); |
||||
|
||||
if (mufs_write(tree, dirent->path, va + sizeof entry, |
||||
entry.path_len) == 0) |
||||
return 0; |
||||
|
||||
if (mufs_write(tree, &entry, va, sizeof entry) == 0) |
||||
return 0; |
||||
|
||||
tree->file_size = max(tree->file_size, va + sizeof entry + entry.path_len); |
||||
|
||||
dtree.file_size = tree->file_size; |
||||
dtree.root = tree->root; |
||||
dtree.depth = tree->depth; |
||||
|
||||
printf("tree->va=%u\n", tree->va); |
||||
|
||||
if (flash_write(tree->fs->dev, tree->va, &dtree, sizeof dtree) == 0) |
||||
return 0; |
||||
|
||||
return entry.path_len + sizeof entry; |
||||
} |
||||
|
||||
int mufs_readdir(struct mufs_dir *dir, struct mufs_dirent *dirent) |
||||
{ |
||||
size_t ret; |
||||
|
||||
if (!dir || !dirent || dir->va >= dir->tree->file_size) |
||||
return -1; |
||||
|
||||
if ((ret = read_dirent(dir->fs, dir->tree, dirent, dir->va)) > 0) { |
||||
dir->va += ret; |
||||
return 0; |
||||
} |
||||
|
||||
dir->va = align_up(dir->va + 1, dir->fs->dev->log2_block_size); |
||||
|
||||
if ((ret = read_dirent(dir->fs, dir->tree, dirent, dir->va)) > 0) { |
||||
dir->va += ret; |
||||
return 0; |
||||
} |
||||
|
||||
printf("return?\n"); |
||||
return -1; |
||||
} |
||||
|
||||
int mufs_mkdir(struct mufs *fs, const char *path) |
||||
{ |
||||
struct mufs_dirent dirent; |
||||
struct mufs_tree tree; |
||||
size_t len; |
||||
char *s; |
||||
char *name; |
||||
|
||||
if (!path) |
||||
return -1; |
||||
|
||||
if (!(s = strdup(path))) |
||||
return -1; |
||||
|
||||
if (!(name = strrchr(s, '/'))) { |
||||
name = s; |
||||
s = NULL; |
||||
} else { |
||||
*name++ = '\0'; |
||||
} |
||||
|
||||
if (*name == '\0') |
||||
return -1; |
||||
|
||||
if (resolve(fs, &tree, s) < 0) |
||||
return -1; |
||||
|
||||
len = min(strlen(name), sizeof(dirent.path) - 1); |
||||
memcpy(dirent.path, name, len); |
||||
dirent.path[len] = '\0'; |
||||
dirent.type = MUFS_DIR; |
||||
|
||||
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; |
||||
} |
@ -0,0 +1,12 @@ |
||||
#pragma once |
||||
|
||||
struct mufs_dentry { |
||||
uint8_t type; |
||||
uint32_t file_size; |
||||
uint32_t root; |
||||
uint8_t depth; |
||||
uint16_t path_len; |
||||
} __attribute__((packed)); |
||||
|
||||
#define MUFS_FILE BIT(0) |
||||
#define MUFS_DIR BIT(1) |
Loading…
Reference in new issue