Merge `fat16_inode_t` and `fat16_node_t`, make `fs_node_t` shared

master
Freywar Ulvnaudgari 6 days ago
parent 1ff38ffad4
commit 4ad32dda17
  1. 374
      src/kernel/fat16.c
  2. 8
      src/kernel/fat16.h
  3. 12
      src/kernel/fs.c
  4. 12
      src/kernel/fs.h
  5. 5
      src/kernel/kernel.c
  6. 56
      src/kernel/path.c
  7. 10
      src/kernel/path.h
  8. 9
      src/kernel/process.c
  9. 2
      src/kernel/process.h
  10. 10
      src/kernel/syscall.c

@ -34,87 +34,66 @@ 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;
uint16_t first_cluster;
} fat16_node_t;
#define MAX_NODES 256
static fat16_inode_t inodes[MAX_INODES];
static fat16_node_t nodes[MAX_NODES];
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];
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--;
}
}
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, &sector);
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;
static void node_free(fs_node_t *node) {
if (node->refs) {
node->refs--;
}
return fs = (fs_node_t *)node;
}
static void to_8_3(const char *name, char *output) {
@ -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, &sector);
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);
char name[FILENAME_SIZE_LIMIT + 1];
from_8_3(entry->name, entry->ext, 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;
}
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();
if (((fat16_node_t *)directory)->inode->removed) {
return node_use(0, UINT16_MAX, "", 1, 0, sizeof(fat16_dir_entry_t) * bpb->root_entry_count);
}
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) {
if (!directory || directory->type != FAT16 || !directory->is_dir || directory->removed) {
return NUL;
}
if (((fat16_node_t *)directory)->inode->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);
}

@ -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);

@ -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);
}

@ -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);

@ -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");

@ -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);
}

@ -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);

@ -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;

@ -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;

@ -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;
}

Loading…
Cancel
Save