221 lines
4.5 KiB
C
221 lines
4.5 KiB
C
|
#include <stdbool.h>
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <drivers/ide.h>
|
||
|
|
||
|
#include <fs/duckfs.h>
|
||
|
|
||
|
|
||
|
static uint16_t duckfs_initialized = 0;
|
||
|
|
||
|
static duckfs_file_header_t duckfs_root;
|
||
|
|
||
|
const char* duckfs_versions[18] = { DFS_VERSION_0, DFS_VERSION_1, DFS_VERSION_2, DFS_VERSION_3, DFS_VERSION_4 };
|
||
|
|
||
|
int32_t duckfs_init(int16_t drive)
|
||
|
{
|
||
|
char duckfs_header_block[512];
|
||
|
if (ide_read48(drive, 0xA, 1, duckfs_header_block) != 0)
|
||
|
{
|
||
|
printf("[ DEBUG ] Disk read error on drive #%i\n", drive);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
duckfs_superblock_t* superblock = (duckfs_superblock_t*)duckfs_header_block;
|
||
|
/*
|
||
|
if (superblock->duckfs_magic != (int32_t) DFS_MAGIC)
|
||
|
{
|
||
|
return -2;
|
||
|
}
|
||
|
|
||
|
bool compliant = false;
|
||
|
for (int16_t i = 0; i < 5; ++i)
|
||
|
{
|
||
|
if (strcmp(superblock->duckfs_version_string, duckfs_versions[i]) == 0)
|
||
|
{
|
||
|
compliant = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (compliant == false)
|
||
|
{
|
||
|
return -3;
|
||
|
}*/
|
||
|
|
||
|
memset(&duckfs_root, 0, sizeof(duckfs_root));
|
||
|
|
||
|
strncpy(duckfs_root.filename, "/", DFS_MAX_FILENAME_LEN);
|
||
|
strncpy(duckfs_root.permissions, "RW", sizeof(duckfs_root.permissions));
|
||
|
|
||
|
duckfs_root.num_sectors = -1;
|
||
|
duckfs_root.type = DFS_FILE_DIRECTORY;
|
||
|
duckfs_root.next = NULL;
|
||
|
duckfs_root.prev = NULL;
|
||
|
duckfs_root.contents = NULL;
|
||
|
duckfs_root.lba_start = 0;
|
||
|
duckfs_root.lba_end = 0;
|
||
|
|
||
|
duckfs_root.contents = malloc(sizeof(duckfs_file_header_t) * DFS_MAX_FILES);
|
||
|
if (!duckfs_root.contents) {
|
||
|
printf("Memory allocation failed for duckfs_root.contents\n");
|
||
|
return -4;
|
||
|
}
|
||
|
|
||
|
for (int32_t i = 0; i < DFS_MAX_FILES; i++) {
|
||
|
duckfs_root.contents[i].type = DFS_FILE_UNUSED;
|
||
|
}
|
||
|
|
||
|
|
||
|
duckfs_initialized = 1;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void duckfs_format(int16_t drive)
|
||
|
{
|
||
|
/* Nothing to do, DuckFS does not require formatting. */
|
||
|
}
|
||
|
|
||
|
int32_t duckfs_makedir(const char* filename, const char* perms)
|
||
|
{
|
||
|
duckfs_file_header_t* dir = malloc(sizeof(duckfs_file_header_t));
|
||
|
if (!dir)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (strlen(perms) < 3)
|
||
|
{
|
||
|
return -2;
|
||
|
}
|
||
|
|
||
|
char p[3] = { "." };
|
||
|
p[0] = perms[0];
|
||
|
p[1] = perms[1];
|
||
|
p[2] = perms[2];
|
||
|
|
||
|
char filen[DFS_MAX_FILENAME_LEN + 1];
|
||
|
char perma[3];
|
||
|
|
||
|
strcpy(filen, filename);
|
||
|
|
||
|
|
||
|
strcpy(perma, perms);
|
||
|
|
||
|
strncpy(dir->filename, filen, sizeof(dir->filename) - 1);
|
||
|
dir->filename[sizeof(dir->filename) - 1] = '\0';
|
||
|
|
||
|
strncpy(dir->permissions, p, sizeof(dir->permissions));
|
||
|
|
||
|
dir->type = DFS_FILE_DIRECTORY;
|
||
|
dir->contents = malloc(sizeof(duckfs_file_header_t) * DFS_MAX_FILES);
|
||
|
|
||
|
if (!dir->contents) {
|
||
|
free(dir);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < DFS_MAX_FILES; i++) {
|
||
|
dir->contents[i].type = DFS_FILE_UNUSED;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void duckfs_free_directory(duckfs_file_header_t* dir)
|
||
|
{
|
||
|
if (!dir || dir->type != DFS_FILE_DIRECTORY || !dir->contents)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < DFS_MAX_FILES; i++) {
|
||
|
duckfs_file_header_t* entry = &dir->contents[i];
|
||
|
|
||
|
if (entry->type == DFS_FILE_UNUSED)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (entry->type == DFS_FILE_DIRECTORY) {
|
||
|
duckfs_free_directory(entry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
free(dir->contents);
|
||
|
dir->contents = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool duckfs_add_entry(duckfs_file_header_t* dir, duckfs_file_header_t* entry)
|
||
|
{
|
||
|
if (dir->type != DFS_FILE_DIRECTORY || !dir->contents)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < DFS_MAX_FILES; i++) {
|
||
|
if (dir->contents[i].type == DFS_FILE_UNUSED) {
|
||
|
dir->contents[i] = *entry;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false; /* Directory full */
|
||
|
}
|
||
|
|
||
|
duckfs_file_header_t duckfs_create_entry(const char* name, const char* perms, const char* type)
|
||
|
{
|
||
|
duckfs_file_header_t entry = {0};
|
||
|
|
||
|
strncpy(entry.filename, name, DFS_MAX_FILENAME_LEN);
|
||
|
strncpy(entry.permissions, perms, sizeof(entry.permissions) - 1);
|
||
|
|
||
|
int16_t itype = DFS_FILE_UNUSED;
|
||
|
|
||
|
if (strcmp(type, "text") == 0)
|
||
|
{
|
||
|
itype = DFS_FILE_TEXT;
|
||
|
}
|
||
|
else if (strcmp(type, "bin") == 0)
|
||
|
{
|
||
|
itype = DFS_FILE_BINARY;
|
||
|
}
|
||
|
else if (strcmp(type, "dir") == 0)
|
||
|
{
|
||
|
itype = DFS_FILE_BINARY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
duckfs_file_header_t vvvv = { .type = DFS_FILE_ERROR };
|
||
|
return vvvv;
|
||
|
}
|
||
|
|
||
|
entry.num_sectors = 0;
|
||
|
entry.type = itype;
|
||
|
entry.next = NULL;
|
||
|
entry.prev = NULL;
|
||
|
entry.contents = NULL;
|
||
|
entry.lba_start = 0;
|
||
|
entry.lba_end = 0;
|
||
|
|
||
|
if (itype == DFS_FILE_DIRECTORY)
|
||
|
{
|
||
|
entry.contents = malloc(sizeof(duckfs_file_header_t) * DFS_MAX_FILES);
|
||
|
if (entry.contents)
|
||
|
{
|
||
|
for (int i = 0; i < DFS_MAX_FILES; i++)
|
||
|
{
|
||
|
entry.contents[i].type = DFS_FILE_UNUSED;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return entry;
|
||
|
}
|
||
|
|
||
|
duckfs_file_header_t duckfs_makefile(const char* filename, const char* perms, duckfs_file_header_t parent)
|
||
|
{
|
||
|
|
||
|
}
|