#include #include #include #include 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); }