From 74637eb5a6ca2a47c2a02654aa31b1f480b62a07 Mon Sep 17 00:00:00 2001 From: Freywar Ulvnaudgari Date: Wed, 15 Jul 2026 23:14:56 +0300 Subject: [PATCH] Merge `fat16_inode_t` and `fat16_node_t`, make `fs_node_t` shared --- src/kernel/fat16.c | 378 +++++++++++++++++++++---------------------- src/kernel/fat16.h | 8 +- src/kernel/fs.c | 12 +- src/kernel/fs.h | 12 +- src/kernel/kernel.c | 5 +- src/kernel/path.c | 56 ++++--- src/kernel/path.h | 10 +- src/kernel/process.c | 9 +- src/kernel/process.h | 2 - src/kernel/syscall.c | 10 +- 10 files changed, 249 insertions(+), 253 deletions(-) diff --git a/src/kernel/fat16.c b/src/kernel/fat16.c index e0ef97c..1b14c54 100644 --- a/src/kernel/fat16.c +++ b/src/kernel/fat16.c @@ -34,89 +34,68 @@ typedef struct __attribute__((packed)) { uint32_t size; } fat16_dir_entry_t; -#define MAX_INODES 256 +// Assuming one persistently mounted partition. +static fat16_bpb_t *bpb = NUL; +static uint32_t data_start; +static uint16_t *fat = NUL; typedef struct { - uint32_t refs; - uint16_t first_cluster; - uint32_t size; + fs_node_t base; uint16_t dir_cluster; uint16_t dir_index; - uint8_t removed; -} fat16_inode_t; - -static fat16_inode_t inodes[MAX_INODES]; - -static fat16_inode_t *inode_create(uint16_t first_cluster, uint32_t size, uint16_t dir_cluster, uint16_t dir_index) { - for (uint64_t i = 0; i < MAX_INODES; i++) { - if (!inodes[i].refs) { - inodes[i] = (fat16_inode_t){ - .refs = 1, - .first_cluster = first_cluster, - .size = size, - .dir_cluster = dir_cluster, - .dir_index = dir_index, - }; - return &inodes[i]; + uint16_t first_cluster; +} fat16_node_t; + +#define MAX_NODES 256 + +static fat16_node_t nodes[MAX_NODES]; + +static fs_node_t *node_create(uint16_t dir_cluster, uint16_t dir_index, const char *name, uint8_t is_dir, uint16_t first_cluster, + uint32_t size) { + for (uint64_t i = 0; i < MAX_NODES; i++) { + if (!nodes[i].base.refs) { + nodes[i].base.type = FAT16; + nodes[i].base.refs = 1; + memory_copy(name, FILENAME_SIZE_LIMIT + 1, nodes[i].base.name); + nodes[i].base.size = size; + nodes[i].base.is_dir = is_dir; + nodes[i].base.removed = 0; + nodes[i].dir_cluster = dir_cluster; + nodes[i].dir_index = dir_index; + nodes[i].first_cluster = first_cluster; + return (fs_node_t *)&nodes[i]; } } return NUL; } -static fat16_inode_t *inode_get(uint32_t dir_cluster, uint16_t dir_index) { - for (uint64_t i = 0; i < MAX_INODES; i++) { - if (inodes[i].refs && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) { - return &inodes[i]; +static fs_node_t *node_get(uint32_t dir_cluster, uint16_t dir_index) { + for (uint64_t i = 0; i < MAX_NODES; i++) { + if (nodes[i].base.refs && nodes[i].dir_cluster == dir_cluster && nodes[i].dir_index == dir_index) { + return (fs_node_t *)&nodes[i]; } } return NUL; } -static fat16_inode_t *inode_use(uint16_t first_cluster, uint32_t size, uint16_t dir_cluster, uint16_t dir_index) { - fat16_inode_t *result = inode_get(dir_cluster, dir_index); +static fs_node_t *node_use(uint16_t dir_cluster, uint16_t dir_index, const char *name, uint8_t is_dir, uint16_t first_cluster, + uint32_t size) { + fs_node_t *result = node_get(dir_cluster, dir_index); if (!result) { - result = inode_create(first_cluster, size, dir_cluster, dir_index); + result = node_create(dir_cluster, dir_index, name, is_dir, first_cluster, size); } else { + ASSERT(result->refs < UINT32_MAX, "node_use: too many references"); result->refs++; } return result; } -static void inode_free(fat16_inode_t *inode) { - if (inode->refs) { - inode->refs--; +static void node_free(fs_node_t *node) { + if (node->refs) { + node->refs--; } } -typedef struct { - fs_node_t base; - fat16_inode_t *inode; -} fat16_node_t; - -static fat16_bpb_t bpb; // Assuming one partition. -static uint32_t data_start; -static fs_node_t *fs = NUL; -static uint16_t *fat = NUL; - -fs_node_t *fat16_mount() { // Assuming one partition. - uint8_t sector[512]; - ata_read_sectors(FIRST_PARTITION_SECTOR, 1, §or); - memory_copy(sector + 11, sizeof(fat16_bpb_t), &bpb); - data_start = FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.sectors_per_fat * bpb.fats_count + - (bpb.root_entry_count * sizeof(fat16_dir_entry_t) + SECTOR_SIZE - 1) / SECTOR_SIZE; - fat16_node_t *node = memory_allocate(sizeof(fat16_node_t)); - node->base.type = FAT16; - node->base.name[0] = '/'; - node->base.size = sizeof(fat16_dir_entry_t) * bpb.root_entry_count; - node->base.is_dir = 1; - node->inode = inode_use(0, node->base.size, 0, UINT16_MAX); - if (!node->inode) { - memory_free(node); - return NUL; - } - return fs = (fs_node_t *)node; -} - static void to_8_3(const char *name, char *output) { memory_set(' ', 11, output); output[11] = '\0'; @@ -150,17 +129,35 @@ static void from_8_3(const char *name, const char *extension, char *output) { } } +static void ensure_bpb() { + if (bpb) { + return; + } + + uint8_t sector[512]; + ata_read_sectors(FIRST_PARTITION_SECTOR, 1, §or); + bpb = memory_allocate(sizeof(fat16_bpb_t)); + memory_copy(sector + 11, sizeof(fat16_bpb_t), bpb); + data_start = FIRST_PARTITION_SECTOR + bpb->reserved_sectors + bpb->sectors_per_fat * bpb->fats_count + + (bpb->root_entry_count * sizeof(fat16_dir_entry_t) + SECTOR_SIZE - 1) / SECTOR_SIZE; +} + static void ensure_fat() { - ASSERT(bpb.sectors_per_fat < 256, "ensure_fat: big FAT not implemented") - if (!fat) { - fat = memory_allocate(bpb.sectors_per_fat * SECTOR_SIZE); - ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat); + if (fat) { + return; } + + ensure_bpb(); + + ASSERT(bpb->sectors_per_fat < 256, "ensure_fat: big FAT not implemented"); + + fat = memory_allocate(bpb->sectors_per_fat * SECTOR_SIZE); + ata_read_sectors(FIRST_PARTITION_SECTOR + bpb->reserved_sectors, (uint8_t)bpb->sectors_per_fat, fat); } static uint16_t allocate_cluster() { ensure_fat(); - for (uint16_t i = 2; i < bpb.sectors_per_fat * SECTOR_SIZE / 2; i++) { + for (uint16_t i = 2; i < bpb->sectors_per_fat * SECTOR_SIZE / 2; i++) { if (fat[i] == 0x0000) { fat[i] = 0xFFFF; return i; @@ -170,15 +167,18 @@ static uint16_t allocate_cluster() { } static void flush_fat() { - ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat); + ensure_fat(); + ata_write_sectors(FIRST_PARTITION_SECTOR + bpb->reserved_sectors, (uint8_t)bpb->sectors_per_fat, fat); } static uint16_t read_directory(uint16_t dir_cluster, fat16_dir_entry_t **entries) { + ensure_bpb(); + if (!dir_cluster) { - uint8_t sectors = (uint8_t)((sizeof(fat16_dir_entry_t) * bpb.root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE); + uint8_t sectors = (uint8_t)((sizeof(fat16_dir_entry_t) * bpb->root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE); *entries = memory_allocate(sectors * SECTOR_SIZE); - ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, sectors, *entries); - return bpb.root_entry_count; + ata_read_sectors(FIRST_PARTITION_SECTOR + bpb->reserved_sectors + bpb->fats_count * bpb->sectors_per_fat, sectors, *entries); + return bpb->root_entry_count; } else { ensure_fat(); @@ -188,19 +188,19 @@ static uint16_t read_directory(uint16_t dir_cluster, fat16_dir_entry_t **entries cluster_count++; next_cluster = fat[next_cluster]; } - *entries = memory_allocate(cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE); + *entries = memory_allocate(cluster_count * bpb->sectors_per_cluster * SECTOR_SIZE); uint8_t *chunk = (uint8_t *)*entries; next_cluster = dir_cluster; while (next_cluster < 0xFFF8) { - ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk); - chunk += bpb.sectors_per_cluster * SECTOR_SIZE; + ata_read_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, chunk); + chunk += bpb->sectors_per_cluster * SECTOR_SIZE; next_cluster = fat[next_cluster]; } - return cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t); + return cluster_count * bpb->sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t); } - return (uint64_t)-1; + return (uint16_t)-1; } static fs_node_t *open_entry(uint16_t dir_cluster, const fat16_dir_entry_t *entries, uint16_t index) { @@ -210,38 +210,30 @@ static fs_node_t *open_entry(uint16_t dir_cluster, const fat16_dir_entry_t *entr return NUL; } - fat16_node_t *result = memory_allocate(sizeof(fat16_node_t)); - result->base.type = FAT16; - from_8_3(entry->name, entry->ext, result->base.name); - - result->base.size = entry->size; - result->base.is_dir = entry->attributes & ATTRIBUTE_SUBDIRECTORY; - result->inode = inode_use(entry->first_cluster, entry->size, dir_cluster, index); - - if (!result->inode) { - memory_free(result); - return NUL; - } + char name[FILENAME_SIZE_LIMIT + 1]; + from_8_3(entry->name, entry->ext, name); - return (fs_node_t *)result; + return node_use(dir_cluster, index, name, entry->attributes & ATTRIBUTE_SUBDIRECTORY, entry->first_cluster, entry->size); } static void write_directory(uint16_t dir_cluster, const fat16_dir_entry_t *entries, uint16_t count) { - ASSERT((count * sizeof(fat16_dir_entry_t)) % (bpb.sectors_per_cluster * SECTOR_SIZE) == 0, + ensure_bpb(); + + ASSERT((count * sizeof(fat16_dir_entry_t)) % (bpb->sectors_per_cluster * SECTOR_SIZE) == 0, "write_directory: entries must be aligned to clusters"); if (!dir_cluster) { - ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, - (uint8_t)((sizeof(fat16_dir_entry_t) * bpb.root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE), entries); + ata_write_sectors(FIRST_PARTITION_SECTOR + bpb->reserved_sectors + bpb->fats_count * bpb->sectors_per_fat, + (uint8_t)((sizeof(fat16_dir_entry_t) * bpb->root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE), entries); } else { ensure_fat(); uint8_t *chunk = (uint8_t *)entries; uint16_t next_cluster = dir_cluster; while (count) { - ata_write_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk); - chunk += bpb.sectors_per_cluster * SECTOR_SIZE; - count -= bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t); + ata_write_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, chunk); + chunk += bpb->sectors_per_cluster * SECTOR_SIZE; + count -= bpb->sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t); if (count && fat[next_cluster] >= 0xFFF8) { fat[next_cluster] = allocate_cluster(); } @@ -251,16 +243,18 @@ static void write_directory(uint16_t dir_cluster, const fat16_dir_entry_t *entri } } -fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t flags) { - if (directory->type != FAT16 || !directory->is_dir) { - return NUL; - } +fs_node_t *fat16_open_root() { + ensure_bpb(); + + return node_use(0, UINT16_MAX, "", 1, 0, sizeof(fat16_dir_entry_t) * bpb->root_entry_count); +} - if (((fat16_node_t *)directory)->inode->removed) { +fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t flags) { + if (!directory || directory->type != FAT16 || !directory->is_dir || directory->removed) { return NUL; } - uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster; + uint16_t dir_cluster = ((fat16_node_t *)directory)->first_cluster; char name_8_3[12]; to_8_3(name, name_8_3); @@ -295,7 +289,7 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t memory_free(entries); return NUL; } else { - uint16_t new_entries_count = entries_count + bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t); + uint16_t new_entries_count = entries_count + bpb->sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t); fat16_dir_entry_t *new_entries = memory_allocate(new_entries_count * sizeof(fat16_dir_entry_t)); memory_copy(entries, entries_count * sizeof(fat16_dir_entry_t), new_entries); memory_free(entries); @@ -309,14 +303,14 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t if (flags & OPEN_DIRECTORY && !(flags & OPEN_FILE)) { entries[index].attributes = ATTRIBUTE_SUBDIRECTORY; entries[index].first_cluster = allocate_cluster(); - fat16_dir_entry_t *inner_entries = memory_allocate(bpb.sectors_per_cluster * SECTOR_SIZE); + fat16_dir_entry_t *inner_entries = memory_allocate(bpb->sectors_per_cluster * SECTOR_SIZE); memory_copy(". ", 11, inner_entries[0].name); inner_entries[0].attributes = ATTRIBUTE_SUBDIRECTORY; inner_entries[0].first_cluster = entries[index].first_cluster; memory_copy(".. ", 11, inner_entries[1].name); inner_entries[1].attributes = ATTRIBUTE_SUBDIRECTORY; inner_entries[1].first_cluster = dir_cluster; - write_directory(entries[index].first_cluster, inner_entries, bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t)); + write_directory(entries[index].first_cluster, inner_entries, bpb->sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t)); memory_free(inner_entries); } @@ -343,15 +337,11 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t } fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags) { - if (directory->type != FAT16 || !directory->is_dir) { - return NUL; - } - - if (((fat16_node_t *)directory)->inode->removed) { + if (!directory || directory->type != FAT16 || !directory->is_dir || directory->removed) { return NUL; } - uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster; + uint16_t dir_cluster = ((fat16_node_t *)directory)->first_cluster; fat16_dir_entry_t *entries; uint16_t entries_count = read_directory(dir_cluster, &entries); @@ -367,7 +357,7 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t fl ei++; } - fs_node_t *result = open_entry(((fat16_node_t *)directory)->inode->first_cluster, entries, ei); + fs_node_t *result = open_entry(dir_cluster, entries, ei); memory_free(entries); @@ -390,36 +380,33 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t fl return result; } -fs_node_t *fat16_open_again(const fs_node_t *source) { - fs_node_t *result = memory_allocate(sizeof(fat16_node_t)); - memory_copy(source, sizeof(fat16_node_t), result); - ((fat16_node_t *)result)->inode->refs++; - return result; +fs_node_t *fat16_open_again(fs_node_t *source) { + ASSERT(source->refs < UINT32_MAX, "fat16_open_again: too many references"); + source->refs++; + return source; } uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void *to) { - fat16_node_t *fat_file = (fat16_node_t *)file; - - if (fat_file->base.type != FAT16 || fat_file->base.is_dir) { + if (!file || file->type != FAT16 || file->is_dir) { return (uint64_t)-1; } - if (fat_file->inode->removed) { + if (file->removed) { return 0; } - if (offset >= fat_file->inode->size) { + if (offset >= file->size) { return 0; } - if (offset + bytes >= fat_file->inode->size) { - bytes = fat_file->inode->size - offset; + if (offset + bytes >= file->size) { + bytes = file->size - offset; } ensure_fat(); - uint32_t cluster_size = bpb.sectors_per_cluster * SECTOR_SIZE; - uint32_t next_cluster = fat_file->inode->first_cluster; + uint32_t cluster_size = bpb->sectors_per_cluster * SECTOR_SIZE; + uint32_t next_cluster = ((fat16_node_t *)file)->first_cluster; while (offset >= cluster_size) { next_cluster = fat[next_cluster]; @@ -431,7 +418,7 @@ uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void uint8_t *cursor = to; uint8_t *tmp = memory_allocate(cluster_size); - ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, tmp); + ata_read_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, tmp); uint32_t prefix_size = bytes <= cluster_size - offset ? bytes : cluster_size - offset; memory_copy(tmp + offset, prefix_size, cursor); bytes -= prefix_size; @@ -440,7 +427,7 @@ uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void next_cluster = fat[next_cluster]; while (bytes >= cluster_size) { - ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, cursor); + ata_read_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, cursor); bytes -= cluster_size; readden += cluster_size; cursor += cluster_size; @@ -448,7 +435,7 @@ uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void } if (bytes) { - ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, tmp); + ata_read_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, tmp); memory_copy(tmp, bytes, cursor); readden += bytes; } @@ -459,24 +446,24 @@ uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void } uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_t bytes) { - fat16_node_t *fat_file = (fat16_node_t *)file; - - if (fat_file->base.type != FAT16 || fat_file->base.is_dir) { + if (!file || file->type != FAT16 || file->is_dir) { return (uint64_t)-1; } - if (fat_file->inode->removed) { + if (file->removed) { return 0; } ensure_fat(); - if (!fat_file->inode->first_cluster) { - fat_file->inode->first_cluster = allocate_cluster(); + fat16_node_t *fat_file = (fat16_node_t *)file; + + if (!fat_file->first_cluster) { + fat_file->first_cluster = allocate_cluster(); } - uint32_t cluster_size = bpb.sectors_per_cluster * SECTOR_SIZE; - uint32_t next_cluster = fat_file->inode->first_cluster; + uint32_t cluster_size = bpb->sectors_per_cluster * SECTOR_SIZE; + uint32_t next_cluster = fat_file->first_cluster; uint32_t allocated = cluster_size; while (allocated < offset + bytes) { @@ -489,8 +476,8 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_ flush_fat(); - cluster_size = bpb.sectors_per_cluster * SECTOR_SIZE; - next_cluster = fat_file->inode->first_cluster; + cluster_size = bpb->sectors_per_cluster * SECTOR_SIZE; + next_cluster = fat_file->first_cluster; while (offset >= cluster_size) { next_cluster = fat[next_cluster]; @@ -502,17 +489,17 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_ const uint8_t *cursor = from; uint8_t *tmp = memory_allocate(cluster_size); - ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, tmp); + ata_read_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, tmp); uint32_t prefix_size = bytes <= cluster_size - offset ? bytes : cluster_size - offset; memory_copy(cursor, prefix_size, tmp + offset); - ata_write_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, tmp); + ata_write_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, tmp); bytes -= prefix_size; written += prefix_size; cursor += prefix_size; next_cluster = fat[next_cluster]; while (bytes >= cluster_size) { - ata_write_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, cursor); + ata_write_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, cursor); bytes -= cluster_size; written += cluster_size; cursor += cluster_size; @@ -520,22 +507,22 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_ } if (bytes) { - ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, tmp); + ata_read_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, tmp); memory_copy(cursor, bytes, tmp); - ata_write_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, tmp); + ata_write_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, tmp); written += bytes; } memory_free(tmp); - if (offset + written > fat_file->inode->size) { - fat_file->inode->size = offset + written; + if (offset + written > file->size) { + file->size = offset + written; fat16_dir_entry_t *entries; - uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries); - entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster; - entries[fat_file->inode->dir_index].size = fat_file->inode->size; - write_directory(fat_file->inode->dir_cluster, entries, entries_count); + uint16_t entries_count = read_directory(fat_file->dir_cluster, &entries); + entries[fat_file->dir_index].first_cluster = fat_file->first_cluster; + entries[fat_file->dir_index].size = file->size; + write_directory(fat_file->dir_cluster, entries, entries_count); memory_free(entries); } @@ -543,13 +530,11 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_ } uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { - fat16_node_t *fat_file = (fat16_node_t *)file; - - if (fat_file->base.type != FAT16 || fat_file->base.is_dir) { + if (!file || file->type != FAT16 || file->is_dir) { return (uint64_t)-1; } - if (fat_file->inode->removed) { + if (file->removed) { return 0; } @@ -562,9 +547,11 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { memory_free(tmp); return written == (uint64_t)-1 ? (uint64_t)-1 : file->size + written; } else if (file->size > size) { - uint32_t cluster_size = bpb.sectors_per_cluster * SECTOR_SIZE; + fat16_node_t *fat_file = (fat16_node_t *)file; + + uint32_t cluster_size = bpb->sectors_per_cluster * SECTOR_SIZE; uint32_t prev_cluster = 0; - uint32_t next_cluster = fat_file->inode->first_cluster; + uint32_t next_cluster = fat_file->first_cluster; ensure_fat(); uint32_t allocated = 0; @@ -576,7 +563,7 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { if (prev_cluster) { fat[prev_cluster] = 0xFFFF; } else { - fat_file->inode->first_cluster = 0; + fat_file->first_cluster = 0; } do { uint32_t swap = fat[next_cluster]; @@ -585,12 +572,12 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { } while (next_cluster < 0xFFF8); flush_fat(); - fat_file->inode->size = size; + file->size = size; fat16_dir_entry_t *entries; - uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries); - entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster; - entries[fat_file->inode->dir_index].size = fat_file->inode->size; - write_directory(fat_file->inode->dir_cluster, entries, entries_count); + uint16_t entries_count = read_directory(fat_file->dir_cluster, &entries); + entries[fat_file->dir_index].first_cluster = fat_file->first_cluster; + entries[fat_file->dir_index].size = file->size; + write_directory(fat_file->dir_cluster, entries, entries_count); memory_free(entries); return size; @@ -599,19 +586,19 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { } uint64_t fat16_remove(fs_node_t *file) { - fat16_node_t *fat_file = (fat16_node_t *)file; - - if (fat_file->base.type != FAT16) { + if (!file || file->type != FAT16) { return (uint64_t)-1; } - if (fat_file->inode->removed) { + if (file->removed) { return 0; } + fat16_node_t *fat_file = (fat16_node_t *)file; + if (file->is_dir) { fat16_dir_entry_t *subentries; - uint16_t subentries_count = read_directory(fat_file->inode->first_cluster, &subentries); + uint16_t subentries_count = read_directory(fat_file->first_cluster, &subentries); uint16_t ei = 0, vi = 0; while (ei < subentries_count && subentries[ei].name[0]) { if ((uint8_t)subentries[ei].name[0] != 0xE5 && (uint8_t)subentries[ei].attributes != 0x0F) { @@ -625,11 +612,11 @@ uint64_t fat16_remove(fs_node_t *file) { } } - fat_file->inode->removed = 1; + file->removed = 1; - if (fat_file->inode->first_cluster) { + if (fat_file->first_cluster) { ensure_fat(); - uint64_t next_cluster = fat_file->inode->first_cluster; + uint64_t next_cluster = fat_file->first_cluster; do { uint32_t swap = fat[next_cluster]; fat[next_cluster] = 0; @@ -639,11 +626,11 @@ uint64_t fat16_remove(fs_node_t *file) { } fat16_dir_entry_t *entries; - uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries); - entries[fat_file->inode->dir_index].name[0] = 0xE5; - entries[fat_file->inode->dir_index].first_cluster = 0; - entries[fat_file->inode->dir_index].size = 0; - write_directory(fat_file->inode->dir_cluster, entries, entries_count); + uint16_t entries_count = read_directory(fat_file->dir_cluster, &entries); + entries[fat_file->dir_index].name[0] = 0xE5; + entries[fat_file->dir_index].first_cluster = 0; + entries[fat_file->dir_index].size = 0; + write_directory(fat_file->dir_cluster, entries, entries_count); memory_free(entries); return 1; @@ -656,6 +643,10 @@ typedef struct { } fat16_file_stream_t; static uint64_t file_stream_write(stream_t *self, const char *from, uint64_t bytes) { + if (!self) { + return (uint64_t)-1; + } + fat16_file_stream_t *ffs = (fat16_file_stream_t *)self; uint64_t written = fat16_write(ffs->node, ffs->offset, from, bytes > UINT32_MAX ? UINT32_MAX : (uint32_t)bytes); if (written != (uint64_t)-1) { @@ -665,6 +656,10 @@ static uint64_t file_stream_write(stream_t *self, const char *from, uint64_t byt } static uint64_t file_stream_read(stream_t *self, uint64_t max, char *to) { + if (!self) { + return (uint64_t)-1; + } + fat16_file_stream_t *ffs = (fat16_file_stream_t *)self; uint64_t readden = fat16_read(ffs->node, ffs->offset, max > UINT32_MAX ? UINT32_MAX : (uint32_t)max, to); if (readden != (uint64_t)-1) { @@ -674,6 +669,10 @@ static uint64_t file_stream_read(stream_t *self, uint64_t max, char *to) { } static uint64_t file_stream_truncate(stream_t *self, uint64_t size) { + if (!self) { + return (uint64_t)-1; + } + fat16_file_stream_t *ffs = (fat16_file_stream_t *)self; uint64_t resized = fat16_truncate(ffs->node, size > UINT32_MAX ? UINT32_MAX : (uint32_t)size); if (resized != (uint64_t)-1 && resized < ffs->offset) { @@ -683,6 +682,10 @@ static uint64_t file_stream_truncate(stream_t *self, uint64_t size) { } static void file_stream_close(stream_t *self) { + if (!self) { + return; + } + fat16_file_stream_t *ffs = (fat16_file_stream_t *)self; fat16_close(ffs->node); memory_free(self); @@ -700,6 +703,10 @@ static uint64_t directory_stream_write(__attribute__((unused)) stream_t *self, _ } static uint64_t directory_stream_read(stream_t *self, uint64_t max, char *to) { + if (!self) { + return (uint64_t)-1; + } + fat16_directory_stream_t *fds = (fat16_directory_stream_t *)self; fs_node_t *node = fat16_open_at(fds->node, fds->index++, OPEN_FILE | OPEN_DIRECTORY); if (!node) { @@ -717,12 +724,20 @@ static uint64_t directory_stream_truncate(__attribute__((unused)) stream_t *self } static void directory_stream_close(stream_t *self) { + if (!self) { + return; + } + fat16_directory_stream_t *fds = (fat16_directory_stream_t *)self; fat16_close(fds->node); memory_free(self); } -stream_t *fat16_open_stream(const fs_node_t *source) { +stream_t *fat16_open_stream(fs_node_t *source) { + if (!source) { + return NUL; + } + if (!source->is_dir) { fat16_file_stream_t *result = memory_allocate(sizeof(fat16_file_stream_t)); result->stream.read = file_stream_read; @@ -745,24 +760,9 @@ stream_t *fat16_open_stream(const fs_node_t *source) { } void fat16_close(fs_node_t *node) { - if (node->type != FAT16 || node == fs) { + if (!node || node->type != FAT16) { return; } - inode_free(((fat16_node_t *)node)->inode); - memory_free(node); -} - -void fat16_unmount(fs_node_t *node) { - if (node->type != FAT16 || node != fs) { - return; - } - inode_free(((fat16_node_t *)node)->inode); - memory_free(node); - - if (fat) { - memory_free(fat); - fat = NUL; - } - fs = NUL; + node_free(node); } diff --git a/src/kernel/fat16.h b/src/kernel/fat16.h index 9284a33..bdcd007 100644 --- a/src/kernel/fat16.h +++ b/src/kernel/fat16.h @@ -5,15 +5,15 @@ #define FAT16 1 -fs_node_t *fat16_mount(); +fs_node_t *fat16_open_root(); fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t flags); fs_node_t *fat16_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags); -fs_node_t *fat16_open_again(const fs_node_t *source); +fs_node_t *fat16_open_again(fs_node_t *source); -stream_t *fat16_open_stream(const fs_node_t *source); +stream_t *fat16_open_stream(fs_node_t *source); uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void *to); @@ -24,5 +24,3 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size); uint64_t fat16_remove(fs_node_t *file); void fat16_close(fs_node_t *node); - -void fat16_unmount(fs_node_t *fs); diff --git a/src/kernel/fs.c b/src/kernel/fs.c index c7f184f..d204645 100644 --- a/src/kernel/fs.c +++ b/src/kernel/fs.c @@ -1,8 +1,8 @@ #include "src/kernel/fs.h" #include "src/kernel/fat16.h" -fs_node_t *fs_mount() { - return fat16_mount(); +fs_node_t *fs_open_root() { + return fat16_open_root(); } fs_node_t *fs_open_by(const fs_node_t *directory, const char *name, uint64_t flags) { @@ -13,11 +13,11 @@ fs_node_t *fs_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags return fat16_open_at(directory, index, flags); } -fs_node_t *fs_open_again(const fs_node_t *source) { +fs_node_t *fs_open_again(fs_node_t *source) { return fat16_open_again(source); } -stream_t *fs_open_stream(const fs_node_t *source) { +stream_t *fs_open_stream(fs_node_t *source) { return fat16_open_stream(source); } @@ -40,7 +40,3 @@ void fs_remove(fs_node_t *file) { void fs_close(fs_node_t *node) { fat16_close(node); } - -void fs_unmount(fs_node_t *fs) { - fat16_unmount(fs); -} diff --git a/src/kernel/fs.h b/src/kernel/fs.h index 284ef0a..e241ceb 100644 --- a/src/kernel/fs.h +++ b/src/kernel/fs.h @@ -5,21 +5,23 @@ #define FILENAME_SIZE_LIMIT 255 typedef struct fs_node { + uint8_t type; + uint32_t refs; char name[FILENAME_SIZE_LIMIT + 1]; uint32_t size; uint8_t is_dir; - uint8_t type; + uint8_t removed; } fs_node_t; -fs_node_t *fs_mount(); +fs_node_t *fs_open_root(); fs_node_t *fs_open_by(const fs_node_t *directory, const char *name, uint64_t flags); fs_node_t *fs_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags); -fs_node_t *fs_open_again(const fs_node_t *source); +fs_node_t *fs_open_again(fs_node_t *source); -stream_t *fs_open_stream(const fs_node_t *source); +stream_t *fs_open_stream(fs_node_t *source); void fs_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void *to); @@ -30,5 +32,3 @@ void fs_truncate(fs_node_t *file, uint32_t size); void fs_remove(fs_node_t *file); void fs_close(fs_node_t *node); - -void fs_unmount(fs_node_t *fs); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 264d2cd..465fc22 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -58,7 +58,6 @@ void kernel_main() { kernel->kernel_stack = kernel->kernel_rsp = (uint8_t *)memory_allocate(PAGE_SIZE) + PAGE_SIZE; kernel->user_stack = kernel->user_rsp = (uint8_t *)memory_allocate(PAGE_SIZE) + PAGE_SIZE; kernel->cwd = memory_allocate(sizeof(path_t)); - kernel->root = fs_mount(); kernel->fds[kernel->free_fd++] = keyboard_init(); kernel->fds[kernel->free_fd++] = vga_init(); kernel->code = EXIT_CODE_OK; @@ -66,8 +65,8 @@ void kernel_main() { current_process = kernel; tss.rsp0 = (uint64_t)kernel->kernel_stack; - fs_node_t *terminal_node = path_open_node(kernel->root, kernel->cwd, "bin/terminal", OPEN_FILE); - fs_node_t *shell_node = path_open_node(kernel->root, kernel->cwd, "bin/shell", OPEN_FILE); + fs_node_t *terminal_node = path_open_node(kernel->cwd, "bin/terminal", OPEN_FILE); + fs_node_t *shell_node = path_open_node(kernel->cwd, "bin/shell", OPEN_FILE); ASSERT(terminal_node, "kernel: terminal not found"); ASSERT(shell_node, "kernel: shell not found"); diff --git a/src/kernel/path.c b/src/kernel/path.c index 1db78e8..f426c14 100644 --- a/src/kernel/path.c +++ b/src/kernel/path.c @@ -6,7 +6,11 @@ #include "src/lib/syscall.h" #include "src/lib/util.h" -path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) { +path_t *path_open(const path_t *base, const char *path, uint64_t flags) { + if (!base || !path) { + return NUL; + } + uint64_t length = string_length(path); char *path_own = memory_allocate(length + 1); memory_copy(path, length + 1, path_own); @@ -16,23 +20,25 @@ path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, char *path_components[PATH_DEPTH]; uint8_t path_length = (uint8_t)string_split(path_own, '/', PATH_DEPTH, path_components); if (!string_empty(path_components[0])) { - for (uint8_t i = 0; i < source->depth; i++) { - result->stack[result->depth++] = fs_open_again(source->stack[i]); + for (uint8_t i = 0; i < base->depth; i++) { + result->stack[result->depth++] = fs_open_again(base->stack[i]); } } for (uint8_t i = 0; i < path_length; i++) { + if (!result->depth) { + result->stack[result->depth++] = fs_open_root(); + } + if (string_empty(path_components[i]) || string_equal(path_components[i], ".")) { continue; } else if (string_equal(path_components[i], "..")) { - if (result->depth) { + if (result->depth > 1) { fs_close(result->stack[--result->depth]); } } else { - const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : root; - fs_node_t *next = prev->is_dir ? fs_open_by(prev, path_components[i], - i < path_length - 1 ? (flags & ~(uint64_t)OPEN_EXCLUSIVE) | OPEN_DIRECTORY : flags) - : NUL; + fs_node_t *next = fs_open_by(result->stack[result->depth - 1], path_components[i], + i < path_length - 1 ? (flags & ~(uint64_t)OPEN_EXCLUSIVE) | OPEN_DIRECTORY : flags); if (!next || result->depth >= PATH_DEPTH) { path_close(result); memory_free(path_own); @@ -48,22 +54,35 @@ path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, return result; } -fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) { - path_t *p = path_open(root, source, path, flags); +path_t *path_open_again(const path_t *path) { + if (!path) { + return NUL; + } + + path_t *p = memory_allocate(sizeof(path_t)); + p->depth = path->depth; + for (uint8_t i = 0; i < path->depth; i++) { + p->stack[i] = fs_open_again(path->stack[i]); + } + return p; +} + +fs_node_t *path_open_node(const path_t *base, const char *path, uint64_t flags) { + path_t *p = path_open(base, path, flags); if (!p) { return NUL; } - fs_node_t *n = fs_open_again(p->depth ? p->stack[p->depth - 1] : root); + fs_node_t *n = fs_open_again(p->stack[p->depth - 1]); path_close(p); return n; } -stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) { - path_t *p = path_open(root, source, path, flags); +stream_t *path_open_stream(const path_t *base, const char *path, uint64_t flags) { + path_t *p = path_open(base, path, flags); if (!p) { return NUL; } - stream_t *s = fs_open_stream(p->depth ? p->stack[p->depth - 1] : root); + stream_t *s = fs_open_stream(p->stack[p->depth - 1]); path_close(p); return s; } @@ -74,12 +93,3 @@ void path_close(path_t *path) { } memory_free(path); } - -void path_remove(const fs_node_t *root, const path_t *source, const char *path) { - path_t *p = path_open(root, source, path, OPEN_FILE | OPEN_DIRECTORY); - if (!p || !p->depth) { - return; - } - fs_remove(p->stack[p->depth - 1]); - path_close(p); -} diff --git a/src/kernel/path.h b/src/kernel/path.h index 694cbc8..bc20f16 100644 --- a/src/kernel/path.h +++ b/src/kernel/path.h @@ -10,12 +10,12 @@ typedef struct { uint8_t depth; } path_t; -path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags); +path_t *path_open(const path_t *base, const char *path, uint64_t flags); -fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags); +path_t *path_open_again(const path_t *path); -stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags); +fs_node_t *path_open_node(const path_t *base, const char *path, uint64_t flags); -void path_close(path_t *path); +stream_t *path_open_stream(const path_t *base, const char *path, uint64_t flags); -void path_remove(const fs_node_t *root, const path_t *source, const char *path); +void path_close(path_t *path); diff --git a/src/kernel/process.c b/src/kernel/process.c index 0191c20..930c5a9 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -68,16 +68,9 @@ process_t *process_create(const process_t *parent, const uint8_t *code, uint64_t PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER); } - path_t *cwd = memory_allocate(sizeof(path_t)); - cwd->depth = parent->cwd->depth; - for (uint8_t i = 0; i < parent->cwd->depth; i++) { - cwd->stack[i] = fs_open_again(parent->cwd->stack[i]); - } - proc->pid = free_pid++; proc->state = PROCESS_RUNNING; - proc->cwd = cwd; - proc->root = parent->root; + proc->cwd = path_open_again(parent->cwd); proc->fds[0] = parent->fds[0]; proc->fds[1] = parent->fds[1]; proc->free_fd = 2; diff --git a/src/kernel/process.h b/src/kernel/process.h index 60e6a3d..190f061 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -1,6 +1,5 @@ #pragma once -#include "src/kernel/fs.h" #include "src/kernel/path.h" #include "src/kernel/stream.h" #include "src/lib/util.h" @@ -25,7 +24,6 @@ typedef struct process { uint64_t pid; process_state_t state; uint64_t waiting_for; - const fs_node_t *root; const path_t *cwd; stream_t *fds[MAX_FDS]; uint64_t free_fd; diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 072acd6..35387dd 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -80,7 +80,7 @@ static uint64_t getcwd(uint64_t max, char *to) { } static uint64_t chdir(const char *path) { - path_t *cwd = path_open(current_process->root, current_process->cwd, path, OPEN_DIRECTORY); + path_t *cwd = path_open(current_process->cwd, path, OPEN_DIRECTORY); if (!cwd) { return (uint64_t)-1; } @@ -90,7 +90,7 @@ static uint64_t chdir(const char *path) { } static uint64_t spawn(const char *path, uint64_t argc, const char **argv) { - fs_node_t *node = path_open_node(current_process->root, current_process->cwd, path, OPEN_FILE); + fs_node_t *node = path_open_node(current_process->cwd, path, OPEN_FILE); if (!node) { return EXIT_CODE_NOT_FOUND; } @@ -161,7 +161,7 @@ static uint64_t open(const char *path, uint64_t flags) { if (current_process->free_fd >= MAX_FDS) { return (uint64_t)-1; } - stream_t *stream = path_open_stream(current_process->root, current_process->cwd, path, flags); + stream_t *stream = path_open_stream(current_process->cwd, path, flags); if (!stream) { return (uint64_t)-1; } @@ -186,7 +186,9 @@ static uint64_t truncate(uint64_t fd, uint64_t size) { } static uint64_t remove(const char *path) { - path_remove(current_process->root, current_process->cwd, path); + fs_node_t *node = path_open_node(current_process->cwd, path, OPEN_FILE | OPEN_DIRECTORY); + fs_remove(node); + fs_close(node); return 0; }