Vhex-kernel/src/kernel/fs/smem/open.c

131 lines
3.1 KiB
C

#include <kernel/fs/smem.h>
#include <kernel/fs/file.h>
#include <kernel/util.h>
//FIXME: find better way to walk into fragment (use ID)
static size_t casio_smem_get_file_size(casio_smem_header_t *file)
{
casio_smem_fragment_t *fragment;
size_t count;
count = 0;
fragment = (void *)((uint32_t)file + sizeof(casio_smem_header_t));
while (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC)
{
count = count + fragment->data_size + 1;
fragment = fragment + 1;
}
return (count);
}
/* casio_smem_get_file() - Walk into the Casio's File System and search the target file */
static casio_smem_header_t *casio_smem_get_file(char const *name, uint16_t *parent_id)
{
extern casio_smem_header_t *casio_smem_header_table;
casio_smem_fragment_t *fragment;
casio_smem_header_t *header;
int i;
// Walk into Casio SMEM File System.
header = casio_smem_header_table;
while (header->info == CASIO_SMEM_HEADER_INFO_EXIST ||
header->info == CASIO_SMEM_HEADER_INFO_DELETE)
{
// Check new file validity.
if (header->info == CASIO_SMEM_HEADER_INFO_EXIST &&
header->parent.id == *parent_id)
{
// Compare File name.
i = -1;
while (++i < 12 &&
header->name[i] != 0x0000 &&
header->name[i] != 0xffff &&
(header->name[i] & 0x00ff) == name[i]);
// Check error.
if (name[i] == '\0' &&
(header->name[i] == 0x0000 ||
header->name[i] == 0xffff))
{
*parent_id = header->id;
return (header);
}
}
// We need to skip fragmented data
fragment = (void *)((uint32_t)header + sizeof(casio_smem_header_t));
if (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC)
{
// The fastest way to skip fragmented data
fragment = (void *)((uint32_t)fragment +
(sizeof(casio_smem_fragment_t) * fragment->frag_total));
}
// Get next header.
header = (void *)fragment;
}
return (NULL);
}
/* casio_smem_open() - Find target file and setup abstraction file structure */
int casio_smem_open(FILE *file, char const *name, int mode)
{
extern uint16_t current_parent_id;
casio_smem_header_t *file_raw;
uint16_t parent_id;
char file_name[14];
int slot_number;
int i;
// check error.
if (mode != O_RDONLY || name == NULL)
return (-1);
// Get parent ID.
if (*name == '/')
{
parent_id = CASIO_SMEM_ROOT_ID;
name += 1;
} else {
parent_id = current_parent_id;
}
// File Systeme walk entry.
while (*name != '\0')
{
// Get current file name.
i = -1;
while (name[++i] != '\0' && name[i] != '/' && i < 14)
file_name[i] = name[i];
// Check file name validity.
if (i >= 12 && name[i] != '\0' && name[i] != '/')
return (-1);
// Update internal informations.
file_name[i] = '\0';
name = name + i;
// find the file.
file_raw = casio_smem_get_file(file_name, &parent_id);
if (file_raw == NULL)
return (-1);
// Directory check
if (name[0] == '/')
{
if (file_raw->type != CASIO_SMEM_HEADER_TYPE_DIRECTORY)
return (-2);
name = name + 1;
}
}
// Initilaize fiel object
// TODO: Use VFS to do this !!
file->cursor = 0;
file->mode = mode;
file->abstract = file_raw;
file->size = casio_smem_get_file_size(file_raw);
return (0);
}