Espresso 0.0.1a
This commit is contained in:
@ -1,5 +1,3 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <drivers/ide.h>
|
||||
@ -7,214 +5,89 @@
|
||||
#include <fs/duckfs.h>
|
||||
|
||||
|
||||
#define DFS_MAGIC 0xDF1984CC
|
||||
|
||||
#define DFS_BLOCK_SIZE 512
|
||||
|
||||
#define DFS_VERSION_0 "DuckFS, wheresDax?"
|
||||
#define DFS_VERSION_1 "DuckFS, Terminator"
|
||||
#define DFS_VERSION_2 "DuckFS-Terminator2"
|
||||
#define DFS_VERSION_3 "DuckFS,StarWarsEIV"
|
||||
#define DFS_VERSION_4 "DuckFS QUACK,QUACK"
|
||||
|
||||
|
||||
#define DFS_FILE_ERROR -8
|
||||
#define DFS_FILE_UNUSED -1
|
||||
#define DFS_FILE_USED 0
|
||||
#define DFS_FILE_TEXT 0
|
||||
#define DFS_FILE_BINARY 1
|
||||
#define DFS_FILE_DIRECTORY 2
|
||||
|
||||
/* encryption algorithms */
|
||||
#define DFS_CAESAR_5 88
|
||||
#define DFS_CAESAR_8 84
|
||||
#define DFS_CAESAR_2 09
|
||||
#define DFS_QUACK_32 99
|
||||
|
||||
#define DFS_MAX_FILENAME_LEN 64
|
||||
#define DFS_MAX_FILES 256
|
||||
|
||||
|
||||
typedef struct duckfs_file_header {
|
||||
char filename[DFS_MAX_FILENAME_LEN + 1]; /* + 1 for the \0 */
|
||||
char permissions[3]; /* Same thing here */
|
||||
|
||||
/*
|
||||
512 Bytes per sector, meaning a 2 sector file is 1024 bytes, or 1 KiB.
|
||||
Only valid if this file is not a directory.
|
||||
*/
|
||||
int32_t num_sectors;
|
||||
|
||||
int16_t type; /* Indicates the file type. -1 for null file, 0 for a text file, 1 for a binary file, and 2 for a directory. */
|
||||
|
||||
uint16_t _reserved0; /* (align to 4) */
|
||||
|
||||
struct duckfs_file_header* next; /* Next file in the directory this file is in. */
|
||||
struct duckfs_file_header* contents; /* contains the first file in the directory. only valid if this file is a directory. */
|
||||
struct duckfs_file_header* parent; /* The directory this file is in. */
|
||||
|
||||
uint64_t next_lba; /* The LBA of the next file's file header on the disk. */
|
||||
uint64_t contents_lba;
|
||||
uint64_t parent_lba;
|
||||
|
||||
uint64_t lba_start; /* only is valid if this file is not a directory. */
|
||||
uint64_t lba_end; /* only is valid if this file is not a directory. */
|
||||
|
||||
uint8_t _reserved1[126]; /* padding to 256 bytes total */
|
||||
} duckfs_file_header_t;
|
||||
|
||||
typedef struct duckfs_superblock {
|
||||
int32_t duckfs_magic; /* must be DFS_MAGIC. */
|
||||
char duckfs_version_string[19];
|
||||
char volume_label[19]; /* 18 characters and a null zero. */
|
||||
|
||||
int16_t encryption;
|
||||
|
||||
uint64_t duckfs_root; /* LBA of the root directory's file header */
|
||||
|
||||
uint32_t _padding[115]; /* padding to 512 bytes total */
|
||||
} duckfs_superblock_t;
|
||||
|
||||
|
||||
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)
|
||||
void duckfs_init(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
printf("\t%i\n", (sizeof(duckfs_file_header_t)));
|
||||
printf("\t\t%i\n", (sizeof(duckfs_superblock_t)));
|
||||
/* int32_t ide_read48(uint8_t drive, uint64_t lba, uint8_t sector_count, void* buffer) */
|
||||
/* int32_t ide_write48(uint8_t drive, uint64_t lba, uint8_t sector_count, const void* buffer) */
|
||||
|
||||
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)
|
||||
{
|
||||
/*uint8_t superblock_sector[512] = { 0 };
|
||||
|
||||
ide_read*/
|
||||
}
|
||||
|
348
drivers/fs/ramfs.c
Normal file
348
drivers/fs/ramfs.c
Normal file
@ -0,0 +1,348 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fs/ramfs.h>
|
||||
|
||||
|
||||
|
||||
static ramfs_file_header_t* ramfs_root = NULL;
|
||||
static int32_t ramfs_num_files = 0;
|
||||
static int32_t next_fd = 2;
|
||||
|
||||
bool ramfs_initialized = false;
|
||||
|
||||
void ramfs_init(void)
|
||||
{
|
||||
if (!ramfs_initialized)
|
||||
{
|
||||
/*printf("%i\n", (int32_t)sizeof(ramfs_file_header_t));*/
|
||||
|
||||
ramfs_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
ramfs_file_header_t* ramfs_make_root(void)
|
||||
{
|
||||
ramfs_root = (ramfs_file_header_t*)malloc(sizeof(ramfs_file_header_t));
|
||||
|
||||
if (!ramfs_root)
|
||||
{
|
||||
printf("RAMFS: Error: malloc failed on attempt to malloc ramfs_root\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(ramfs_root->filename, "/");
|
||||
ramfs_root->type = RAMFS_FILE_DIR;
|
||||
ramfs_root->encryption = RAMFS_ENCR_NONE;
|
||||
ramfs_root->content = NULL;
|
||||
ramfs_root->parent = NULL;
|
||||
ramfs_root->next = NULL;
|
||||
ramfs_root->link_target = NULL;
|
||||
ramfs_root->fd = 0;
|
||||
|
||||
return ramfs_root;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* ramfs_get_root(void)
|
||||
{
|
||||
if (!ramfs_root)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ramfs_root;
|
||||
}
|
||||
|
||||
int32_t ramfs_get_files(void)
|
||||
{
|
||||
return ramfs_num_files;
|
||||
}
|
||||
|
||||
bool ramfs_get_initialized(void)
|
||||
{
|
||||
return ramfs_initialized;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* ramfs_create_file(char* name, char type, char encryption, ramfs_file_header_t* parent)
|
||||
{
|
||||
if (!parent)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((strlen(name) + 1) > RAMFS_FILENAME_LEN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* _file = (ramfs_file_header_t*)malloc(sizeof(ramfs_file_header_t));
|
||||
|
||||
if (!_file)
|
||||
{
|
||||
printf("RAMFS: Error: malloc failed on attempt to malloc _file (in ramfs_create_file)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(_file->filename, name);
|
||||
|
||||
_file->type = type;
|
||||
_file->encryption = encryption;
|
||||
_file->content = NULL;
|
||||
_file->parent = parent;
|
||||
_file->next = NULL;
|
||||
_file->link_target = NULL;
|
||||
_file->fd = (next_fd - 1);
|
||||
_file->data_begin = (void*)0x0;
|
||||
_file->data_end = (void*)0x0;
|
||||
|
||||
if (parent->content != NULL)
|
||||
{
|
||||
ramfs_file_header_t* current = parent->content;
|
||||
|
||||
/* Traverse to the end of the linked list */
|
||||
while (current->next != NULL)
|
||||
{
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
/* Append the new file at the end */
|
||||
current->next = _file;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If no content yet, this is the first child */
|
||||
parent->content = _file;
|
||||
}
|
||||
|
||||
ramfs_num_files++;
|
||||
next_fd++;
|
||||
|
||||
return _file;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* ramfs_write_file(ramfs_file_header_t* file, void* data, size_t len)
|
||||
{
|
||||
if (!file || !data || !len || file->type == RAMFS_FILE_DIR)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free existing data */
|
||||
if (file->data_begin)
|
||||
{
|
||||
free(file->data_begin);
|
||||
file->data_begin = NULL;
|
||||
file->data_end = NULL;
|
||||
}
|
||||
|
||||
void* new_buf = malloc(len);
|
||||
if (!new_buf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(new_buf, data, len);
|
||||
file->data_begin = new_buf;
|
||||
file->data_end = (uint8_t*)new_buf + len;
|
||||
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
int32_t ramfs_read_file(ramfs_file_header_t* file, void* buffer, size_t buffer_len)
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (file->type == RAMFS_FILE_DIR)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (!file->data_begin || !file->data_end)
|
||||
{
|
||||
return -4; /* No data to read */
|
||||
}
|
||||
|
||||
size_t data_len = (size_t)((char*)file->data_end - (char*)file->data_begin);
|
||||
|
||||
if (buffer_len < data_len)
|
||||
{
|
||||
return -5; /* Buffer too small */
|
||||
}
|
||||
|
||||
memcpy(buffer, file->data_begin, data_len);
|
||||
|
||||
return (int32_t)data_len; /* return number of bytes copied */
|
||||
}
|
||||
|
||||
int32_t ramfs_delete_file(ramfs_file_header_t* file)
|
||||
{
|
||||
if (!file)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!file->parent)
|
||||
{
|
||||
return -2; /* Don't delete the root or orphaned files */
|
||||
}
|
||||
|
||||
ramfs_file_header_t* parent = file->parent;
|
||||
ramfs_file_header_t* current = parent->content;
|
||||
ramfs_file_header_t* prev = NULL;
|
||||
|
||||
/* Find the file in the linked list */
|
||||
while (current && current != file)
|
||||
{
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (!current)
|
||||
{
|
||||
return -3; /* File not found in parent's content list */
|
||||
}
|
||||
|
||||
/* Unlink the file from the list */
|
||||
if (prev)
|
||||
{
|
||||
prev->next = current->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->content = current->next;
|
||||
}
|
||||
|
||||
/* Recursively delete content if it's a directory */
|
||||
if (file->type == RAMFS_FILE_DIR && file->content)
|
||||
{
|
||||
ramfs_file_header_t* child = file->content;
|
||||
while (child)
|
||||
{
|
||||
ramfs_file_header_t* next_child = child->next;
|
||||
ramfs_delete_file(child);
|
||||
child = next_child;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free file data if applicable */
|
||||
if ((file->type == RAMFS_FILE_TEXT || file->type == RAMFS_FILE_BINARY) && file->data_begin)
|
||||
{
|
||||
free(file->data_begin);
|
||||
}
|
||||
|
||||
/* Free the file header itself */
|
||||
free(file);
|
||||
|
||||
next_fd--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* ramfs_resolve_path(const char* path)
|
||||
{
|
||||
if (!path || !ramfs_get_root())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* current;
|
||||
|
||||
/* Start from root if absolute path */
|
||||
if (path[0] == '/')
|
||||
{
|
||||
current = ramfs_get_root();
|
||||
path++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: make a ramfs_get_cwd and use it instead */
|
||||
current = ramfs_get_root();
|
||||
}
|
||||
|
||||
char* path_copy = strdup(path);
|
||||
if (!path_copy)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* token = strtok(path_copy, "/");
|
||||
|
||||
while (token && current)
|
||||
{
|
||||
if (strcmp(token, ".") == 0)
|
||||
{
|
||||
/* Stay in the same directory */
|
||||
}
|
||||
else if (strcmp(token, "..") == 0)
|
||||
{
|
||||
if (current->parent)
|
||||
{
|
||||
current = current->parent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Traverse to matching child */
|
||||
ramfs_file_header_t* child = current->content;
|
||||
current = NULL;
|
||||
|
||||
while (child)
|
||||
{
|
||||
if (strcmp(child->filename, token) == 0)
|
||||
{
|
||||
current = child;
|
||||
break;
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
if (!current)
|
||||
{
|
||||
/* Not found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
token = strtok(NULL, "/");
|
||||
}
|
||||
|
||||
free(path_copy);
|
||||
return current; /* NULL if not found or invalid path */
|
||||
}
|
||||
|
||||
ramfs_file_header_t* ramfs_resolve_fd_dir(ramfs_file_header_t* current, int32_t fd)
|
||||
{
|
||||
if (!current)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (current->fd == fd)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* found = ramfs_resolve_fd_dir(current->content, fd);
|
||||
if (found)
|
||||
{
|
||||
return found;
|
||||
}
|
||||
|
||||
return ramfs_resolve_fd_dir(current->next, fd);
|
||||
}
|
||||
|
||||
ramfs_file_header_t* ramfs_resolve_fd(int32_t fd)
|
||||
{
|
||||
return ramfs_resolve_fd_dir(ramfs_root, fd);
|
||||
}
|
230
drivers/fs/vfs.c
Normal file
230
drivers/fs/vfs.c
Normal file
@ -0,0 +1,230 @@
|
||||
#include <fs/ramfs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fs/vfs.h>
|
||||
|
||||
|
||||
/*
|
||||
Note: the special FILE value -128 means the current directory.
|
||||
-32 means stdin
|
||||
-33 means stdout (which can be read)
|
||||
*/
|
||||
|
||||
bool vfs_initialized = false;
|
||||
ramfs_file_header_t* vfs_current_dir = NULL;
|
||||
|
||||
void vfs_init(void)
|
||||
{
|
||||
if (!vfs_initialized)
|
||||
{
|
||||
ramfs_init();
|
||||
|
||||
ramfs_make_root();
|
||||
|
||||
vfs_initialized = true;
|
||||
vfs_current_dir = ramfs_get_root();
|
||||
}
|
||||
}
|
||||
|
||||
/* ramfs_file_header_t* ramfs_create_file(char* name, char type, char encryption, ramfs_file_header_t* parent); */
|
||||
|
||||
FILE create_file(char* filename, char type, char encryption, FILE parent)
|
||||
{
|
||||
if (!filename)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parent == -128)
|
||||
{
|
||||
parent = vfs_current_dir->fd;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* file = ramfs_create_file(filename, type, encryption, ramfs_resolve_fd(parent));
|
||||
if (!file)
|
||||
{
|
||||
return -4; /* error code for failed creation */
|
||||
}
|
||||
|
||||
return file->fd;
|
||||
}
|
||||
|
||||
int32_t delete_file(FILE file)
|
||||
{
|
||||
/*
|
||||
XXX WARNING: ANY AND ALL PROCESSES CAN DELETE A FILE VIA THIS INTERFACE!!! XXX
|
||||
XXX THIS MUST BE PACHED SOON!!! OR AT LEAST ADD PERMISSION CHECKING IN THE SYSCALL INTERFACE XXX
|
||||
XXX OR IN THE C LIBRARIES!!! XXX
|
||||
*/
|
||||
|
||||
if (file < 1)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file);
|
||||
return ramfs_delete_file(_file);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Open a file based on a string.
|
||||
Return a file descriptor on success, a negative value on failure.
|
||||
|
||||
return values:
|
||||
(positive non-zero value) - File descriptor
|
||||
-1 - Insufficient permissions to open file
|
||||
-2 - File does not exist ( or at least, File not found. )
|
||||
-3 - No filesystem is initialized
|
||||
-4 - Internal error, perhaps try again
|
||||
*/
|
||||
FILE open_file(char* filename)
|
||||
{
|
||||
if (ramfs_get_initialized() && vfs_initialized)
|
||||
{
|
||||
ramfs_file_header_t* _file = ramfs_resolve_path(filename);
|
||||
|
||||
if (!_file)
|
||||
{
|
||||
return (FILE)-2;
|
||||
}
|
||||
|
||||
return (FILE)_file->fd;
|
||||
}
|
||||
|
||||
return (FILE)-3;
|
||||
}
|
||||
|
||||
|
||||
FILE write_file(FILE file, void* data, size_t len)
|
||||
{
|
||||
|
||||
if (file < 1 || !data || len == 0)
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
if (ramfs_get_initialized() && vfs_initialized)
|
||||
{
|
||||
|
||||
ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file);
|
||||
|
||||
if (!_file)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (_file->type == RAMFS_FILE_DIR)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_file->data_begin)
|
||||
{
|
||||
free(_file->data_begin);
|
||||
_file->data_begin = NULL;
|
||||
_file->data_end = NULL;
|
||||
}
|
||||
|
||||
void* new_buf = malloc(len);
|
||||
if (!new_buf)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
memcpy(new_buf, data, len);
|
||||
|
||||
_file->data_begin = new_buf;
|
||||
_file->data_end = (void*)((uint8_t*)new_buf + len);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
return -3;
|
||||
}
|
||||
|
||||
|
||||
int32_t read_file(FILE file, void* buf, size_t buflen)
|
||||
{
|
||||
if (file < 1 || !buf || buflen == 0)
|
||||
{
|
||||
return -1; /* Invalid arguments */
|
||||
}
|
||||
|
||||
if (ramfs_get_initialized() && vfs_initialized)
|
||||
{
|
||||
ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file);
|
||||
|
||||
if (!_file || _file->type == RAMFS_FILE_DIR)
|
||||
{
|
||||
return -2; /* Not a file or trying to read a directory */
|
||||
}
|
||||
|
||||
if (!_file->data_begin || !_file->data_end)
|
||||
{
|
||||
return 0; /* Empty file */
|
||||
}
|
||||
|
||||
size_t total_len = (size_t)((uint8_t*)_file->data_end - (uint8_t*)_file->data_begin);
|
||||
|
||||
if (_file->read_offset >= (int32_t)total_len)
|
||||
{
|
||||
return 0; /* End of file */
|
||||
}
|
||||
|
||||
size_t available = total_len - _file->read_offset;
|
||||
size_t to_copy = (buflen < available) ? buflen : available;
|
||||
|
||||
memcpy(buf, (uint8_t*)_file->data_begin + _file->read_offset, to_copy);
|
||||
|
||||
_file->read_offset += to_copy;
|
||||
|
||||
return (int32_t)to_copy;
|
||||
}
|
||||
|
||||
return -3; /* FS not initialized */
|
||||
}
|
||||
|
||||
int32_t reset_read_offset(FILE file)
|
||||
{
|
||||
if (file < 1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file);
|
||||
|
||||
if (!_file)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
_file->read_offset = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t seek_file(FILE file, int32_t offset)
|
||||
{
|
||||
if (file < 0 && file != -32 && file != -33)
|
||||
{
|
||||
return -1; /* Invalid file descriptor */
|
||||
}
|
||||
|
||||
ramfs_file_header_t* _file = ramfs_resolve_fd_dir(vfs_current_dir, file);
|
||||
|
||||
if (!_file || _file->type == RAMFS_FILE_DIR)
|
||||
return -2; // Invalid file or directory
|
||||
|
||||
if (!_file->data_begin || !_file->data_end)
|
||||
return -3; // Empty file
|
||||
|
||||
size_t file_size = (size_t)((uint8_t*)_file->data_end - (uint8_t*)_file->data_begin);
|
||||
|
||||
if (offset < 0 || (size_t)offset > file_size)
|
||||
return -4; // Offset out of bounds
|
||||
|
||||
_file->read_offset = offset;
|
||||
return 0; // Success
|
||||
}
|
||||
|
Reference in New Issue
Block a user