From 44584939a9effa5280de0d023af39d7224cf7323 Mon Sep 17 00:00:00 2001 From: Freywar Ulvnaudgari Date: Tue, 30 Jun 2026 20:37:24 +0300 Subject: [PATCH] Add file and directory creation, `mkdir` --- build.sh | 1 + meson.build | 39 ++++++++++ src/kernel/fat16.c | 144 ++++++++++++++++++++++++++++++------- src/kernel/fat16.h | 4 +- src/kernel/fs.c | 8 +-- src/kernel/fs.h | 5 +- src/kernel/kernel.c | 5 +- src/kernel/path.c | 47 +++--------- src/kernel/path.h | 10 +-- src/kernel/syscall.c | 16 ++--- src/kernel/syscall.h | 11 --- src/kernel/vga.c | 2 + src/lib/syscall.h | 15 ++++ src/user/app/cat/cat.c | 3 +- src/user/app/cp/cp.c | 7 +- src/user/app/ls/ls.c | 3 +- src/user/app/mkdir/mkdir.c | 28 ++++++++ src/user/syscall.h | 3 +- 18 files changed, 241 insertions(+), 110 deletions(-) create mode 100644 src/lib/syscall.h create mode 100644 src/user/app/mkdir/mkdir.c diff --git a/build.sh b/build.sh index c5a3da7..91b686b 100755 --- a/build.sh +++ b/build.sh @@ -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/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/mkdir ::bin/mkdir diff --git a/meson.build b/meson.build index ba9a79c..7ee109a 100644 --- a/meson.build +++ b/meson.build @@ -349,3 +349,42 @@ custom_target( command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'], 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, +) diff --git a/src/kernel/fat16.c b/src/kernel/fat16.c index 8dbae2b..4959420 100644 --- a/src/kernel/fat16.c +++ b/src/kernel/fat16.c @@ -5,6 +5,7 @@ #include "src/kernel/stream.h" #include "src/lib/memory.h" #include "src/lib/string.h" +#include "src/lib/syscall.h" #include "src/lib/util.h" #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); } -static fat16_dir_entry_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) { if (!dir_cluster) { 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. - ata_read_sectors(FIRST_PARTITION_SECTOR + bpb.reserved_sectors + bpb.fats_count * bpb.sectors_per_fat, sectors, entries); + *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; } else { ensure_fat(); uint16_t next_cluster = dir_cluster; - uint32_t cluster_count = 0; + uint16_t cluster_count = 0; while (next_cluster < 0xFFF8) { cluster_count++; next_cluster = fat[next_cluster]; } - entries = - memory_allocate(cluster_count * bpb.sectors_per_cluster * SECTOR_SIZE + sizeof(fat16_dir_entry_t)); // One extra as null terminator. + *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; 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; 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) { @@ -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; } -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) { 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(); - // Assuming no entries were added or removed. uint8_t *chunk = (uint8_t *)entries; 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); 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]; } + 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) { return NUL; } + uint16_t dir_cluster = ((fat16_node_t *)directory)->inode->first_cluster; + char name_8_3[12]; 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; 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)) { break; } @@ -271,20 +281,82 @@ fs_node_t *fat16_open_by(const fs_node_t *directory, const char *name) { 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); + + if (!result) { + return NUL; + } + + if (result->is_dir && !(flags & OPEN_DIRECTORY)) { + return NUL; + } + + if (!result->is_dir && !(flags & OPEN_FILE)) { + return NUL; + } + 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) { 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; - 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 (vi == index) { 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); + 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; } @@ -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) { 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].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); } @@ -482,10 +573,11 @@ uint64_t fat16_truncate(fs_node_t *file, uint32_t size) { flush_fat(); 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].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); return size; @@ -535,7 +627,7 @@ static void file_stream_close(stream_t *self) { typedef struct { stream_t stream; fs_node_t *node; - uint32_t index; + uint16_t index; } fat16_directory_stream_t; 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) { 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) { return 0; } diff --git a/src/kernel/fat16.h b/src/kernel/fat16.h index f1c4e1f..83f87fd 100644 --- a/src/kernel/fat16.h +++ b/src/kernel/fat16.h @@ -7,9 +7,9 @@ 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); diff --git a/src/kernel/fs.c b/src/kernel/fs.c index e551fe2..a504d28 100644 --- a/src/kernel/fs.c +++ b/src/kernel/fs.c @@ -5,12 +5,12 @@ fs_node_t *fs_mount() { return fat16_mount(); } -fs_node_t *fs_open_by(const fs_node_t *directory, const char *name) { - return fat16_open_by(directory, name); +fs_node_t *fs_open_by(const fs_node_t *directory, const char *name, uint64_t flags) { + return fat16_open_by(directory, name, flags); } -fs_node_t *fs_open_at(const fs_node_t *directory, uint64_t index) { - return fat16_open_at(directory, index); +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) { diff --git a/src/kernel/fs.h b/src/kernel/fs.h index a6b0b6d..fe1b48a 100644 --- a/src/kernel/fs.h +++ b/src/kernel/fs.h @@ -1,7 +1,6 @@ #pragma once #include "src/kernel/stream.h" -#include #define FILENAME_SIZE_LIMIT 255 @@ -14,9 +13,9 @@ typedef struct fs_node { 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); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index e68b5b6..264d2cd 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -14,6 +14,7 @@ #include "src/kernel/vga.h" #include "src/lib/layout.h" #include "src/lib/memory.h" +#include "src/lib/syscall.h" __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); @@ -65,8 +66,8 @@ void kernel_main() { current_process = kernel; tss.rsp0 = (uint64_t)kernel->kernel_stack; - fs_node_t *terminal_node = path_open_file(kernel->root, kernel->cwd, "bin/terminal"); - fs_node_t *shell_node = path_open_file(kernel->root, kernel->cwd, "bin/shell"); + 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); ASSERT(terminal_node, "kernel: terminal not found"); ASSERT(shell_node, "kernel: shell not found"); diff --git a/src/kernel/path.c b/src/kernel/path.c index 5af7ada..5f674ee 100644 --- a/src/kernel/path.c +++ b/src/kernel/path.c @@ -3,9 +3,10 @@ #include "src/kernel/stream.h" #include "src/lib/memory.h" #include "src/lib/string.h" +#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) { +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); char *path_own = memory_allocate(length + 1); 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 { 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) { path_close(result); 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; } -fs_node_t *path_open_node(const fs_node_t *root, const path_t *source, const char *path) { - path_t *p = path_open(root, source, 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, flags); if (!p) { 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; } -fs_node_t *path_open_file(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 || 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); +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); if (!p) { return NUL; } diff --git a/src/kernel/path.h b/src/kernel/path.h index b09fc7c..fad9a76 100644 --- a/src/kernel/path.h +++ b/src/kernel/path.h @@ -10,14 +10,10 @@ typedef struct { uint8_t depth; } 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); - -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); +stream_t *path_open_stream(const fs_node_t *root, const path_t *source, const char *path, uint64_t flags); void path_close(path_t *path); diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 386ffae..1f20bad 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -7,6 +7,7 @@ #include "src/lib/layout.h" #include "src/lib/memory.h" #include "src/lib/string.h" +#include "src/lib/syscall.h" #include "src/lib/util.h" #define MSR_EFER 0xC0000080 @@ -79,22 +80,17 @@ 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); + path_t *cwd = path_open(current_process->root, current_process->cwd, path, OPEN_DIRECTORY); if (!cwd) { 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); current_process->cwd = cwd; return current_process->cwd->depth; } 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) { return EXIT_CODE_NOT_FOUND; } @@ -161,11 +157,11 @@ static exit_code_t wait(uint64_t pid) { 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) { 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) { 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: return wait(arg1); case SYSCALL_OPEN: - return open((const char *)arg1); + return open((const char *)arg1, arg2); case SYSCALL_CLOSE: return close(arg1); case SYSCALL_TRUNCATE: diff --git a/src/kernel/syscall.h b/src/kernel/syscall.h index b5d3497..d702d5f 100644 --- a/src/kernel/syscall.h +++ b/src/kernel/syscall.h @@ -2,17 +2,6 @@ #include -#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(); uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); diff --git a/src/kernel/vga.c b/src/kernel/vga.c index 96db46c..ee93cc8 100644 --- a/src/kernel/vga.c +++ b/src/kernel/vga.c @@ -172,8 +172,10 @@ stream_t *vga_init() { 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") color = (uint16_t)((uint16_t)c << 8); + uint16_t prev_offset = offset; offset = row * VGA_WIDTH + col; while (*str) { on_char_received(*str++); } + offset = prev_offset; } diff --git a/src/lib/syscall.h b/src/lib/syscall.h new file mode 100644 index 0000000..cf22976 --- /dev/null +++ b/src/lib/syscall.h @@ -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 diff --git a/src/user/app/cat/cat.c b/src/user/app/cat/cat.c index dbd5baa..7d9cfc5 100644 --- a/src/user/app/cat/cat.c +++ b/src/user/app/cat/cat.c @@ -1,3 +1,4 @@ +#include "src/lib/syscall.h" #include "src/lib/util.h" #include "src/user/syscall.h" @@ -7,7 +8,7 @@ #define PRINT_D(s) write(1, s, string_length(s)); exit_code_t cat(const char *path) { - uint64_t fd = open(path); + uint64_t fd = open(path, OPEN_FILE); if (fd == (uint64_t)-1) { PRINT_S("cat: path does not exist\n"); diff --git a/src/user/app/cp/cp.c b/src/user/app/cp/cp.c index 23b3167..1258553 100644 --- a/src/user/app/cp/cp.c +++ b/src/user/app/cp/cp.c @@ -1,3 +1,4 @@ +#include "src/lib/syscall.h" #include "src/lib/util.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; } - uint64_t source = open(argv[1]); + uint64_t source = open(argv[1], OPEN_FILE); if (source == (uint64_t)-1) { PRINT_S("cp: source does not exist\n"); 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) { - PRINT_S("cp: target does not exist\n"); + PRINT_S("cp: target path does not exist\n"); close(source); return EXIT_CODE_GENERAL_FAILURE; } diff --git a/src/user/app/ls/ls.c b/src/user/app/ls/ls.c index 19a0b22..5308a52 100644 --- a/src/user/app/ls/ls.c +++ b/src/user/app/ls/ls.c @@ -1,4 +1,5 @@ #include "src/lib/string.h" +#include "src/lib/syscall.h" #include "src/lib/util.h" #include "src/user/syscall.h" @@ -6,7 +7,7 @@ #define PRINT_D(s) write(1, s, string_length(s)); exit_code_t ls(const char *path) { - uint64_t fd = open(path); + uint64_t fd = open(path, OPEN_DIRECTORY); if (fd == (uint64_t)-1) { PRINT_S("ls: path does not exist\n"); diff --git a/src/user/app/mkdir/mkdir.c b/src/user/app/mkdir/mkdir.c new file mode 100644 index 0000000..eb552d2 --- /dev/null +++ b/src/user/app/mkdir/mkdir.c @@ -0,0 +1,28 @@ +#include "src/lib/syscall.h" +#include "src/lib/util.h" +#include "src/user/syscall.h" +#include + +#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; +} diff --git a/src/user/syscall.h b/src/user/syscall.h index ef60f3b..8dbf829 100644 --- a/src/user/syscall.h +++ b/src/user/syscall.h @@ -1,7 +1,6 @@ #pragma once #include "src/lib/util.h" -#include 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); -uint64_t open(const char *path); +uint64_t open(const char *path, uint64_t flags); uint64_t close(uint64_t fd);