mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
fix(fs): remove 256-file limit in RAMFS using a dynamic linked list
This commit is contained in:
parent
c1411e378a
commit
9988a6e420
1 changed files with 83 additions and 78 deletions
159
src/fs/fat32.c
159
src/fs/fat32.c
|
|
@ -15,7 +15,6 @@
|
|||
static spinlock_t ramfs_lock = SPINLOCK_INIT; // Protects the RAM-based filesystem (/)
|
||||
|
||||
|
||||
#define MAX_FILES 256
|
||||
#define MAX_CLUSTERS 8192
|
||||
#define MAX_OPEN_HANDLES 32
|
||||
|
||||
|
|
@ -23,8 +22,7 @@ static spinlock_t ramfs_lock = SPINLOCK_INIT; // Protects the RAM-based filesyst
|
|||
static uint32_t fat_table[MAX_CLUSTERS];
|
||||
static uint8_t cluster_data[MAX_CLUSTERS][FAT32_CLUSTER_SIZE];
|
||||
|
||||
// File/Directory tracking
|
||||
typedef struct {
|
||||
typedef struct FileEntry {
|
||||
char full_path[FAT32_MAX_PATH];
|
||||
char filename[FAT32_MAX_FILENAME];
|
||||
uint32_t start_cluster;
|
||||
|
|
@ -32,9 +30,10 @@ typedef struct {
|
|||
uint32_t attributes;
|
||||
bool used;
|
||||
char parent_path[FAT32_MAX_PATH];
|
||||
struct FileEntry *next;
|
||||
} FileEntry;
|
||||
|
||||
static FileEntry files[MAX_FILES];
|
||||
static FileEntry *file_list_head = NULL;
|
||||
static uint32_t next_cluster = 3; // Start after reserved clusters 0, 1, 2
|
||||
static FAT32_FileHandle open_handles[MAX_OPEN_HANDLES];
|
||||
static char current_dir[FAT32_MAX_PATH] = "/";
|
||||
|
|
@ -234,9 +233,9 @@ static FileEntry* ramfs_find_file(const char *path) {
|
|||
if (!normalized) return NULL;
|
||||
fat32_normalize_path(path, normalized);
|
||||
FileEntry *ret = NULL;
|
||||
for (int i = 0; i < MAX_FILES; i++) {
|
||||
if (files[i].used && fs_strcmp(files[i].full_path, normalized) == 0) {
|
||||
ret = &files[i];
|
||||
for (FileEntry *n = file_list_head; n; n = n->next) {
|
||||
if (fs_strcmp(n->full_path, normalized) == 0) {
|
||||
ret = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -244,11 +243,29 @@ static FileEntry* ramfs_find_file(const char *path) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static FileEntry* ramfs_find_free_entry(void) {
|
||||
for (int i = 0; i < MAX_FILES; i++) {
|
||||
if (!files[i].used) return &files[i];
|
||||
static FileEntry* ramfs_alloc_entry(void) {
|
||||
FileEntry *e = (FileEntry*)kmalloc(sizeof(FileEntry));
|
||||
if (!e) return NULL;
|
||||
for (int i = 0; i < (int)sizeof(FileEntry); i++) ((char*)e)[i] = 0;
|
||||
e->used = true;
|
||||
e->next = file_list_head;
|
||||
file_list_head = e;
|
||||
return e;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
static void ramfs_free_entry(FileEntry *entry) {
|
||||
if (!entry) return;
|
||||
if (file_list_head == entry) {
|
||||
file_list_head = entry->next;
|
||||
} else {
|
||||
for (FileEntry *n = file_list_head; n && n->next; n = n->next) {
|
||||
if (n->next == entry) {
|
||||
n->next = entry->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
kfree(entry);
|
||||
}
|
||||
|
||||
static FAT32_FileHandle* ramfs_find_free_handle(void) {
|
||||
|
|
@ -267,10 +284,8 @@ static uint32_t ramfs_allocate_cluster(void) {
|
|||
|
||||
static int ramfs_count_files_in_dir(const char *normalized_path) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < MAX_FILES; i++) {
|
||||
if (files[i].used && fs_strcmp(files[i].parent_path, normalized_path) == 0) {
|
||||
count++;
|
||||
}
|
||||
for (FileEntry *n = file_list_head; n; n = n->next) {
|
||||
if (fs_strcmp(n->parent_path, normalized_path) == 0) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
@ -306,14 +321,13 @@ static FAT32_FileHandle* ramfs_open(const char *normalized_path, const char *mod
|
|||
} else if (mode[0] == 'w' || (mode[0] == 'a')) {
|
||||
if (!entry) {
|
||||
if (!check_desktop_limit(normalized_path)) return NULL;
|
||||
entry = ramfs_find_free_entry();
|
||||
entry = ramfs_alloc_entry();
|
||||
if (!entry) return NULL;
|
||||
entry->used = true;
|
||||
fs_strcpy(entry->full_path, normalized_path);
|
||||
extract_filename(normalized_path, entry->filename);
|
||||
extract_parent_path(normalized_path, entry->parent_path);
|
||||
entry->start_cluster = ramfs_allocate_cluster();
|
||||
if (!entry->start_cluster) return NULL;
|
||||
if (!entry->start_cluster) { ramfs_free_entry(entry); return NULL; }
|
||||
entry->size = 0;
|
||||
entry->attributes = 0;
|
||||
}
|
||||
|
|
@ -411,9 +425,9 @@ static int ramfs_write(FAT32_FileHandle *handle, const void *buffer, int size) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_FILES; i++) {
|
||||
if (files[i].used && files[i].start_cluster == handle->start_cluster) {
|
||||
files[i].size = handle->size;
|
||||
for (FileEntry *n = file_list_head; n; n = n->next) {
|
||||
if (n->start_cluster == handle->start_cluster) {
|
||||
n->size = handle->size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1467,27 +1481,26 @@ static int vfs_ramfs_readdir(void *fs_private, const char *rel_path, vfs_dirent_
|
|||
vfs_ramfs_get_abs_path(rel_path, abs);
|
||||
|
||||
uint64_t rflags = spinlock_acquire_irqsave(&ramfs_lock);
|
||||
for (int i = 0; i < MAX_FILES && count < max; i++) {
|
||||
for (FileEntry *n = file_list_head; n && count < max; n = n->next) {
|
||||
bool match = false;
|
||||
if (files[i].used && files[i].filename[0] != '\0') {
|
||||
if (fs_strcmp(files[i].parent_path, abs) == 0) match = true;
|
||||
if (n->filename[0] != '\0') {
|
||||
if (fs_strcmp(n->parent_path, abs) == 0) match = true;
|
||||
|
||||
// Root unification: Treat "", "/", and "A:/" as root parent
|
||||
if (!match && abs[0] == '/' && abs[1] == '\0') {
|
||||
if (files[i].parent_path[0] == '\0' ||
|
||||
fs_strcmp(files[i].parent_path, "/") == 0 ||
|
||||
fs_strcmp(files[i].parent_path, "A:/") == 0) {
|
||||
if (n->parent_path[0] == '\0' ||
|
||||
fs_strcmp(n->parent_path, "/") == 0 ||
|
||||
fs_strcmp(n->parent_path, "A:/") == 0) {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
fs_strcpy(entries[count].name, files[i].filename);
|
||||
entries[count].size = files[i].size;
|
||||
entries[count].is_directory = (files[i].attributes & ATTR_DIRECTORY) ? 1 : 0;
|
||||
entries[count].start_cluster = files[i].start_cluster;
|
||||
entries[count].write_date = 0; // Not tracked in RAMFS for now
|
||||
fs_strcpy(entries[count].name, n->filename);
|
||||
entries[count].size = n->size;
|
||||
entries[count].is_directory = (n->attributes & ATTR_DIRECTORY) ? 1 : 0;
|
||||
entries[count].start_cluster = n->start_cluster;
|
||||
entries[count].write_date = 0;
|
||||
entries[count].write_time = 0;
|
||||
count++;
|
||||
}
|
||||
|
|
@ -1840,16 +1853,13 @@ void* fat32_mount_volume(void *disk_ptr) {
|
|||
// === Public API (Dispatch) ===
|
||||
|
||||
void fat32_init(void) {
|
||||
// Explicitly zero out all structures for RAMFS safety
|
||||
for (int i = 0; i < MAX_FILES; i++) {
|
||||
files[i].used = false;
|
||||
files[i].full_path[0] = 0;
|
||||
files[i].filename[0] = 0;
|
||||
files[i].parent_path[0] = 0;
|
||||
files[i].size = 0;
|
||||
files[i].attributes = 0;
|
||||
files[i].start_cluster = 0;
|
||||
FileEntry *node = file_list_head;
|
||||
while (node) {
|
||||
FileEntry *next = node->next;
|
||||
kfree(node);
|
||||
node = next;
|
||||
}
|
||||
file_list_head = NULL;
|
||||
|
||||
// Initialize FAT table for RAMFS
|
||||
for (int i = 0; i < MAX_CLUSTERS; i++) {
|
||||
|
|
@ -1917,11 +1927,6 @@ FAT32_FileHandle* fat32_open_nolock(const char *path, const char *mode) {
|
|||
}
|
||||
}
|
||||
} else if (path[0] == '/') {
|
||||
// Absolute VFS path - bypass legacy drive letters
|
||||
// This is safe to call WITHOUT the fat32_lock because vfs_open was called formerly
|
||||
// and it will resolve to one of our mounts which will then acquire the lock.
|
||||
// HOWEVER, if we are already inside a fat32_lock call, we SHOULD NOT call vfs_open.
|
||||
// For now, absolute paths starting with / are handled by VFS entry points.
|
||||
vfs_file_t *vf = vfs_open(path, mode);
|
||||
if (vf && vf->fs_handle) {
|
||||
return (FAT32_FileHandle*)vf->fs_handle;
|
||||
|
|
@ -2223,7 +2228,7 @@ bool fat32_mkdir(const char *path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
FileEntry *entry = ramfs_find_free_entry();
|
||||
FileEntry *entry = ramfs_alloc_entry();
|
||||
if (!entry) {
|
||||
kfree(normalized);
|
||||
spinlock_release_irqrestore(&ramfs_lock, rflags);
|
||||
|
|
@ -2263,7 +2268,7 @@ bool fat32_rmdir(const char *path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
entry->used = false;
|
||||
ramfs_free_entry(entry);
|
||||
kfree(normalized);
|
||||
wm_notify_fs_change();
|
||||
spinlock_release_irqrestore(&ramfs_lock, rflags);
|
||||
|
|
@ -2287,7 +2292,7 @@ bool fat32_delete(const char *path) {
|
|||
|
||||
FileEntry *entry = ramfs_find_file(normalized);
|
||||
if (entry && !(entry->attributes & ATTR_DIRECTORY)) {
|
||||
entry->used = false;
|
||||
ramfs_free_entry(entry);
|
||||
result = true;
|
||||
}
|
||||
kfree(normalized);
|
||||
|
|
@ -2426,27 +2431,26 @@ bool fat32_rename(const char *old_path, const char *new_path) {
|
|||
char *suffix = (char*)kmalloc(FAT32_MAX_PATH);
|
||||
if (!suffix) { spinlock_release_irqrestore(&ramfs_lock, rflags); return false; }
|
||||
|
||||
for (int i = 0; i < MAX_FILES; i++) {
|
||||
if (!files[i].used) continue;
|
||||
if (fs_strcmp(files[i].full_path, old_path) == 0) {
|
||||
fs_strcpy(files[i].full_path, new_path);
|
||||
extract_filename(new_path, files[i].filename);
|
||||
extract_parent_path(new_path, files[i].parent_path);
|
||||
} else if (fs_strlen(files[i].full_path) > old_len &&
|
||||
fs_starts_with(files[i].full_path, old_path) &&
|
||||
files[i].full_path[old_len] == '/') {
|
||||
fs_strcpy(suffix, files[i].full_path + old_len);
|
||||
fs_strcpy(files[i].full_path, new_path);
|
||||
fs_strcat(files[i].full_path, suffix);
|
||||
for (FileEntry *n = file_list_head; n; n = n->next) {
|
||||
if (fs_strcmp(n->full_path, old_path) == 0) {
|
||||
fs_strcpy(n->full_path, new_path);
|
||||
extract_filename(new_path, n->filename);
|
||||
extract_parent_path(new_path, n->parent_path);
|
||||
} else if (fs_strlen(n->full_path) > old_len &&
|
||||
fs_starts_with(n->full_path, old_path) &&
|
||||
n->full_path[old_len] == '/') {
|
||||
fs_strcpy(suffix, n->full_path + old_len);
|
||||
fs_strcpy(n->full_path, new_path);
|
||||
fs_strcat(n->full_path, suffix);
|
||||
}
|
||||
if (fs_strcmp(files[i].parent_path, old_path) == 0) {
|
||||
fs_strcpy(files[i].parent_path, new_path);
|
||||
} else if (fs_strlen(files[i].parent_path) > old_len &&
|
||||
fs_starts_with(files[i].parent_path, old_path) &&
|
||||
files[i].parent_path[old_len] == '/') {
|
||||
fs_strcpy(suffix, files[i].parent_path + old_len);
|
||||
fs_strcpy(files[i].parent_path, new_path);
|
||||
fs_strcat(files[i].parent_path, suffix);
|
||||
if (fs_strcmp(n->parent_path, old_path) == 0) {
|
||||
fs_strcpy(n->parent_path, new_path);
|
||||
} else if (fs_strlen(n->parent_path) > old_len &&
|
||||
fs_starts_with(n->parent_path, old_path) &&
|
||||
n->parent_path[old_len] == '/') {
|
||||
fs_strcpy(suffix, n->parent_path + old_len);
|
||||
fs_strcpy(n->parent_path, new_path);
|
||||
fs_strcat(n->parent_path, suffix);
|
||||
}
|
||||
}
|
||||
kfree(suffix);
|
||||
|
|
@ -2524,15 +2528,16 @@ int fat32_list_directory(const char *path, FAT32_FileInfo *entries, int max_entr
|
|||
if (!normalized) { spinlock_release_irqrestore(&ramfs_lock, rflags); return 0; }
|
||||
fat32_normalize_path(p, normalized);
|
||||
|
||||
for (int i = 0; i < MAX_FILES && count < max_entries; i++) {
|
||||
if (files[i].used && fs_strcmp(files[i].parent_path, normalized) == 0) {
|
||||
fs_strcpy(entries[count].name, files[i].filename);
|
||||
entries[count].size = files[i].size;
|
||||
entries[count].is_directory = (files[i].attributes & ATTR_DIRECTORY) != 0;
|
||||
entries[count].start_cluster = files[i].start_cluster;
|
||||
for (FileEntry *_n = file_list_head; _n && count < max_entries; _n = _n->next) {
|
||||
if (fs_strcmp(_n->parent_path, normalized) != 0) continue;
|
||||
fs_strcpy(entries[count].name, _n->filename);
|
||||
entries[count].size = _n->size;
|
||||
entries[count].is_directory = (_n->attributes & ATTR_DIRECTORY) != 0;
|
||||
entries[count].start_cluster = _n->start_cluster;
|
||||
entries[count].write_date = 0;
|
||||
entries[count].write_time = 0;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
kfree(normalized);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue