Add file and directory creation, mkdir
This commit is contained in:
@@ -22,3 +22,4 @@ mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/echo ::bin/ec
|
|||||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/ls ::bin/ls
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/ls ::bin/ls
|
||||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cat ::bin/cat
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cat ::bin/cat
|
||||||
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cp ::bin/cp
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/cp ::bin/cp
|
||||||
|
mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/mkdir ::bin/mkdir
|
||||||
|
|||||||
+39
@@ -349,3 +349,42 @@ custom_target(
|
|||||||
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||||
build_by_default: true,
|
build_by_default: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
mkdir_start = custom_target(
|
||||||
|
'mkdir_start',
|
||||||
|
input: 'src/user/start.asm',
|
||||||
|
output: 'mkdir_start.o',
|
||||||
|
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
mkdir_syscall = custom_target(
|
||||||
|
'mkdir_syscall',
|
||||||
|
input: 'src/user/syscall.asm',
|
||||||
|
output: 'mkdir_syscall.o',
|
||||||
|
command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'],
|
||||||
|
)
|
||||||
|
|
||||||
|
mkdir_elf = executable(
|
||||||
|
'mkdir.elf',
|
||||||
|
sources: [mkdir_start, mkdir_syscall, lib_sources, 'src/user/app/mkdir/mkdir.c'],
|
||||||
|
c_args: [
|
||||||
|
'-ffreestanding',
|
||||||
|
'-nostdlib',
|
||||||
|
'-fno-stack-protector',
|
||||||
|
'-mcmodel=large',
|
||||||
|
'-DVERSION="' + meson.project_version() + '"',
|
||||||
|
],
|
||||||
|
link_args: [
|
||||||
|
'-T', meson.project_source_root() / 'src/user/linker.ld',
|
||||||
|
'-nostdlib',
|
||||||
|
],
|
||||||
|
link_depends: 'src/user/linker.ld',
|
||||||
|
)
|
||||||
|
|
||||||
|
custom_target(
|
||||||
|
'mkdir',
|
||||||
|
input: mkdir_elf,
|
||||||
|
output: 'mkdir',
|
||||||
|
command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'],
|
||||||
|
build_by_default: true,
|
||||||
|
)
|
||||||
|
|||||||
+118
-26
@@ -5,6 +5,7 @@
|
|||||||
#include "src/kernel/stream.h"
|
#include "src/kernel/stream.h"
|
||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
#include "src/lib/string.h"
|
#include "src/lib/string.h"
|
||||||
|
#include "src/lib/syscall.h"
|
||||||
#include "src/lib/util.h"
|
#include "src/lib/util.h"
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
@@ -179,35 +180,34 @@ static void flush_fat() {
|
|||||||
ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat);
|
ata_write_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors, (uint8_t)bpb.sectors_per_fat, fat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fat16_dir_entry_t *read_directory(uint16_t dir_cluster) {
|
static uint16_t read_directory(uint16_t dir_cluster, fat16_dir_entry_t **entries) {
|
||||||
fat16_dir_entry_t *entries;
|
|
||||||
|
|
||||||
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 + sizeof(fat16_dir_entry_t)); // One extra as null terminator.
|
*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;
|
||||||
} else {
|
} else {
|
||||||
ensure_fat();
|
ensure_fat();
|
||||||
|
|
||||||
uint16_t next_cluster = dir_cluster;
|
uint16_t next_cluster = dir_cluster;
|
||||||
uint32_t cluster_count = 0;
|
uint16_t cluster_count = 0;
|
||||||
while (next_cluster < 0xFFF8) {
|
while (next_cluster < 0xFFF8) {
|
||||||
cluster_count++;
|
cluster_count++;
|
||||||
next_cluster = fat[next_cluster];
|
next_cluster = fat[next_cluster];
|
||||||
}
|
}
|
||||||
entries =
|
*entries = memory_allocate(cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE);
|
||||||
memory_allocate(cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE + sizeof(fat16_dir_entry_t)); // One extra as null terminator.
|
|
||||||
|
|
||||||
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 entries;
|
return (uint64_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) {
|
||||||
@@ -233,37 +233,47 @@ static fs_node_t *open_entry(uint16_t dir_cluster, const fat16_dir_entry_t *entr
|
|||||||
return (fs_node_t *)result;
|
return (fs_node_t *)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_directory(uint16_t dir_cluster, const fat16_dir_entry_t *entries) {
|
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,
|
||||||
|
"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();
|
||||||
|
|
||||||
// Assuming no entries were added or removed.
|
|
||||||
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 (next_cluster < 0xFFF8) {
|
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);
|
||||||
|
if (count && fat[next_cluster] >= 0xFFF8) {
|
||||||
|
fat[next_cluster] = allocate_cluster();
|
||||||
|
}
|
||||||
next_cluster = fat[next_cluster];
|
next_cluster = fat[next_cluster];
|
||||||
}
|
}
|
||||||
|
flush_fat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name) {
|
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->type != FAT16 || !directory->is_dir) {
|
||||||
return NUL;
|
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);
|
||||||
|
|
||||||
fat16_dir_entry_t *entries = read_directory(((fat16_node_t *)directory)->inode->first_cluster);
|
fat16_dir_entry_t *entries;
|
||||||
|
uint16_t entries_count = read_directory(dir_cluster, &entries);
|
||||||
|
|
||||||
fat16_dir_entry_t *entry = entries;
|
fat16_dir_entry_t *entry = entries;
|
||||||
uint16_t index = 0;
|
uint16_t index = 0;
|
||||||
while (entry->name[0]) {
|
while (index < entries_count && entry->name[0]) {
|
||||||
if ((uint8_t)entry->name[0] != 0xE5 && (uint8_t)entry->attributes != 0x0F && bytes_equal(name_8_3, (char *)entry, 11)) {
|
if ((uint8_t)entry->name[0] != 0xE5 && (uint8_t)entry->attributes != 0x0F && bytes_equal(name_8_3, (char *)entry, 11)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -271,20 +281,82 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name) {
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *result = open_entry(((fat16_node_t *)directory)->inode->first_cluster, entries, index);
|
fs_node_t *result = open_entry(dir_cluster, entries, index);
|
||||||
|
|
||||||
|
if (result && (flags & OPEN_EXCLUSIVE)) {
|
||||||
|
memory_free(entries);
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result && (flags & OPEN_CREATE)) {
|
||||||
|
index = 0;
|
||||||
|
while (index < entries_count && entries[index].name[0]) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (index >= entries_count) {
|
||||||
|
if (!dir_cluster) {
|
||||||
|
memory_free(entries);
|
||||||
|
return NUL;
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
entries_count = new_entries_count;
|
||||||
|
entries = new_entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_copy(name_8_3, 11, &entries[index]);
|
||||||
|
|
||||||
|
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);
|
||||||
|
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));
|
||||||
|
memory_free(inner_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_directory(dir_cluster, entries, entries_count);
|
||||||
|
|
||||||
|
result = open_entry(dir_cluster, entries, index);
|
||||||
|
}
|
||||||
|
|
||||||
memory_free(entries);
|
memory_free(entries);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->is_dir && !(flags & OPEN_DIRECTORY)) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result->is_dir && !(flags & OPEN_FILE)) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index) {
|
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->type != FAT16 || !directory->is_dir) {
|
||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fat16_dir_entry_t *entries = read_directory(((fat16_node_t *)directory)->inode->first_cluster);
|
uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster;
|
||||||
|
|
||||||
|
fat16_dir_entry_t *entries;
|
||||||
|
uint16_t entries_count = read_directory(dir_cluster, &entries);
|
||||||
|
|
||||||
uint16_t ei = 0, vi = 0;
|
uint16_t ei = 0, vi = 0;
|
||||||
while (entries[ei].name[0]) {
|
while (ei < entries_count && entries[ei].name[0]) {
|
||||||
if ((uint8_t)entries[ei].name[0] != 0xE5 && (uint8_t)entries[ei].attributes != 0x0F) {
|
if ((uint8_t)entries[ei].name[0] != 0xE5 && (uint8_t)entries[ei].attributes != 0x0F) {
|
||||||
if (vi == index) {
|
if (vi == index) {
|
||||||
break;
|
break;
|
||||||
@@ -295,7 +367,25 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *result = open_entry(((fat16_node_t *)directory)->inode->first_cluster, entries, ei);
|
fs_node_t *result = open_entry(((fat16_node_t *)directory)->inode->first_cluster, entries, ei);
|
||||||
|
|
||||||
memory_free(entries);
|
memory_free(entries);
|
||||||
|
|
||||||
|
if (result && (flags & OPEN_EXCLUSIVE)) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->is_dir && !(flags & OPEN_DIRECTORY)) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result->is_dir && !(flags & OPEN_FILE)) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,10 +522,11 @@ uint64_t fat16_write(fs_node_t *file, uint32_t offset, const void *from, uint32_
|
|||||||
if (offset + written > fat_file->inode->size) {
|
if (offset + written > fat_file->inode->size) {
|
||||||
fat_file->inode->size = offset + written;
|
fat_file->inode->size = offset + written;
|
||||||
|
|
||||||
fat16_dir_entry_t *entries = read_directory(fat_file->inode->dir_cluster);
|
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].first_cluster = fat_file->inode->first_cluster;
|
||||||
entries[fat_file->inode->dir_index].size = fat_file->inode->size;
|
entries[fat_file->inode->dir_index].size = fat_file->inode->size;
|
||||||
write_directory(fat_file->inode->dir_cluster, entries);
|
write_directory(fat_file->inode->dir_cluster, entries, entries_count);
|
||||||
memory_free(entries);
|
memory_free(entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,10 +573,11 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) {
|
|||||||
flush_fat();
|
flush_fat();
|
||||||
|
|
||||||
fat_file->inode->size = size;
|
fat_file->inode->size = size;
|
||||||
fat16_dir_entry_t *entries = read_directory(fat_file->inode->dir_cluster);
|
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].first_cluster = fat_file->inode->first_cluster;
|
||||||
entries[fat_file->inode->dir_index].size = fat_file->inode->size;
|
entries[fat_file->inode->dir_index].size = fat_file->inode->size;
|
||||||
write_directory(fat_file->inode->dir_cluster, entries);
|
write_directory(fat_file->inode->dir_cluster, entries, entries_count);
|
||||||
memory_free(entries);
|
memory_free(entries);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
@@ -535,7 +627,7 @@ static void file_stream_close(stream_t *self) {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
stream_t stream;
|
stream_t stream;
|
||||||
fs_node_t *node;
|
fs_node_t *node;
|
||||||
uint32_t index;
|
uint16_t index;
|
||||||
} fat16_directory_stream_t;
|
} fat16_directory_stream_t;
|
||||||
|
|
||||||
static uint64_t directory_stream_write(__attribute__((unused)) stream_t *self, __attribute__((unused)) const char *from,
|
static uint64_t directory_stream_write(__attribute__((unused)) stream_t *self, __attribute__((unused)) const char *from,
|
||||||
@@ -545,7 +637,7 @@ 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) {
|
||||||
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++);
|
fs_node_t *node = fat16_open_at(fds->node, fds->index++, OPEN_FILE | OPEN_DIRECTORY);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
fs_node_t *fat16_mount();
|
fs_node_t *fat16_mount();
|
||||||
|
|
||||||
fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name);
|
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, uint64_t index);
|
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(const fs_node_t *source);
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -5,12 +5,12 @@ fs_node_t *fs_mount() {
|
|||||||
return fat16_mount();
|
return fat16_mount();
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name) {
|
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name, uint64_t flags) {
|
||||||
return fat16_open_by(directory, name);
|
return fat16_open_by(directory, name, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fs_open_at(const fs_node_t *directory, uint64_t index) {
|
fs_node_t *fs_open_at(const fs_node_t *directory, uint16_t index, uint64_t flags) {
|
||||||
return fat16_open_at(directory, index);
|
return fat16_open_at(directory, index, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *fs_open_again(const fs_node_t *source) {
|
fs_node_t *fs_open_again(const fs_node_t *source) {
|
||||||
|
|||||||
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/kernel/stream.h"
|
#include "src/kernel/stream.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define FILENAME_SIZE_LIMIT 255
|
#define FILENAME_SIZE_LIMIT 255
|
||||||
|
|
||||||
@@ -14,9 +13,9 @@ typedef struct fs_node {
|
|||||||
|
|
||||||
fs_node_t *fs_mount();
|
fs_node_t *fs_mount();
|
||||||
|
|
||||||
fs_node_t *fs_open_by(const fs_node_t *directory, const char *name);
|
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, uint64_t index);
|
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(const fs_node_t *source);
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -14,6 +14,7 @@
|
|||||||
#include "src/kernel/vga.h"
|
#include "src/kernel/vga.h"
|
||||||
#include "src/lib/layout.h"
|
#include "src/lib/layout.h"
|
||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
|
#include "src/lib/syscall.h"
|
||||||
|
|
||||||
__attribute__((interrupt)) void isr_divide_by_zero(__attribute__((unused)) struct interrupt_frame *frame) {
|
__attribute__((interrupt)) void isr_divide_by_zero(__attribute__((unused)) struct interrupt_frame *frame) {
|
||||||
vga_set_string(VGA_HEIGHT - 1, 0, "EXCEPTION: divide by zero", 0x4F);
|
vga_set_string(VGA_HEIGHT - 1, 0, "EXCEPTION: divide by zero", 0x4F);
|
||||||
@@ -65,8 +66,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_file(kernel->root, kernel->cwd, "bin/terminal");
|
fs_node_t *terminal_node = path_open_node(kernel->root, kernel->cwd, "bin/terminal", OPEN_FILE);
|
||||||
fs_node_t *shell_node = path_open_file(kernel->root, kernel->cwd, "bin/shell");
|
fs_node_t *shell_node = path_open_node(kernel->root, 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");
|
||||||
|
|||||||
+9
-38
@@ -3,9 +3,10 @@
|
|||||||
#include "src/kernel/stream.h"
|
#include "src/kernel/stream.h"
|
||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
#include "src/lib/string.h"
|
#include "src/lib/string.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) {
|
path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags) {
|
||||||
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);
|
||||||
@@ -29,7 +30,9 @@ path_t *path_open(const fs_node_t *root, const path_t *source, const char *path)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : root;
|
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]) : NUL;
|
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;
|
||||||
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);
|
||||||
@@ -45,8 +48,8 @@ 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) {
|
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);
|
path_t *p = path_open(root, source, path, flags);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
@@ -55,40 +58,8 @@ fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const cha
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_node_t *path_open_file(const fs_node_t *root, const path_t *source, const char *path) {
|
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);
|
path_t *p = path_open(root, source, path, flags);
|
||||||
if (!p) {
|
|
||||||
return NUL;
|
|
||||||
}
|
|
||||||
if (!p->depth || p->stack[p->depth - 1]->is_dir) {
|
|
||||||
path_close(p);
|
|
||||||
return NUL;
|
|
||||||
}
|
|
||||||
fs_node_t *n = fs_open_again(p->stack[p->depth - 1]);
|
|
||||||
path_close(p);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs_node_t *path_open_directory(const fs_node_t *root, const path_t *source, const char *path) {
|
|
||||||
path_t *p = path_open(root, source, path);
|
|
||||||
if (!p) {
|
|
||||||
return NUL;
|
|
||||||
}
|
|
||||||
if (!p->depth) {
|
|
||||||
path_close(p);
|
|
||||||
return fs_open_again(root);
|
|
||||||
}
|
|
||||||
if (!p->stack[p->depth - 1]->is_dir) {
|
|
||||||
path_close(p);
|
|
||||||
return NUL;
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
path_t *p = path_open(root, source, path);
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
return NUL;
|
return NUL;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -10,14 +10,10 @@ 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);
|
path_t *path_open(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags);
|
||||||
|
|
||||||
fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path);
|
fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags);
|
||||||
|
|
||||||
fs_node_t *path_open_file(const fs_node_t *root, const path_t *source, const char *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_directory(const fs_node_t *root, const path_t *source, const char *path);
|
|
||||||
|
|
||||||
stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path);
|
|
||||||
|
|
||||||
void path_close(path_t *path);
|
void path_close(path_t *path);
|
||||||
|
|||||||
+6
-10
@@ -7,6 +7,7 @@
|
|||||||
#include "src/lib/layout.h"
|
#include "src/lib/layout.h"
|
||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
#include "src/lib/string.h"
|
#include "src/lib/string.h"
|
||||||
|
#include "src/lib/syscall.h"
|
||||||
#include "src/lib/util.h"
|
#include "src/lib/util.h"
|
||||||
|
|
||||||
#define MSR_EFER 0xC0000080
|
#define MSR_EFER 0xC0000080
|
||||||
@@ -79,22 +80,17 @@ 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);
|
path_t *cwd = path_open(current_process->root, current_process->cwd, path, OPEN_DIRECTORY);
|
||||||
if (!cwd) {
|
if (!cwd) {
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
if (!cwd->depth || !cwd->stack[cwd->depth - 1]->is_dir) {
|
|
||||||
path_close(cwd);
|
|
||||||
return (uint64_t)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
path_close((path_t *)current_process->cwd);
|
path_close((path_t *)current_process->cwd);
|
||||||
current_process->cwd = cwd;
|
current_process->cwd = cwd;
|
||||||
return current_process->cwd->depth;
|
return current_process->cwd->depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_file(current_process->root, current_process->cwd, path);
|
fs_node_t *node = path_open_node(current_process->root, current_process->cwd, path, OPEN_FILE);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return EXIT_CODE_NOT_FOUND;
|
return EXIT_CODE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@@ -161,11 +157,11 @@ static exit_code_t wait(uint64_t pid) {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t open(const char *path) {
|
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);
|
stream_t *stream = path_open_stream(current_process->root, current_process->cwd, path, flags);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
@@ -218,7 +214,7 @@ uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t
|
|||||||
case SYSCALL_WAIT:
|
case SYSCALL_WAIT:
|
||||||
return wait(arg1);
|
return wait(arg1);
|
||||||
case SYSCALL_OPEN:
|
case SYSCALL_OPEN:
|
||||||
return open((const char *)arg1);
|
return open((const char *)arg1, arg2);
|
||||||
case SYSCALL_CLOSE:
|
case SYSCALL_CLOSE:
|
||||||
return close(arg1);
|
return close(arg1);
|
||||||
case SYSCALL_TRUNCATE:
|
case SYSCALL_TRUNCATE:
|
||||||
|
|||||||
@@ -2,17 +2,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define SYSCALL_READ 0
|
|
||||||
#define SYSCALL_WRITE 1
|
|
||||||
#define SYSCALL_GETCWD 2
|
|
||||||
#define SYSCALL_CHDIR 3
|
|
||||||
#define SYSCALL_SPAWN 4
|
|
||||||
#define SYSCALL_WAIT 5
|
|
||||||
#define SYSCALL_OPEN 6
|
|
||||||
#define SYSCALL_CLOSE 7
|
|
||||||
#define SYSCALL_TRUNCATE 8
|
|
||||||
#define SYSCALL_EXIT 60
|
|
||||||
|
|
||||||
void syscall_init();
|
void syscall_init();
|
||||||
|
|
||||||
uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);
|
uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);
|
||||||
|
|||||||
@@ -172,8 +172,10 @@ stream_t *vga_init() {
|
|||||||
void vga_set_string(uint8_t row, uint8_t col, const char *str, uint8_t c) {
|
void vga_set_string(uint8_t row, uint8_t col, const char *str, uint8_t c) {
|
||||||
ASSERT(row < VGA_HEIGHT && col < VGA_WIDTH, "vga_set_string: invalid coordinates")
|
ASSERT(row < VGA_HEIGHT && col < VGA_WIDTH, "vga_set_string: invalid coordinates")
|
||||||
color = (uint16_t)((uint16_t)c << 8);
|
color = (uint16_t)((uint16_t)c << 8);
|
||||||
|
uint16_t prev_offset = offset;
|
||||||
offset = row * VGA_WIDTH + col;
|
offset = row * VGA_WIDTH + col;
|
||||||
while (*str) {
|
while (*str) {
|
||||||
on_char_received(*str++);
|
on_char_received(*str++);
|
||||||
}
|
}
|
||||||
|
offset = prev_offset;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#define SYSCALL_READ 0
|
||||||
|
#define SYSCALL_WRITE 1
|
||||||
|
#define SYSCALL_GETCWD 2
|
||||||
|
#define SYSCALL_CHDIR 3
|
||||||
|
#define SYSCALL_SPAWN 4
|
||||||
|
#define SYSCALL_WAIT 5
|
||||||
|
#define SYSCALL_OPEN 6
|
||||||
|
#define SYSCALL_CLOSE 7
|
||||||
|
#define SYSCALL_TRUNCATE 8
|
||||||
|
#define SYSCALL_EXIT 60
|
||||||
|
|
||||||
|
#define OPEN_CREATE 0b0001
|
||||||
|
#define OPEN_EXCLUSIVE 0b0010
|
||||||
|
#define OPEN_FILE 0b0100
|
||||||
|
#define OPEN_DIRECTORY 0b1000
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "src/lib/syscall.h"
|
||||||
#include "src/lib/util.h"
|
#include "src/lib/util.h"
|
||||||
#include "src/user/syscall.h"
|
#include "src/user/syscall.h"
|
||||||
|
|
||||||
@@ -7,7 +8,7 @@
|
|||||||
#define PRINT_D(s) write(1, s, string_length(s));
|
#define PRINT_D(s) write(1, s, string_length(s));
|
||||||
|
|
||||||
exit_code_t cat(const char *path) {
|
exit_code_t cat(const char *path) {
|
||||||
uint64_t fd = open(path);
|
uint64_t fd = open(path, OPEN_FILE);
|
||||||
|
|
||||||
if (fd == (uint64_t)-1) {
|
if (fd == (uint64_t)-1) {
|
||||||
PRINT_S("cat: path does not exist\n");
|
PRINT_S("cat: path does not exist\n");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "src/lib/syscall.h"
|
||||||
#include "src/lib/util.h"
|
#include "src/lib/util.h"
|
||||||
#include "src/user/syscall.h"
|
#include "src/user/syscall.h"
|
||||||
|
|
||||||
@@ -12,15 +13,15 @@ exit_code_t main(uint64_t argc, const char **argv) {
|
|||||||
return EXIT_CODE_GENERAL_FAILURE;
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t source = open(argv[1]);
|
uint64_t source = open(argv[1], OPEN_FILE);
|
||||||
if (source == (uint64_t)-1) {
|
if (source == (uint64_t)-1) {
|
||||||
PRINT_S("cp: source does not exist\n");
|
PRINT_S("cp: source does not exist\n");
|
||||||
return EXIT_CODE_GENERAL_FAILURE;
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t target = open(argv[2]);
|
uint64_t target = open(argv[2], OPEN_FILE | OPEN_CREATE);
|
||||||
if (target == (uint64_t)-1) {
|
if (target == (uint64_t)-1) {
|
||||||
PRINT_S("cp: target does not exist\n");
|
PRINT_S("cp: target path does not exist\n");
|
||||||
close(source);
|
close(source);
|
||||||
return EXIT_CODE_GENERAL_FAILURE;
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "src/lib/string.h"
|
#include "src/lib/string.h"
|
||||||
|
#include "src/lib/syscall.h"
|
||||||
#include "src/lib/util.h"
|
#include "src/lib/util.h"
|
||||||
#include "src/user/syscall.h"
|
#include "src/user/syscall.h"
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@
|
|||||||
#define PRINT_D(s) write(1, s, string_length(s));
|
#define PRINT_D(s) write(1, s, string_length(s));
|
||||||
|
|
||||||
exit_code_t ls(const char *path) {
|
exit_code_t ls(const char *path) {
|
||||||
uint64_t fd = open(path);
|
uint64_t fd = open(path, OPEN_DIRECTORY);
|
||||||
|
|
||||||
if (fd == (uint64_t)-1) {
|
if (fd == (uint64_t)-1) {
|
||||||
PRINT_S("ls: path does not exist\n");
|
PRINT_S("ls: path does not exist\n");
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#include "src/lib/syscall.h"
|
||||||
|
#include "src/lib/util.h"
|
||||||
|
#include "src/user/syscall.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 65536
|
||||||
|
|
||||||
|
#define PRINT_S(s) write(1, s, sizeof(s) - 1);
|
||||||
|
#define PRINT_D(s) write(1, s, string_length(s));
|
||||||
|
|
||||||
|
exit_code_t main(uint64_t argc, const char **argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
PRINT_S("mkdir: requires target(s)\n");
|
||||||
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint64_t i = 1; i < argc; i++) {
|
||||||
|
uint64_t fd = open(argv[i], OPEN_DIRECTORY | OPEN_CREATE | OPEN_EXCLUSIVE);
|
||||||
|
if (fd == (uint64_t)-1) {
|
||||||
|
PRINT_S("mkdir: could not create directory\n");
|
||||||
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
|
} else {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_CODE_OK;
|
||||||
|
}
|
||||||
+1
-2
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/lib/util.h"
|
#include "src/lib/util.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint64_t read(int64_t fd, uint64_t max, void *to);
|
uint64_t read(int64_t fd, uint64_t max, void *to);
|
||||||
|
|
||||||
@@ -15,7 +14,7 @@ uint64_t spawn(const char *path, uint64_t argc, const char **argv);
|
|||||||
|
|
||||||
exit_code_t waitpid(uint64_t pid);
|
exit_code_t waitpid(uint64_t pid);
|
||||||
|
|
||||||
uint64_t open(const char *path);
|
uint64_t open(const char *path, uint64_t flags);
|
||||||
|
|
||||||
uint64_t close(uint64_t fd);
|
uint64_t close(uint64_t fd);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user