mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-26 22:18:54 +00:00
461 lines
12 KiB
C
461 lines
12 KiB
C
/**
|
|
* File: romfs.c
|
|
* Author: AWTK Develop Team
|
|
* Brief: romfs
|
|
*
|
|
* Copyright (c) 2018 - 2023 Guangzhou ZHIYUAN Electronics Co.,Ltd.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* License file for more details.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* History:
|
|
* ================================================================
|
|
* 2023-07-27 Li XianJing <xianjimli@hotmail.com> adapt from uclib
|
|
*
|
|
*/
|
|
|
|
#include "tkc/fs.h"
|
|
#include "tkc/mem.h"
|
|
#include "tkc/utils.h"
|
|
#include "conf_io/conf_node.h"
|
|
#include "conf_io/conf_ubjson.h"
|
|
|
|
typedef struct _romfs_fs_t {
|
|
fs_t fs;
|
|
uint32_t header_size;
|
|
uint32_t body_size;
|
|
const uint8_t* header_data;
|
|
const uint8_t* body_data;
|
|
conf_doc_t* doc;
|
|
} romfs_fs_t;
|
|
|
|
typedef struct _romfs_file_t {
|
|
int32_t size;
|
|
int32_t offset;
|
|
const uint8_t* data;
|
|
} romfs_file_t;
|
|
|
|
static int32_t romfs_file_read(fs_file_t* file, void* buffer, uint32_t size) {
|
|
romfs_file_t* fp = (romfs_file_t*)(file->data);
|
|
int32_t rsize = (fp->offset + size) <= fp->size ? size : (fp->size - fp->offset);
|
|
|
|
memcpy(buffer, fp->data + fp->offset, rsize);
|
|
fp->offset += rsize;
|
|
|
|
return rsize;
|
|
}
|
|
|
|
static int32_t romfs_file_write(fs_file_t* file, const void* buffer, uint32_t size) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static int32_t romfs_file_printf(fs_file_t* file, const char* const format_str, va_list vl) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_file_seek(fs_file_t* file, int32_t offset) {
|
|
romfs_file_t* fp = (romfs_file_t*)(file->data);
|
|
|
|
fp->offset = offset;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
static int64_t romfs_file_tell(fs_file_t* file) {
|
|
romfs_file_t* fp = (romfs_file_t*)(file->data);
|
|
|
|
return fp->offset;
|
|
}
|
|
|
|
static int64_t romfs_file_size(fs_file_t* file) {
|
|
romfs_file_t* fp = (romfs_file_t*)(file->data);
|
|
|
|
return fp->size;
|
|
}
|
|
|
|
static ret_t romfs_file_stat(fs_file_t* file, fs_stat_info_t* fst) {
|
|
romfs_file_t* fp = (romfs_file_t*)(file->data);
|
|
|
|
memset(fst, 0x00, sizeof(*fst));
|
|
fst->size = fp->size;
|
|
fst->is_reg_file = TRUE;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
static ret_t romfs_file_sync(fs_file_t* file) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_file_truncate(fs_file_t* file, int32_t size) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static bool_t romfs_file_eof(fs_file_t* file) {
|
|
romfs_file_t* fp = (romfs_file_t*)(file->data);
|
|
|
|
return fp->offset >= fp->size;
|
|
}
|
|
|
|
static ret_t romfs_file_close(fs_file_t* file) {
|
|
TKMEM_FREE(file);
|
|
return RET_OK;
|
|
}
|
|
|
|
typedef struct _romfs_dir_t {
|
|
conf_node_t* first;
|
|
conf_node_t* iter;
|
|
} romfs_dir_t;
|
|
|
|
static ret_t romfs_dir_rewind(fs_dir_t* dir) {
|
|
romfs_dir_t* d = (romfs_dir_t*)(dir->data);
|
|
|
|
d->iter = d->first;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
static ret_t romfs_dir_read(fs_dir_t* dir, fs_item_t* item) {
|
|
romfs_dir_t* d = (romfs_dir_t*)(dir->data);
|
|
|
|
memset(item, 0x00, sizeof(fs_item_t));
|
|
if (d->iter != NULL) {
|
|
value_t v;
|
|
if (conf_node_get_child_value(d->iter, "name", &v) == RET_OK) {
|
|
tk_strncpy(item->name, value_str(&v), MAX_PATH);
|
|
}
|
|
|
|
if (conf_node_get_child_value(d->iter, "type", &v) == RET_OK) {
|
|
item->is_dir = tk_str_eq(value_str(&v), "dir");
|
|
item->is_reg_file = tk_str_eq(value_str(&v), "file");
|
|
}
|
|
|
|
d->iter = d->iter->next;
|
|
return RET_OK;
|
|
} else {
|
|
return RET_FAIL;
|
|
}
|
|
}
|
|
|
|
static ret_t romfs_dir_close(fs_dir_t* dir) {
|
|
romfs_dir_t* d = (romfs_dir_t*)dir->data;
|
|
|
|
TKMEM_FREE(d);
|
|
TKMEM_FREE(dir);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
static const fs_file_vtable_t s_file_vtable = {.read = romfs_file_read,
|
|
.write = romfs_file_write,
|
|
.printf = romfs_file_printf,
|
|
.seek = romfs_file_seek,
|
|
.tell = romfs_file_tell,
|
|
.size = romfs_file_size,
|
|
.stat = romfs_file_stat,
|
|
.sync = romfs_file_sync,
|
|
.truncate = romfs_file_truncate,
|
|
.eof = romfs_file_eof,
|
|
.close = romfs_file_close};
|
|
|
|
static ret_t romfs_file_destory(romfs_file_t* fp) {
|
|
TKMEM_FREE(fp);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
static fs_file_t* fs_file_create(romfs_file_t* fp) {
|
|
fs_file_t* f = NULL;
|
|
return_value_if_fail(fp != NULL, NULL);
|
|
|
|
f = TKMEM_ZALLOC(fs_file_t);
|
|
if (f != NULL) {
|
|
f->vt = &s_file_vtable;
|
|
f->data = fp;
|
|
} else {
|
|
romfs_file_destory(fp);
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
static conf_node_t* romfs_find_node(conf_node_t* node, const char* name) {
|
|
value_t v;
|
|
char curr_name[MAX_PATH + 1] = {0};
|
|
const char* p = strchr(name, '/');
|
|
conf_node_t* iter = conf_node_get_first_child(node);
|
|
|
|
if (p == NULL) {
|
|
p = strchr(name, '\\');
|
|
}
|
|
|
|
if (p != NULL) {
|
|
tk_strncpy(curr_name, name, p - name);
|
|
name = p + 1;
|
|
} else {
|
|
tk_strncpy(curr_name, name, sizeof(curr_name) - 1);
|
|
name = NULL;
|
|
}
|
|
|
|
while (iter != NULL) {
|
|
if (conf_node_get_child_value(iter, "name", &v) == RET_OK) {
|
|
if (tk_str_eq(value_str(&v), curr_name)) {
|
|
if (name == NULL) {
|
|
return iter;
|
|
} else {
|
|
conf_node_t* children = conf_node_find_child(iter, "children");
|
|
if (children != NULL) {
|
|
return romfs_find_node(children, name);
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
iter = iter->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static romfs_file_t* romfs_file_create(fs_t* fs, const char* name) {
|
|
conf_node_t* node = NULL;
|
|
romfs_fs_t* rfs = (romfs_fs_t*)fs;
|
|
romfs_file_t* file = NULL;
|
|
node = romfs_find_node(rfs->doc->root, name);
|
|
|
|
if (node != NULL) {
|
|
value_t v;
|
|
file = TKMEM_ZALLOC(romfs_file_t);
|
|
return_value_if_fail(file != NULL, NULL);
|
|
|
|
file->offset = 0;
|
|
if (conf_node_get_child_value(node, "size", &v) == RET_OK) {
|
|
file->size = value_int(&v);
|
|
}
|
|
|
|
if (conf_node_get_child_value(node, "data", &v) == RET_OK) {
|
|
file->data = rfs->body_data + value_uint32(&v);
|
|
assert(value_uint32(&v) < rfs->body_size);
|
|
}
|
|
}
|
|
|
|
return file;
|
|
}
|
|
|
|
static fs_file_t* romfs_open_file(fs_t* fs, const char* name, const char* mode) {
|
|
return_value_if_fail(name != NULL && mode != NULL, NULL);
|
|
|
|
return fs_file_create(romfs_file_create(fs, name));
|
|
}
|
|
|
|
static ret_t romfs_remove_file(fs_t* fs, const char* name) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static bool_t romfs_file_exist(fs_t* fs, const char* name) {
|
|
fs_stat_info_t st;
|
|
return_value_if_fail(name != NULL, FALSE);
|
|
|
|
if (fs_stat(fs, name, &st) == RET_OK) {
|
|
return st.is_reg_file;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static ret_t romfs_file_rename(fs_t* fs, const char* name, const char* new_name) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static const fs_dir_vtable_t s_dir_vtable = {
|
|
.read = romfs_dir_read, .rewind = romfs_dir_rewind, .close = romfs_dir_close};
|
|
|
|
static romfs_dir_t* romfs_dir_create(fs_t* fs, const char* name) {
|
|
romfs_dir_t* dir = NULL;
|
|
romfs_fs_t* rfs = (romfs_fs_t*)fs;
|
|
conf_node_t* node = romfs_find_node(rfs->doc->root, name);
|
|
return_value_if_fail(node != NULL, NULL);
|
|
node = conf_node_find_child(node, "children");
|
|
return_value_if_fail(node != NULL, NULL);
|
|
node = conf_node_get_first_child(node);
|
|
|
|
dir = TKMEM_ZALLOC(romfs_dir_t);
|
|
return_value_if_fail(dir != NULL, NULL);
|
|
dir->first = node;
|
|
dir->iter = node;
|
|
|
|
return dir;
|
|
}
|
|
|
|
static fs_dir_t* romfs_open_dir(fs_t* fs, const char* name) {
|
|
fs_dir_t* dir = NULL;
|
|
romfs_dir_t* rdir = romfs_dir_create(fs, name);
|
|
|
|
return_value_if_fail(rdir != NULL, NULL);
|
|
dir = TKMEM_ZALLOC(fs_dir_t);
|
|
|
|
if (dir != NULL) {
|
|
dir->vt = &s_dir_vtable;
|
|
dir->data = rdir;
|
|
} else {
|
|
TKMEM_FREE(rdir);
|
|
}
|
|
|
|
return dir;
|
|
}
|
|
|
|
static ret_t romfs_remove_dir(fs_t* fs, const char* name) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_change_dir(fs_t* fs, const char* name) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_create_dir(fs_t* fs, const char* name) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static bool_t romfs_dir_exist(fs_t* fs, const char* name) {
|
|
fs_stat_info_t st;
|
|
return_value_if_fail(name != NULL, FALSE);
|
|
|
|
if (fs_stat(fs, name, &st) == RET_OK) {
|
|
return st.is_dir;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static ret_t romfs_dir_rename(fs_t* fs, const char* name, const char* new_name) {
|
|
return romfs_file_rename(fs, name, new_name);
|
|
}
|
|
|
|
static int32_t romfs_get_file_size(fs_t* fs, const char* name) {
|
|
fs_stat_info_t st;
|
|
return_value_if_fail(name != NULL, FALSE);
|
|
|
|
if (fs_stat(fs, name, &st) == RET_OK && st.is_reg_file) {
|
|
return st.size;
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static ret_t romfs_get_disk_info(fs_t* fs, const char* volume, int32_t* free_kb,
|
|
int32_t* total_kb) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_get_exe(fs_t* fs, char path[MAX_PATH + 1]) {
|
|
strcpy(path, "/bin/app");
|
|
return RET_OK;
|
|
}
|
|
|
|
static ret_t romfs_get_temp_path(fs_t* fs, char path[MAX_PATH + 1]) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_get_user_storage_path(fs_t* fs, char path[MAX_PATH + 1]) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_get_cwd(fs_t* fs, char path[MAX_PATH + 1]) {
|
|
return RET_NOT_IMPL;
|
|
}
|
|
|
|
static ret_t romfs_stat(fs_t* fs, const char* name, fs_stat_info_t* fst) {
|
|
conf_node_t* node = NULL;
|
|
romfs_fs_t* rfs = (romfs_fs_t*)fs;
|
|
return_value_if_fail(rfs->doc != NULL && rfs->doc->root != NULL, RET_BAD_PARAMS);
|
|
|
|
node = romfs_find_node(rfs->doc->root, name);
|
|
if (node != NULL) {
|
|
value_t v;
|
|
memset(fst, 0x00, sizeof(fs_stat_info_t));
|
|
|
|
if (conf_node_get_child_value(node, "size", &v) == RET_OK) {
|
|
fst->size = value_int(&v);
|
|
}
|
|
|
|
if (conf_node_get_child_value(node, "type", &v) == RET_OK) {
|
|
fst->is_dir = tk_str_eq(value_str(&v), "dir");
|
|
fst->is_reg_file = tk_str_eq(value_str(&v), "file");
|
|
}
|
|
return RET_OK;
|
|
} else {
|
|
return RET_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
static romfs_fs_t s_romfs_fs = {.fs =
|
|
{
|
|
.open_file = romfs_open_file,
|
|
.remove_file = romfs_remove_file,
|
|
.file_exist = romfs_file_exist,
|
|
.file_rename = romfs_file_rename,
|
|
|
|
.open_dir = romfs_open_dir,
|
|
.remove_dir = romfs_remove_dir,
|
|
.create_dir = romfs_create_dir,
|
|
.change_dir = romfs_change_dir,
|
|
.dir_exist = romfs_dir_exist,
|
|
.dir_rename = romfs_dir_rename,
|
|
|
|
.get_file_size = romfs_get_file_size,
|
|
.get_disk_info = romfs_get_disk_info,
|
|
.get_cwd = romfs_get_cwd,
|
|
.get_exe = romfs_get_exe,
|
|
.get_user_storage_path = romfs_get_user_storage_path,
|
|
.get_temp_path = romfs_get_temp_path,
|
|
.stat = romfs_stat,
|
|
},
|
|
.header_size = 0,
|
|
.body_size = 0,
|
|
.header_data = NULL,
|
|
.body_data = NULL,
|
|
.doc = NULL};
|
|
|
|
ret_t romfs_init(const uint8_t* header_data, uint32_t header_size, const uint8_t* body_data,
|
|
uint32_t body_size) {
|
|
return_value_if_fail(header_data != NULL && body_data != NULL, RET_BAD_PARAMS);
|
|
return_value_if_fail(s_romfs_fs.doc == NULL, RET_BAD_PARAMS);
|
|
|
|
s_romfs_fs.body_data = body_data;
|
|
s_romfs_fs.header_data = header_data;
|
|
s_romfs_fs.body_size = body_size;
|
|
s_romfs_fs.header_size = header_size;
|
|
|
|
s_romfs_fs.doc = conf_doc_load_ubjson(header_data, header_size);
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
ret_t romfs_deinit(void) {
|
|
return_value_if_fail(s_romfs_fs.doc != NULL, RET_BAD_PARAMS);
|
|
|
|
conf_doc_destroy(s_romfs_fs.doc);
|
|
s_romfs_fs.doc = NULL;
|
|
|
|
return RET_OK;
|
|
}
|
|
|
|
fs_t* romfs_get(void) {
|
|
return (fs_t*)&s_romfs_fs;
|
|
}
|
|
|
|
#if defined(WITH_ROMFS_AS_OS_FS) || defined(AWTK_WEB)
|
|
fs_t* os_fs(void) {
|
|
return_value_if_fail(s_romfs_fs.doc != NULL, NULL);
|
|
|
|
return (fs_t*)&s_romfs_fs;
|
|
}
|
|
#endif /*WITH_ROMFS_AS_OS_FS*/
|