Merge fat16_inode_t and fat16_node_t, make fs_node_t shared
This commit is contained in:
+188
-188
@@ -34,89 +34,68 @@ typedef struct __attribute__((packed)) {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
} fat16_dir_entry_t;
|
} 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 {
|
typedef struct {
|
||||||
uint32_t refs;
|
fs_node_t base;
|
||||||
uint16_t first_cluster;
|
|
||||||
uint32_t size;
|
|
||||||
uint16_t dir_cluster;
|
uint16_t dir_cluster;
|
||||||
uint16_t dir_index;
|
uint16_t dir_index;
|
||||||
uint8_t removed;
|
uint16_t first_cluster;
|
||||||
} fat16_inode_t;
|
} fat16_node_t;
|
||||||
|
|
||||||
static fat16_inode_t inodes[MAX_INODES];
|
#define MAX_NODES 256
|
||||||
|
|
||||||
static fat16_inode_t *inode_create(uint16_t first_cluster, uint32_t size, uint16_t dir_cluster, uint16_t dir_index) {
|
static fat16_node_t nodes[MAX_NODES];
|
||||||
for (uint64_t i = 0; i < MAX_INODES; i++) {
|
|
||||||
if (!inodes[i].refs) {
|
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,
|
||||||
inodes[i] = (fat16_inode_t){
|
uint32_t size) {
|
||||||
.refs = 1,
|
for (uint64_t i = 0; i < MAX_NODES; i++) {
|
||||||
.first_cluster = first_cluster,
|
if (!nodes[i].base.refs) {
|
||||||
.size = size,
|
nodes[i].base.type = FAT16;
|
||||||
.dir_cluster = dir_cluster,
|
nodes[i].base.refs = 1;
|
||||||
.dir_index = dir_index,
|
memory_copy(name, FILENAME_SIZE_LIMIT + 1, nodes[i].base.name);
|
||||||
};
|
nodes[i].base.size = size;
|
||||||
return &inodes[i];
|
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;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fat16_inode_t *inode_get(uint32_t dir_cluster, uint16_t dir_index) {
|
static fs_node_t *node_get(uint32_t dir_cluster, uint16_t dir_index) {
|
||||||
for (uint64_t i = 0; i < MAX_INODES; i++) {
|
for (uint64_t i = 0; i < MAX_NODES; i++) {
|
||||||
if (inodes[i].refs && inodes[i].dir_cluster == dir_cluster && inodes[i].dir_index == dir_index) {
|
if (nodes[i].base.refs && nodes[i].dir_cluster == dir_cluster && nodes[i].dir_index == dir_index) {
|
||||||
return &inodes[i];
|
return (fs_node_t *)&nodes[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fat16_inode_t *inode_use(uint16_t first_cluster, uint32_t size, uint16_t dir_cluster, uint16_t 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,
|
||||||
fat16_inode_t *result = inode_get(dir_cluster, dir_index);
|
uint32_t size) {
|
||||||
|
fs_node_t *result = node_get(dir_cluster, dir_index);
|
||||||
if (!result) {
|
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 {
|
} else {
|
||||||
|
ASSERT(result->refs < UINT32_MAX, "node_use: too many references");
|
||||||
result->refs++;
|
result->refs++;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inode_free(fat16_inode_t *inode) {
|
static void node_free(fs_node_t *node) {
|
||||||
if (inode->refs) {
|
if (node->refs) {
|
||||||
inode->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) {
|
static void to_8_3(const char *name, char *output) {
|
||||||
memory_set(' ', 11, output);
|
memory_set(' ', 11, output);
|
||||||
output[11] = '\0';
|
output[11] = '\0';
|
||||||
@@ -150,17 +129,35 @@ static void from_8_3(const char *name, const char *extension, char *output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ensure_fat() {
|
static void ensure_bpb() {
|
||||||
ASSERT(bpb.sectors_per_fat < 256, "ensure_fat: big FAT not implemented")
|
if (bpb) {
|
||||||
if (!fat) {
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
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() {
|
static uint16_t allocate_cluster() {
|
||||||
ensure_fat();
|
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) {
|
if (fat[i] == 0x0000) {
|
||||||
fat[i] = 0xFFFF;
|
fat[i] = 0xFFFF;
|
||||||
return i;
|
return i;
|
||||||
@@ -170,15 +167,18 @@ static uint16_t allocate_cluster() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void flush_fat() {
|
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) {
|
static uint16_t read_directory(uint16_t dir_cluster, fat16_dir_entry_t **entries) {
|
||||||
|
ensure_bpb();
|
||||||
|
|
||||||
if (!dir_cluster) {
|
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);
|
*entries = memory_allocate(sectors * SECTOR_SIZE);
|
||||||
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, sectors, *entries);
|
ata_read_sectors(FIRST_PARTITION_SECTOR + bpb->reserved_sectors + bpb->fats_count * bpb->sectors_per_fat, sectors, *entries);
|
||||||
return bpb.root_entry_count;
|
return bpb->root_entry_count;
|
||||||
} else {
|
} else {
|
||||||
ensure_fat();
|
ensure_fat();
|
||||||
|
|
||||||
@@ -188,19 +188,19 @@ static uint16_t read_directory(uint16_t dir_cluster, fat16_dir_entry_t **entries
|
|||||||
cluster_count++;
|
cluster_count++;
|
||||||
next_cluster = fat[next_cluster];
|
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;
|
uint8_t *chunk = (uint8_t *)*entries;
|
||||||
next_cluster = dir_cluster;
|
next_cluster = dir_cluster;
|
||||||
while (next_cluster < 0xFFF8) {
|
while (next_cluster < 0xFFF8) {
|
||||||
ata_read_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk);
|
ata_read_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, chunk);
|
||||||
chunk += bpb.sectors_per_cluster * SECTOR_SIZE;
|
chunk += bpb->sectors_per_cluster * SECTOR_SIZE;
|
||||||
next_cluster = fat[next_cluster];
|
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) {
|
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;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fat16_node_t *result = memory_allocate(sizeof(fat16_node_t));
|
char name[FILENAME_SIZE_LIMIT + 1];
|
||||||
result->base.type = FAT16;
|
from_8_3(entry->name, entry->ext, name);
|
||||||
from_8_3(entry->name, entry->ext, result->base.name);
|
|
||||||
|
|
||||||
result->base.size = entry->size;
|
return node_use(dir_cluster, index, name, entry->attributes & ATTRIBUTE_SUBDIRECTORY, entry->first_cluster, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_directory(uint16_t dir_cluster, const fat16_dir_entry_t *entries, uint16_t count) {
|
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");
|
"write_directory: entries must be aligned to clusters");
|
||||||
|
|
||||||
if (!dir_cluster) {
|
if (!dir_cluster) {
|
||||||
ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat,
|
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);
|
(uint8_t)((sizeof(fat16_dir_entry_t) * bpb->root_entry_count + SECTOR_SIZE - 1) / SECTOR_SIZE), entries);
|
||||||
} else {
|
} else {
|
||||||
ensure_fat();
|
ensure_fat();
|
||||||
|
|
||||||
uint8_t *chunk = (uint8_t *)entries;
|
uint8_t *chunk = (uint8_t *)entries;
|
||||||
uint16_t next_cluster = dir_cluster;
|
uint16_t next_cluster = dir_cluster;
|
||||||
while (count) {
|
while (count) {
|
||||||
ata_write_sectors(data_start + bpb.sectors_per_cluster * (next_cluster - 2), bpb.sectors_per_cluster, chunk);
|
ata_write_sectors(data_start + bpb->sectors_per_cluster * (next_cluster - 2), bpb->sectors_per_cluster, chunk);
|
||||||
chunk += bpb.sectors_per_cluster * SECTOR_SIZE;
|
chunk += bpb->sectors_per_cluster * SECTOR_SIZE;
|
||||||
count -= bpb.sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t);
|
count -= bpb->sectors_per_cluster * SECTOR_SIZE / sizeof(fat16_dir_entry_t);
|
||||||
if (count && fat[next_cluster] >= 0xFFF8) {
|
if (count && fat[next_cluster] >= 0xFFF8) {
|
||||||
fat[next_cluster] = allocate_cluster();
|
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_root() {
|
||||||
|
ensure_bpb();
|
||||||
|
|
||||||
|
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) {
|
fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name, uint64_t flags) {
|
||||||
if (directory->type != FAT16 || !directory->is_dir) {
|
if (!directory || directory->type != FAT16 || !directory->is_dir || directory->removed) {
|
||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((fat16_node_t *)directory)->inode->removed) {
|
uint16_t dir_cluster = ((fat16_node_t *)directory)->first_cluster;
|
||||||
return NUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
|
|
||||||
|
|
||||||
char name_8_3[12];
|
char name_8_3[12];
|
||||||
to_8_3(name, name_8_3);
|
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);
|
memory_free(entries);
|
||||||
return NUL;
|
return NUL;
|
||||||
} else {
|
} 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));
|
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_copy(entries, entries_count * sizeof(fat16_dir_entry_t), new_entries);
|
||||||
memory_free(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)) {
|
if (flags & OPEN_DIRECTORY && !(flags & OPEN_FILE)) {
|
||||||
entries[index].attributes = ATTRIBUTE_SUBDIRECTORY;
|
entries[index].attributes = ATTRIBUTE_SUBDIRECTORY;
|
||||||
entries[index].first_cluster = allocate_cluster();
|
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);
|
memory_copy(". ", 11, inner_entries[0].name);
|
||||||
inner_entries[0].attributes = ATTRIBUTE_SUBDIRECTORY;
|
inner_entries[0].attributes = ATTRIBUTE_SUBDIRECTORY;
|
||||||
inner_entries[0].first_cluster = entries[index].first_cluster;
|
inner_entries[0].first_cluster = entries[index].first_cluster;
|
||||||
memory_copy(".. ", 11, inner_entries[1].name);
|
memory_copy(".. ", 11, inner_entries[1].name);
|
||||||
inner_entries[1].attributes = ATTRIBUTE_SUBDIRECTORY;
|
inner_entries[1].attributes = ATTRIBUTE_SUBDIRECTORY;
|
||||||
inner_entries[1].first_cluster = dir_cluster;
|
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);
|
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) {
|
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;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((fat16_node_t *)directory)->inode->removed) {
|
uint16_t dir_cluster = ((fat16_node_t *)directory)->first_cluster;
|
||||||
return NUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
|
|
||||||
|
|
||||||
fat16_dir_entry_t *entries;
|
fat16_dir_entry_t *entries;
|
||||||
uint16_t entries_count = read_directory(dir_cluster, &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++;
|
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);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fat16_open_again(const fs_node_t *source) {
|
fs_node_t *fat16_open_again(fs_node_t *source) {
|
||||||
fs_node_t *result = memory_allocate(sizeof(fat16_node_t));
|
ASSERT(source->refs < UINT32_MAX, "fat16_open_again: too many references");
|
||||||
memory_copy(source, sizeof(fat16_node_t), result);
|
source->refs++;
|
||||||
((fat16_node_t *)result)->inode->refs++;
|
return source;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t fat16_read(const fs_node_t *file, uint32_t offset, uint32_t bytes, void *to) {
|
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 (!file || file->type != FAT16 || file->is_dir) {
|
||||||
|
|
||||||
if (fat_file->base.type != FAT16 || fat_file->base.is_dir) {
|
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fat_file->inode->removed) {
|
if (file->removed) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset >= fat_file->inode->size) {
|
if (offset >= file->size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset + bytes >= fat_file->inode->size) {
|
if (offset + bytes >= file->size) {
|
||||||
bytes = fat_file->inode->size - offset;
|
bytes = file->size - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_fat();
|
ensure_fat();
|
||||||
|
|
||||||
uint32_t cluster_size = bpb.sectors_per_cluster * SECTOR_SIZE;
|
uint32_t cluster_size = bpb->sectors_per_cluster * SECTOR_SIZE;
|
||||||
uint32_t next_cluster = fat_file->inode->first_cluster;
|
uint32_t next_cluster = ((fat16_node_t *)file)->first_cluster;
|
||||||
|
|
||||||
while (offset >= cluster_size) {
|
while (offset >= cluster_size) {
|
||||||
next_cluster = fat[next_cluster];
|
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 *cursor = to;
|
||||||
|
|
||||||
uint8_t *tmp = memory_allocate(cluster_size);
|
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;
|
uint32_t prefix_size = bytes <= cluster_size - offset ? bytes : cluster_size - offset;
|
||||||
memory_copy(tmp + offset, prefix_size, cursor);
|
memory_copy(tmp + offset, prefix_size, cursor);
|
||||||
bytes -= prefix_size;
|
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];
|
next_cluster = fat[next_cluster];
|
||||||
|
|
||||||
while (bytes >= cluster_size) {
|
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;
|
bytes -= cluster_size;
|
||||||
readden += cluster_size;
|
readden += cluster_size;
|
||||||
cursor += 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) {
|
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);
|
memory_copy(tmp, bytes, cursor);
|
||||||
readden += bytes;
|
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) {
|
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 (!file || file->type != FAT16 || file->is_dir) {
|
||||||
|
|
||||||
if (fat_file->base.type != FAT16 || fat_file->base.is_dir) {
|
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fat_file->inode->removed) {
|
if (file->removed) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_fat();
|
ensure_fat();
|
||||||
|
|
||||||
if (!fat_file->inode->first_cluster) {
|
fat16_node_t *fat_file = (fat16_node_t *)file;
|
||||||
fat_file->inode->first_cluster = allocate_cluster();
|
|
||||||
|
if (!fat_file->first_cluster) {
|
||||||
|
fat_file->first_cluster = allocate_cluster();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t cluster_size = bpb.sectors_per_cluster * SECTOR_SIZE;
|
uint32_t cluster_size = bpb->sectors_per_cluster * SECTOR_SIZE;
|
||||||
uint32_t next_cluster = fat_file->inode->first_cluster;
|
uint32_t next_cluster = fat_file->first_cluster;
|
||||||
|
|
||||||
uint32_t allocated = cluster_size;
|
uint32_t allocated = cluster_size;
|
||||||
while (allocated < offset + bytes) {
|
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();
|
flush_fat();
|
||||||
|
|
||||||
cluster_size = bpb.sectors_per_cluster * SECTOR_SIZE;
|
cluster_size = bpb->sectors_per_cluster * SECTOR_SIZE;
|
||||||
next_cluster = fat_file->inode->first_cluster;
|
next_cluster = fat_file->first_cluster;
|
||||||
|
|
||||||
while (offset >= cluster_size) {
|
while (offset >= cluster_size) {
|
||||||
next_cluster = fat[next_cluster];
|
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;
|
const uint8_t *cursor = from;
|
||||||
|
|
||||||
uint8_t *tmp = memory_allocate(cluster_size);
|
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;
|
uint32_t prefix_size = bytes <= cluster_size - offset ? bytes : cluster_size - offset;
|
||||||
memory_copy(cursor, prefix_size, tmp + 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;
|
bytes -= prefix_size;
|
||||||
written += prefix_size;
|
written += prefix_size;
|
||||||
cursor += prefix_size;
|
cursor += prefix_size;
|
||||||
next_cluster = fat[next_cluster];
|
next_cluster = fat[next_cluster];
|
||||||
|
|
||||||
while (bytes >= cluster_size) {
|
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;
|
bytes -= cluster_size;
|
||||||
written += cluster_size;
|
written += cluster_size;
|
||||||
cursor += 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) {
|
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);
|
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;
|
written += bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_free(tmp);
|
memory_free(tmp);
|
||||||
|
|
||||||
if (offset + written > fat_file->inode->size) {
|
if (offset + written > file->size) {
|
||||||
fat_file->inode->size = offset + written;
|
file->size = offset + written;
|
||||||
|
|
||||||
fat16_dir_entry_t *entries;
|
fat16_dir_entry_t *entries;
|
||||||
uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries);
|
uint16_t entries_count = read_directory(fat_file->dir_cluster, &entries);
|
||||||
entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster;
|
entries[fat_file->dir_index].first_cluster = fat_file->first_cluster;
|
||||||
entries[fat_file->inode->dir_index].size = fat_file->inode->size;
|
entries[fat_file->dir_index].size = file->size;
|
||||||
write_directory(fat_file->inode->dir_cluster, entries, entries_count);
|
write_directory(fat_file->dir_cluster, entries, entries_count);
|
||||||
memory_free(entries);
|
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) {
|
uint64_t fat16_truncate(fs_node_t *file, uint32_t size) {
|
||||||
fat16_node_t *fat_file = (fat16_node_t *)file;
|
if (!file || file->type != FAT16 || file->is_dir) {
|
||||||
|
|
||||||
if (fat_file->base.type != FAT16 || fat_file->base.is_dir) {
|
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fat_file->inode->removed) {
|
if (file->removed) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,9 +547,11 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) {
|
|||||||
memory_free(tmp);
|
memory_free(tmp);
|
||||||
return written == (uint64_t)-1 ? (uint64_t)-1 : file->size + written;
|
return written == (uint64_t)-1 ? (uint64_t)-1 : file->size + written;
|
||||||
} else if (file->size > size) {
|
} 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 prev_cluster = 0;
|
||||||
uint32_t next_cluster = fat_file->inode->first_cluster;
|
uint32_t next_cluster = fat_file->first_cluster;
|
||||||
|
|
||||||
ensure_fat();
|
ensure_fat();
|
||||||
uint32_t allocated = 0;
|
uint32_t allocated = 0;
|
||||||
@@ -576,7 +563,7 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) {
|
|||||||
if (prev_cluster) {
|
if (prev_cluster) {
|
||||||
fat[prev_cluster] = 0xFFFF;
|
fat[prev_cluster] = 0xFFFF;
|
||||||
} else {
|
} else {
|
||||||
fat_file->inode->first_cluster = 0;
|
fat_file->first_cluster = 0;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
uint32_t swap = fat[next_cluster];
|
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);
|
} while (next_cluster < 0xFFF8);
|
||||||
flush_fat();
|
flush_fat();
|
||||||
|
|
||||||
fat_file->inode->size = size;
|
file->size = size;
|
||||||
fat16_dir_entry_t *entries;
|
fat16_dir_entry_t *entries;
|
||||||
uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries);
|
uint16_t entries_count = read_directory(fat_file->dir_cluster, &entries);
|
||||||
entries[fat_file->inode->dir_index].first_cluster = fat_file->inode->first_cluster;
|
entries[fat_file->dir_index].first_cluster = fat_file->first_cluster;
|
||||||
entries[fat_file->inode->dir_index].size = fat_file->inode->size;
|
entries[fat_file->dir_index].size = file->size;
|
||||||
write_directory(fat_file->inode->dir_cluster, entries, entries_count);
|
write_directory(fat_file->dir_cluster, entries, entries_count);
|
||||||
memory_free(entries);
|
memory_free(entries);
|
||||||
|
|
||||||
return size;
|
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) {
|
uint64_t fat16_remove(fs_node_t *file) {
|
||||||
fat16_node_t *fat_file = (fat16_node_t *)file;
|
if (!file || file->type != FAT16) {
|
||||||
|
|
||||||
if (fat_file->base.type != FAT16) {
|
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fat_file->inode->removed) {
|
if (file->removed) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fat16_node_t *fat_file = (fat16_node_t *)file;
|
||||||
|
|
||||||
if (file->is_dir) {
|
if (file->is_dir) {
|
||||||
fat16_dir_entry_t *subentries;
|
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;
|
uint16_t ei = 0, vi = 0;
|
||||||
while (ei < subentries_count && subentries[ei].name[0]) {
|
while (ei < subentries_count && subentries[ei].name[0]) {
|
||||||
if ((uint8_t)subentries[ei].name[0] != 0xE5 && (uint8_t)subentries[ei].attributes != 0x0F) {
|
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();
|
ensure_fat();
|
||||||
uint64_t next_cluster = fat_file->inode->first_cluster;
|
uint64_t next_cluster = fat_file->first_cluster;
|
||||||
do {
|
do {
|
||||||
uint32_t swap = fat[next_cluster];
|
uint32_t swap = fat[next_cluster];
|
||||||
fat[next_cluster] = 0;
|
fat[next_cluster] = 0;
|
||||||
@@ -639,11 +626,11 @@ uint64_t fat16_remove(fs_node_t *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fat16_dir_entry_t *entries;
|
fat16_dir_entry_t *entries;
|
||||||
uint16_t entries_count = read_directory(fat_file->inode->dir_cluster, &entries);
|
uint16_t entries_count = read_directory(fat_file->dir_cluster, &entries);
|
||||||
entries[fat_file->inode->dir_index].name[0] = 0xE5;
|
entries[fat_file->dir_index].name[0] = 0xE5;
|
||||||
entries[fat_file->inode->dir_index].first_cluster = 0;
|
entries[fat_file->dir_index].first_cluster = 0;
|
||||||
entries[fat_file->inode->dir_index].size = 0;
|
entries[fat_file->dir_index].size = 0;
|
||||||
write_directory(fat_file->inode->dir_cluster, entries, entries_count);
|
write_directory(fat_file->dir_cluster, entries, entries_count);
|
||||||
memory_free(entries);
|
memory_free(entries);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -656,6 +643,10 @@ typedef struct {
|
|||||||
} fat16_file_stream_t;
|
} fat16_file_stream_t;
|
||||||
|
|
||||||
static uint64_t file_stream_write(stream_t *self, const char *from, uint64_t bytes) {
|
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;
|
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);
|
uint64_t written = fat16_write(ffs->node, ffs->offset, from, bytes > UINT32_MAX ? UINT32_MAX : (uint32_t)bytes);
|
||||||
if (written != (uint64_t)-1) {
|
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) {
|
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;
|
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);
|
uint64_t readden = fat16_read(ffs->node, ffs->offset, max > UINT32_MAX ? UINT32_MAX : (uint32_t)max, to);
|
||||||
if (readden != (uint64_t)-1) {
|
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) {
|
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;
|
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);
|
uint64_t resized = fat16_truncate(ffs->node, size > UINT32_MAX ? UINT32_MAX : (uint32_t)size);
|
||||||
if (resized != (uint64_t)-1 && resized < ffs->offset) {
|
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) {
|
static void file_stream_close(stream_t *self) {
|
||||||
|
if (!self) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fat16_file_stream_t *ffs = (fat16_file_stream_t *)self;
|
fat16_file_stream_t *ffs = (fat16_file_stream_t *)self;
|
||||||
fat16_close(ffs->node);
|
fat16_close(ffs->node);
|
||||||
memory_free(self);
|
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) {
|
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;
|
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);
|
fs_node_t *node = fat16_open_at(fds->node, fds->index++, OPEN_FILE | OPEN_DIRECTORY);
|
||||||
if (!node) {
|
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) {
|
static void directory_stream_close(stream_t *self) {
|
||||||
|
if (!self) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fat16_directory_stream_t *fds = (fat16_directory_stream_t *)self;
|
fat16_directory_stream_t *fds = (fat16_directory_stream_t *)self;
|
||||||
fat16_close(fds->node);
|
fat16_close(fds->node);
|
||||||
memory_free(self);
|
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) {
|
if (!source->is_dir) {
|
||||||
fat16_file_stream_t *result = memory_allocate(sizeof(fat16_file_stream_t));
|
fat16_file_stream_t *result = memory_allocate(sizeof(fat16_file_stream_t));
|
||||||
result->stream.read = file_stream_read;
|
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) {
|
void fat16_close(fs_node_t *node) {
|
||||||
if (node->type != FAT16 || node == fs) {
|
if (!node || node->type != FAT16) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inode_free(((fat16_node_t *)node)->inode);
|
|
||||||
memory_free(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fat16_unmount(fs_node_t *node) {
|
node_free(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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -5,15 +5,15 @@
|
|||||||
|
|
||||||
#define FAT16 1
|
#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_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_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);
|
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);
|
uint64_t fat16_remove(fs_node_t *file);
|
||||||
|
|
||||||
void fat16_close(fs_node_t *node);
|
void fat16_close(fs_node_t *node);
|
||||||
|
|
||||||
void fat16_unmount(fs_node_t *fs);
|
|
||||||
|
|||||||
+4
-8
@@ -1,8 +1,8 @@
|
|||||||
#include "src/kernel/fs.h"
|
#include "src/kernel/fs.h"
|
||||||
#include "src/kernel/fat16.h"
|
#include "src/kernel/fat16.h"
|
||||||
|
|
||||||
fs_node_t *fs_mount() {
|
fs_node_t *fs_open_root() {
|
||||||
return fat16_mount();
|
return fat16_open_root();
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name, uint64_t flags) {
|
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);
|
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);
|
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);
|
return fat16_open_stream(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,3 @@ void fs_remove(fs_node_t *file) {
|
|||||||
void fs_close(fs_node_t *node) {
|
void fs_close(fs_node_t *node) {
|
||||||
fat16_close(node);
|
fat16_close(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fs_unmount(fs_node_t *fs) {
|
|
||||||
fat16_unmount(fs);
|
|
||||||
}
|
|
||||||
|
|||||||
+6
-6
@@ -5,21 +5,23 @@
|
|||||||
#define FILENAME_SIZE_LIMIT 255
|
#define FILENAME_SIZE_LIMIT 255
|
||||||
|
|
||||||
typedef struct fs_node {
|
typedef struct fs_node {
|
||||||
|
uint8_t type;
|
||||||
|
uint32_t refs;
|
||||||
char name[FILENAME_SIZE_LIMIT + 1];
|
char name[FILENAME_SIZE_LIMIT + 1];
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint8_t is_dir;
|
uint8_t is_dir;
|
||||||
uint8_t type;
|
uint8_t removed;
|
||||||
} fs_node_t;
|
} 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_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_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);
|
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_remove(fs_node_t *file);
|
||||||
|
|
||||||
void fs_close(fs_node_t *node);
|
void fs_close(fs_node_t *node);
|
||||||
|
|
||||||
void fs_unmount(fs_node_t *fs);
|
|
||||||
|
|||||||
+2
-3
@@ -58,7 +58,6 @@ void kernel_main() {
|
|||||||
kernel->kernel_stack = kernel->kernel_rsp = (uint8_t *)memory_allocate(PAGE_SIZE) + PAGE_SIZE;
|
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->user_stack = kernel->user_rsp = (uint8_t *)memory_allocate(PAGE_SIZE) + PAGE_SIZE;
|
||||||
kernel->cwd = memory_allocate(sizeof(path_t));
|
kernel->cwd = memory_allocate(sizeof(path_t));
|
||||||
kernel->root = fs_mount();
|
|
||||||
kernel->fds[kernel->free_fd++] = keyboard_init();
|
kernel->fds[kernel->free_fd++] = keyboard_init();
|
||||||
kernel->fds[kernel->free_fd++] = vga_init();
|
kernel->fds[kernel->free_fd++] = vga_init();
|
||||||
kernel->code = EXIT_CODE_OK;
|
kernel->code = EXIT_CODE_OK;
|
||||||
@@ -66,8 +65,8 @@ void kernel_main() {
|
|||||||
current_process = kernel;
|
current_process = kernel;
|
||||||
tss.rsp0 = (uint64_t)kernel->kernel_stack;
|
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 *terminal_node = path_open_node(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 *shell_node = path_open_node(kernel->cwd, "bin/shell", OPEN_FILE);
|
||||||
|
|
||||||
ASSERT(terminal_node, "kernel: terminal not found");
|
ASSERT(terminal_node, "kernel: terminal not found");
|
||||||
ASSERT(shell_node, "kernel: shell not found");
|
ASSERT(shell_node, "kernel: shell not found");
|
||||||
|
|||||||
+33
-23
@@ -6,7 +6,11 @@
|
|||||||
#include "src/lib/syscall.h"
|
#include "src/lib/syscall.h"
|
||||||
#include "src/lib/util.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);
|
uint64_t length = string_length(path);
|
||||||
char *path_own = memory_allocate(length + 1);
|
char *path_own = memory_allocate(length + 1);
|
||||||
memory_copy(path, length + 1, path_own);
|
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];
|
char *path_components[PATH_DEPTH];
|
||||||
uint8_t path_length = (uint8_t)string_split(path_own, '/', PATH_DEPTH, path_components);
|
uint8_t path_length = (uint8_t)string_split(path_own, '/', PATH_DEPTH, path_components);
|
||||||
if (!string_empty(path_components[0])) {
|
if (!string_empty(path_components[0])) {
|
||||||
for (uint8_t i = 0; i < source->depth; i++) {
|
for (uint8_t i = 0; i < base->depth; i++) {
|
||||||
result->stack[result->depth++] = fs_open_again(source->stack[i]);
|
result->stack[result->depth++] = fs_open_again(base->stack[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < path_length; 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], ".")) {
|
if (string_empty(path_components[i]) || string_equal(path_components[i], ".")) {
|
||||||
continue;
|
continue;
|
||||||
} else if (string_equal(path_components[i], "..")) {
|
} else if (string_equal(path_components[i], "..")) {
|
||||||
if (result->depth) {
|
if (result->depth > 1) {
|
||||||
fs_close(result->stack[--result->depth]);
|
fs_close(result->stack[--result->depth]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : root;
|
fs_node_t *next = fs_open_by(result->stack[result->depth - 1], path_components[i],
|
||||||
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);
|
||||||
i < path_length - 1 ? (flags & ~(uint64_t)OPEN_EXCLUSIVE) | OPEN_DIRECTORY : flags)
|
|
||||||
: NUL;
|
|
||||||
if (!next || result->depth >= PATH_DEPTH) {
|
if (!next || result->depth >= PATH_DEPTH) {
|
||||||
path_close(result);
|
path_close(result);
|
||||||
memory_free(path_own);
|
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;
|
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 *path_open_again(const path_t *path) {
|
||||||
path_t *p = path_open(root, source, path, flags);
|
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) {
|
if (!p) {
|
||||||
return NUL;
|
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);
|
path_close(p);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) {
|
stream_t *path_open_stream(const path_t *base, const char *path, uint64_t flags) {
|
||||||
path_t *p = path_open(root, source, path, flags);
|
path_t *p = path_open(base, path, flags);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
return NUL;
|
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);
|
path_close(p);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -74,12 +93,3 @@ void path_close(path_t *path) {
|
|||||||
}
|
}
|
||||||
memory_free(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);
|
|
||||||
}
|
|
||||||
|
|||||||
+5
-5
@@ -10,12 +10,12 @@ typedef struct {
|
|||||||
uint8_t depth;
|
uint8_t depth;
|
||||||
} path_t;
|
} 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);
|
||||||
|
|
||||||
|
stream_t *path_open_stream(const path_t *base, const char *path, uint64_t flags);
|
||||||
|
|
||||||
void path_close(path_t *path);
|
void path_close(path_t *path);
|
||||||
|
|
||||||
void path_remove(const fs_node_t *root, const path_t *source, const char *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);
|
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->pid = free_pid++;
|
||||||
proc->state = PROCESS_RUNNING;
|
proc->state = PROCESS_RUNNING;
|
||||||
proc->cwd = cwd;
|
proc->cwd = path_open_again(parent->cwd);
|
||||||
proc->root = parent->root;
|
|
||||||
proc->fds[0] = parent->fds[0];
|
proc->fds[0] = parent->fds[0];
|
||||||
proc->fds[1] = parent->fds[1];
|
proc->fds[1] = parent->fds[1];
|
||||||
proc->free_fd = 2;
|
proc->free_fd = 2;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/kernel/fs.h"
|
|
||||||
#include "src/kernel/path.h"
|
#include "src/kernel/path.h"
|
||||||
#include "src/kernel/stream.h"
|
#include "src/kernel/stream.h"
|
||||||
#include "src/lib/util.h"
|
#include "src/lib/util.h"
|
||||||
@@ -25,7 +24,6 @@ typedef struct process {
|
|||||||
uint64_t pid;
|
uint64_t pid;
|
||||||
process_state_t state;
|
process_state_t state;
|
||||||
uint64_t waiting_for;
|
uint64_t waiting_for;
|
||||||
const fs_node_t *root;
|
|
||||||
const path_t *cwd;
|
const path_t *cwd;
|
||||||
stream_t *fds[MAX_FDS];
|
stream_t *fds[MAX_FDS];
|
||||||
uint64_t free_fd;
|
uint64_t free_fd;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ static uint64_t getcwd(uint64_t max, char *to) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t chdir(const char *path) {
|
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) {
|
if (!cwd) {
|
||||||
return (uint64_t)-1;
|
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) {
|
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) {
|
if (!node) {
|
||||||
return EXIT_CODE_NOT_FOUND;
|
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) {
|
if (current_process->free_fd >= MAX_FDS) {
|
||||||
return (uint64_t)-1;
|
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) {
|
if (!stream) {
|
||||||
return (uint64_t)-1;
|
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) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user