Convert file descriptors to generic streams
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
#include "src/kernel/ata.h"
|
#include "src/kernel/ata.h"
|
||||||
#include "src/kernel/fs.h"
|
#include "src/kernel/fs.h"
|
||||||
#include "src/kernel/panic.h"
|
#include "src/kernel/panic.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/util.h"
|
#include "src/lib/util.h"
|
||||||
@@ -200,6 +201,45 @@ fs_node_t *fat16_open_again(const fs_node_t *source) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
stream_t stream;
|
||||||
|
fs_node_t *node;
|
||||||
|
uint64_t offset;
|
||||||
|
} fat16_stream_t;
|
||||||
|
|
||||||
|
static uint64_t stream_write(__attribute__((unused)) const stream_t *self, __attribute__((unused)) const char *from,
|
||||||
|
__attribute__((unused)) uint64_t bytes) {
|
||||||
|
return (uint64_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t stream_read(const stream_t *self, uint64_t max, char *to) {
|
||||||
|
fat16_stream_t *fss = (fat16_stream_t *)self;
|
||||||
|
if (fss->offset >= fss->node->size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint64_t remaining = fss->node->size - fss->offset;
|
||||||
|
uint64_t to_read = remaining > max ? max : remaining;
|
||||||
|
fat16_read(fss->node, fss->offset, to_read, to);
|
||||||
|
fss->offset += to_read;
|
||||||
|
return to_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stream_close(stream_t *self) {
|
||||||
|
fat16_stream_t *fss = (fat16_stream_t *)self;
|
||||||
|
fat16_close(fss->node);
|
||||||
|
memory_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_t *fat16_open_stream(const fs_node_t *source) {
|
||||||
|
fat16_stream_t *result = memory_allocate(sizeof(fat16_node_t));
|
||||||
|
result->stream.read = stream_read;
|
||||||
|
result->stream.write = stream_write;
|
||||||
|
result->stream.close = stream_close;
|
||||||
|
result->node = fat16_open_again(source);
|
||||||
|
result->offset = 0;
|
||||||
|
return (stream_t *)result;
|
||||||
|
}
|
||||||
|
|
||||||
void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
||||||
ASSERT(file->type == FAT16, "fat16_read: file is not FAT16");
|
ASSERT(file->type == FAT16, "fat16_read: file is not FAT16");
|
||||||
ASSERT(!file->is_dir, "fat16_read: can not read directory");
|
ASSERT(!file->is_dir, "fat16_read: can not read directory");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/kernel/fs.h"
|
#include "src/kernel/fs.h"
|
||||||
|
#include "src/kernel/stream.h"
|
||||||
|
|
||||||
#define FAT16 1
|
#define FAT16 1
|
||||||
|
|
||||||
@@ -12,6 +13,8 @@ fs_node_t *fat16_open_at(const fs_node_t *directory, uint64_t index);
|
|||||||
|
|
||||||
fs_node_t *fat16_open_again(const fs_node_t *source);
|
fs_node_t *fat16_open_again(const fs_node_t *source);
|
||||||
|
|
||||||
|
stream_t *fat16_open_stream(const fs_node_t *source);
|
||||||
|
|
||||||
void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
void fat16_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
||||||
|
|
||||||
void fat16_close(fs_node_t *node);
|
void fat16_close(fs_node_t *node);
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ fs_node_t *fs_open_again(const fs_node_t *source) {
|
|||||||
return fat16_open_again(source);
|
return fat16_open_again(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream_t *fs_open_stream(const fs_node_t *source) {
|
||||||
|
return fat16_open_stream(source);
|
||||||
|
}
|
||||||
|
|
||||||
void fs_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
void fs_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to) {
|
||||||
fat16_read(file, offset, size, to);
|
fat16_read(file, offset, size, to);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "src/kernel/stream.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define FILENAME_SIZE_LIMIT 255
|
#define FILENAME_SIZE_LIMIT 255
|
||||||
@@ -19,6 +20,8 @@ fs_node_t *fs_open_at(const fs_node_t *directory, uint64_t index);
|
|||||||
|
|
||||||
fs_node_t *fs_open_again(const fs_node_t *source);
|
fs_node_t *fs_open_again(const fs_node_t *source);
|
||||||
|
|
||||||
|
stream_t *fs_open_stream(const fs_node_t *source);
|
||||||
|
|
||||||
void fs_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
void fs_read(const fs_node_t *file, uint64_t offset, uint64_t size, void *to);
|
||||||
|
|
||||||
void fs_close(fs_node_t *node);
|
void fs_close(fs_node_t *node);
|
||||||
|
|||||||
+3
-2
@@ -53,8 +53,9 @@ void kernel_main() {
|
|||||||
kernel->pml4 = (void *)KERNEL_VIRTUAL_PML4;
|
kernel->pml4 = (void *)KERNEL_VIRTUAL_PML4;
|
||||||
kernel->root = fs_mount();
|
kernel->root = fs_mount();
|
||||||
kernel->cwd = memory_allocate(sizeof(path_t));
|
kernel->cwd = memory_allocate(sizeof(path_t));
|
||||||
kernel->stdin = keyboard_init();
|
kernel->fds[0] = keyboard_init();
|
||||||
kernel->stdout = vga_init();
|
kernel->fds[1] = vga_init();
|
||||||
|
kernel->free_fd = 2;
|
||||||
|
|
||||||
fs_node_t *bin = path_open_file(kernel->root, kernel->cwd, "bin/terminal");
|
fs_node_t *bin = path_open_file(kernel->root, kernel->cwd, "bin/terminal");
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,10 @@ static uint64_t stream_read(__attribute__((unused)) const stream_t *self, uint64
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static stream_t stream = {stream_write, stream_read};
|
static void stream_close(__attribute__((unused)) stream_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static stream_t stream = {stream_write, stream_read, stream_close};
|
||||||
|
|
||||||
static void on_key(uint8_t scancode) {
|
static void on_key(uint8_t scancode) {
|
||||||
const uint8_t pressed = !(scancode & 0x80);
|
const uint8_t pressed = !(scancode & 0x80);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "src/kernel/path.h"
|
#include "src/kernel/path.h"
|
||||||
#include "src/kernel/fs.h"
|
#include "src/kernel/fs.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/util.h"
|
#include "src/lib/util.h"
|
||||||
@@ -86,6 +87,16 @@ fs_node_t *path_open_directory(const fs_node_t *root, const path_t *source, cons
|
|||||||
return n;
|
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) {
|
||||||
|
return NUL;
|
||||||
|
}
|
||||||
|
stream_t *s = fs_open_stream(p->depth ? p->stack[p->depth - 1] : root);
|
||||||
|
path_close(p);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void path_close(path_t *path) {
|
void path_close(path_t *path) {
|
||||||
for (uint64_t i = 0; i < path->depth; i++) {
|
for (uint64_t i = 0; i < path->depth; i++) {
|
||||||
fs_close(path->stack[i]);
|
fs_close(path->stack[i]);
|
||||||
|
|||||||
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "src/kernel/fs.h"
|
#include "src/kernel/fs.h"
|
||||||
#include <stdint.h>
|
#include "src/kernel/stream.h"
|
||||||
|
|
||||||
#define PATH_DEPTH 255
|
#define PATH_DEPTH 255
|
||||||
|
|
||||||
@@ -18,4 +18,6 @@ fs_node_t *path_open_file(const fs_node_t *root, const path_t *source, const cha
|
|||||||
|
|
||||||
fs_node_t *path_open_directory(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);
|
||||||
|
|
||||||
void path_close(path_t *path);
|
void path_close(path_t *path);
|
||||||
|
|||||||
+11
-2
@@ -4,6 +4,7 @@
|
|||||||
#include "src/kernel/path.h"
|
#include "src/kernel/path.h"
|
||||||
#include "src/lib/layout.h"
|
#include "src/lib/layout.h"
|
||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
|
#include "src/lib/util.h"
|
||||||
|
|
||||||
process_t *current_process;
|
process_t *current_process;
|
||||||
|
|
||||||
@@ -57,14 +58,22 @@ process_t *process_create(const process_t *parent, const uint8_t *code, uint64_t
|
|||||||
|
|
||||||
proc->cwd = cwd;
|
proc->cwd = cwd;
|
||||||
proc->root = parent->root;
|
proc->root = parent->root;
|
||||||
proc->stdin = parent->stdin;
|
proc->fds[0] = parent->fds[0];
|
||||||
proc->stdout = parent->stdout;
|
proc->fds[1] = parent->fds[1];
|
||||||
proc->free_fd = 2;
|
proc->free_fd = 2;
|
||||||
|
proc->code = EXIT_CODE_OK;
|
||||||
|
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_destroy(process_t *proc) {
|
void process_destroy(process_t *proc) {
|
||||||
|
for (uint64_t i = 2; i < MAX_FDS; i++) {
|
||||||
|
if (proc->fds[i]) {
|
||||||
|
proc->fds[i]->close(proc->fds[i]);
|
||||||
|
proc->fds[i] = NUL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path_close((path_t *)proc->cwd);
|
path_close((path_t *)proc->cwd);
|
||||||
|
|
||||||
for (uint16_t pml4i = 0; pml4i < 256; pml4i++) {
|
for (uint16_t pml4i = 0; pml4i < 256; pml4i++) {
|
||||||
|
|||||||
@@ -3,16 +3,12 @@
|
|||||||
#include "src/kernel/fs.h"
|
#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"
|
||||||
|
|
||||||
#define USER_RFLAGS 0x202
|
#define USER_RFLAGS 0x202
|
||||||
|
|
||||||
#define MAX_FDS 16
|
#define MAX_FDS 16
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
fs_node_t *node;
|
|
||||||
uint64_t offset;
|
|
||||||
} fd_entry_t;
|
|
||||||
|
|
||||||
typedef struct process {
|
typedef struct process {
|
||||||
const struct process *parent;
|
const struct process *parent;
|
||||||
uint64_t *pml4;
|
uint64_t *pml4;
|
||||||
@@ -22,10 +18,9 @@ typedef struct process {
|
|||||||
void *user_rsp;
|
void *user_rsp;
|
||||||
const fs_node_t *root;
|
const fs_node_t *root;
|
||||||
const path_t *cwd;
|
const path_t *cwd;
|
||||||
const stream_t *stdin;
|
stream_t *fds[MAX_FDS];
|
||||||
const stream_t *stdout;
|
|
||||||
fd_entry_t fds[MAX_FDS];
|
|
||||||
uint64_t free_fd;
|
uint64_t free_fd;
|
||||||
|
exit_code_t code;
|
||||||
} process_t;
|
} process_t;
|
||||||
|
|
||||||
typedef void (*app_t)(process_t *proc, uint8_t argc, char **argv);
|
typedef void (*app_t)(process_t *proc, uint8_t argc, char **argv);
|
||||||
|
|||||||
@@ -29,8 +29,10 @@ typedef struct stream stream_t;
|
|||||||
|
|
||||||
typedef uint64_t (*stream_write_t)(const stream_t *self, const char *from, uint64_t bytes);
|
typedef uint64_t (*stream_write_t)(const stream_t *self, const char *from, uint64_t bytes);
|
||||||
typedef uint64_t (*stream_read_t)(const stream_t *self, uint64_t max, char *to);
|
typedef uint64_t (*stream_read_t)(const stream_t *self, uint64_t max, char *to);
|
||||||
|
typedef void (*stream_close_t)(stream_t *self);
|
||||||
|
|
||||||
typedef struct stream {
|
typedef struct stream {
|
||||||
stream_write_t write;
|
stream_write_t write;
|
||||||
stream_read_t read;
|
stream_read_t read;
|
||||||
|
stream_close_t close;
|
||||||
} stream_t;
|
} stream_t;
|
||||||
|
|||||||
+22
-42
@@ -3,6 +3,7 @@
|
|||||||
#include "src/kernel/gdt.h"
|
#include "src/kernel/gdt.h"
|
||||||
#include "src/kernel/path.h"
|
#include "src/kernel/path.h"
|
||||||
#include "src/kernel/process.h"
|
#include "src/kernel/process.h"
|
||||||
|
#include "src/kernel/stream.h"
|
||||||
#include "src/kernel/tss.h"
|
#include "src/kernel/tss.h"
|
||||||
#include "src/lib/layout.h"
|
#include "src/lib/layout.h"
|
||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
@@ -34,37 +35,17 @@ void syscall_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t read(uint64_t fd, uint64_t max, char *to) {
|
static uint64_t read(uint64_t fd, uint64_t max, char *to) {
|
||||||
switch (fd) {
|
if (fd >= MAX_FDS || !current_process->fds[fd]) {
|
||||||
case 0:
|
|
||||||
return current_process->stdin->read(current_process->stdin, max, to);
|
|
||||||
case 1:
|
|
||||||
return current_process->stdout->read(current_process->stdout, max, to);
|
|
||||||
default:
|
|
||||||
if (!current_process->fds[fd].node) {
|
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
if (current_process->fds[fd].offset >= current_process->fds[fd].node->size) {
|
return current_process->fds[fd]->read(current_process->fds[fd], max, to);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint64_t remaining = current_process->fds[fd].node->size - current_process->fds[fd].offset;
|
|
||||||
uint64_t to_read = remaining > max ? max : remaining;
|
|
||||||
fs_read(current_process->fds[fd].node, current_process->fds[fd].offset, to_read, to);
|
|
||||||
current_process->fds[fd].offset += to_read;
|
|
||||||
return to_read;
|
|
||||||
}
|
|
||||||
return (uint64_t)-1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t write(uint64_t fd, const char *from, uint64_t bytes) {
|
static uint64_t write(uint64_t fd, const char *from, uint64_t bytes) {
|
||||||
switch (fd) {
|
if (fd >= MAX_FDS || !current_process->fds[fd]) {
|
||||||
case 0:
|
|
||||||
return current_process->stdin->write(current_process->stdin, from, bytes);
|
|
||||||
case 1:
|
|
||||||
return current_process->stdout->write(current_process->stdout, from, bytes);
|
|
||||||
default:
|
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
return (uint64_t)-1;
|
return current_process->fds[fd]->write(current_process->fds[fd], from, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t getcwd(uint64_t max, char *to) {
|
static uint64_t getcwd(uint64_t max, char *to) {
|
||||||
@@ -113,13 +94,13 @@ static uint64_t chdir(const char *path) {
|
|||||||
return current_process->cwd->depth;
|
return current_process->cwd->depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t spawn(const char *path, uint64_t argc, const char **argv) {
|
static exit_code_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_file(current_process->root, current_process->cwd, path);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return (uint64_t)-1;
|
return EXIT_CODE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
uint8_t *code = memory_allocate(node->size);
|
uint8_t *bin = memory_allocate(node->size);
|
||||||
fs_read(node, 0, node->size, code);
|
fs_read(node, 0, node->size, bin);
|
||||||
|
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
uint64_t sizes[16];
|
uint64_t sizes[16];
|
||||||
@@ -133,9 +114,9 @@ static uint64_t spawn(const char *path, uint64_t argc, const char **argv) {
|
|||||||
memory_copy(argv[i], sizes[i], blob + offsets[i]);
|
memory_copy(argv[i], sizes[i], blob + offsets[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
process_t *child = process_create(current_process, code, node->size);
|
process_t *child = process_create(current_process, bin, node->size);
|
||||||
|
|
||||||
memory_free(code);
|
memory_free(bin);
|
||||||
fs_close(node);
|
fs_close(node);
|
||||||
|
|
||||||
__asm__ volatile("mov %0, %%cr3" : : "r"((uint64_t)VIRT_TO_PHYS((void *)KERNEL_VIRTUAL_PML4)) : "memory");
|
__asm__ volatile("mov %0, %%cr3" : : "r"((uint64_t)VIRT_TO_PHYS((void *)KERNEL_VIRTUAL_PML4)) : "memory");
|
||||||
@@ -163,11 +144,12 @@ static uint64_t spawn(const char *path, uint64_t argc, const char **argv) {
|
|||||||
|
|
||||||
process_switch_to(&parent->kernel_rsp, child->kernel_rsp, VIRT_TO_PHYS(child->pml4));
|
process_switch_to(&parent->kernel_rsp, child->kernel_rsp, VIRT_TO_PHYS(child->pml4));
|
||||||
|
|
||||||
|
exit_code_t code = child->code;
|
||||||
tss.rsp0 = (uint64_t)parent->kernel_stack;
|
tss.rsp0 = (uint64_t)parent->kernel_stack;
|
||||||
current_process = parent;
|
current_process = parent;
|
||||||
process_destroy(child);
|
process_destroy(child);
|
||||||
|
|
||||||
return 0;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t readdir(const char *path, uint64_t index, uint64_t max, char *to) {
|
static uint64_t readdir(const char *path, uint64_t index, uint64_t max, char *to) {
|
||||||
@@ -199,27 +181,25 @@ static uint64_t open(const char *path) {
|
|||||||
if (current_process->free_fd >= MAX_FDS) {
|
if (current_process->free_fd >= MAX_FDS) {
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
fs_node_t *node = path_open_node(current_process->root, current_process->cwd, path);
|
stream_t *stream = path_open_stream(current_process->root, current_process->cwd, path);
|
||||||
if (!node) {
|
if (!stream) {
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
current_process->fds[current_process->free_fd].node = node;
|
current_process->fds[current_process->free_fd++] = stream;
|
||||||
current_process->fds[current_process->free_fd].offset++;
|
|
||||||
current_process->free_fd++;
|
|
||||||
return current_process->free_fd - 1;
|
return current_process->free_fd - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t close(uint64_t fd) {
|
static uint64_t close(uint64_t fd) {
|
||||||
if (fd >= MAX_FDS || !current_process->fds[fd].node) {
|
if (fd >= MAX_FDS || !current_process->fds[fd]) {
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
fs_close(current_process->fds[fd].node);
|
current_process->fds[fd]->close(current_process->fds[fd]);
|
||||||
current_process->fds[fd].node = NUL;
|
current_process->fds[fd] = NUL;
|
||||||
current_process->fds[fd].offset = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exit() {
|
static void exit(exit_code_t code) {
|
||||||
|
current_process->code = code;
|
||||||
process_switch_to(¤t_process->kernel_rsp, current_process->parent->kernel_rsp, VIRT_TO_PHYS(current_process->parent->pml4));
|
process_switch_to(¤t_process->kernel_rsp, current_process->parent->kernel_rsp, VIRT_TO_PHYS(current_process->parent->pml4));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +222,7 @@ uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t
|
|||||||
case SYSCALL_CLOSE:
|
case SYSCALL_CLOSE:
|
||||||
return close(arg1);
|
return close(arg1);
|
||||||
case SYSCALL_EXIT:
|
case SYSCALL_EXIT:
|
||||||
exit();
|
exit(arg1);
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
|
|||||||
+4
-1
@@ -155,7 +155,10 @@ static uint64_t stream_read(__attribute__((unused)) const stream_t *self, __attr
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static stream_t stream = {stream_write, stream_read};
|
static void stream_close(__attribute__((unused)) stream_t *self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static stream_t stream = {stream_write, stream_read, stream_close};
|
||||||
|
|
||||||
stream_t *vga_init() {
|
stream_t *vga_init() {
|
||||||
clear();
|
clear();
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define NUL 0 // TODO Fix VSCode thinking `NULL` conflicts with some other definition.
|
#define NUL 0 // TODO Fix VSCode thinking `NULL` conflicts with some other definition.
|
||||||
|
|
||||||
|
typedef uint64_t exit_code_t;
|
||||||
|
|
||||||
|
#define EXIT_CODE_OK 0
|
||||||
|
#define EXIT_CODE_NOT_FOUND ((uint64_t)-2)
|
||||||
|
#define EXIT_CODE_GENERAL_FAILURE ((uint64_t)-1)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "src/lib/util.h"
|
||||||
#include "src/user/syscall.h"
|
#include "src/user/syscall.h"
|
||||||
|
|
||||||
#define BLOCK_SIZE 65536
|
#define BLOCK_SIZE 65536
|
||||||
@@ -5,12 +6,12 @@
|
|||||||
#define PRINT_S(s) write(1, s, sizeof(s) - 1);
|
#define PRINT_S(s) write(1, s, sizeof(s) - 1);
|
||||||
#define PRINT_D(s) write(1, s, string_length(s));
|
#define PRINT_D(s) write(1, s, string_length(s));
|
||||||
|
|
||||||
uint64_t cat(const char *path) {
|
exit_code_t cat(const char *path) {
|
||||||
uint64_t fd = open(path);
|
uint64_t fd = open(path);
|
||||||
|
|
||||||
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");
|
||||||
return (uint64_t)-1;
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char buffer[BLOCK_SIZE];
|
static char buffer[BLOCK_SIZE];
|
||||||
@@ -19,7 +20,7 @@ uint64_t cat(const char *path) {
|
|||||||
if (bytes == (uint64_t)-1) {
|
if (bytes == (uint64_t)-1) {
|
||||||
PRINT_S("cat: could not read file\n");
|
PRINT_S("cat: could not read file\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return (uint64_t)-1;
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
write(1, buffer, bytes);
|
write(1, buffer, bytes);
|
||||||
}
|
}
|
||||||
@@ -29,15 +30,16 @@ uint64_t cat(const char *path) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t main(uint64_t argc, const char **argv) {
|
exit_code_t main(uint64_t argc, const char **argv) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
return cat(".");
|
return cat(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t code = 0;
|
uint64_t code = EXIT_CODE_OK;
|
||||||
for (uint64_t i = 1; i < argc; i++) {
|
for (uint64_t i = 1; i < argc; i++) {
|
||||||
if (cat(argv[i]) == (uint64_t)-1) {
|
exit_code_t c = cat(argv[i]);
|
||||||
code = (uint64_t)-1;
|
if (c != EXIT_CODE_OK) {
|
||||||
|
code = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "src/lib/string.h"
|
#include "src/lib/string.h"
|
||||||
|
#include "src/lib/util.h"
|
||||||
#include "src/user/syscall.h"
|
#include "src/user/syscall.h"
|
||||||
|
|
||||||
uint64_t main(uint64_t argc, const char **argv) {
|
exit_code_t main(uint64_t argc, const char **argv) {
|
||||||
for (uint64_t i = 1; i < argc; i++) {
|
for (uint64_t i = 1; i < argc; i++) {
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
write(1, " ", 1);
|
write(1, " ", 1);
|
||||||
@@ -9,5 +10,5 @@ uint64_t main(uint64_t argc, const char **argv) {
|
|||||||
write(1, argv[i], string_length(argv[i]));
|
write(1, argv[i], string_length(argv[i]));
|
||||||
}
|
}
|
||||||
write(1, "\n", 1);
|
write(1, "\n", 1);
|
||||||
return 0;
|
return EXIT_CODE_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
#include "src/lib/string.h"
|
#include "src/lib/string.h"
|
||||||
|
#include "src/lib/util.h"
|
||||||
#include "src/user/syscall.h"
|
#include "src/user/syscall.h"
|
||||||
|
|
||||||
#define PRINT_S(s) write(1, s, sizeof(s) - 1);
|
#define PRINT_S(s) write(1, s, sizeof(s) - 1);
|
||||||
#define PRINT_D(s) write(1, s, string_length(s));
|
#define PRINT_D(s) write(1, s, string_length(s));
|
||||||
|
|
||||||
uint64_t ls(const char *path) {
|
exit_code_t ls(const char *path) {
|
||||||
uint64_t i = 0;
|
uint64_t i = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
char out[100];
|
char out[100];
|
||||||
uint64_t s = readdir(path, i, 100, out);
|
uint64_t s = readdir(path, i, 100, out);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
return 0;
|
return EXIT_CODE_OK;
|
||||||
}
|
}
|
||||||
if (s == (uint64_t)-1) {
|
if (s == (uint64_t)-1) {
|
||||||
PRINT_S("ls: path does not exist\n");
|
PRINT_S("ls: path does not exist\n");
|
||||||
return (uint64_t)-1;
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
PRINT_D(out);
|
PRINT_D(out);
|
||||||
PRINT_S("\n");
|
PRINT_S("\n");
|
||||||
@@ -22,20 +23,21 @@ uint64_t ls(const char *path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t main(uint64_t argc, const char **argv) {
|
exit_code_t main(uint64_t argc, const char **argv) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
return ls(".");
|
return ls(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t code = 0;
|
exit_code_t code = EXIT_CODE_OK;
|
||||||
for (uint64_t i = 1; i < argc; i++) {
|
for (uint64_t i = 1; i < argc; i++) {
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
PRINT_S("\n");
|
PRINT_S("\n");
|
||||||
PRINT_D(argv[i]);
|
PRINT_D(argv[i]);
|
||||||
PRINT_S(":\n");
|
PRINT_S(":\n");
|
||||||
}
|
}
|
||||||
if (ls(argv[i]) == (uint64_t)-1) {
|
exit_code_t c = ls(argv[i]);
|
||||||
code = (uint64_t)-1;
|
if (c != EXIT_CODE_OK) {
|
||||||
|
code = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
#include "src/lib/string.h"
|
#include "src/lib/string.h"
|
||||||
|
#include "src/lib/util.h"
|
||||||
#include "src/user/syscall.h"
|
#include "src/user/syscall.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ static void on_enter_pressed() {
|
|||||||
char *path = memory_allocate(size);
|
char *path = memory_allocate(size);
|
||||||
memory_copy(PATH, sizeof(PATH), path);
|
memory_copy(PATH, sizeof(PATH), path);
|
||||||
memory_copy(argv[0], size - sizeof(PATH), path + sizeof(PATH) - 1);
|
memory_copy(argv[0], size - sizeof(PATH), path + sizeof(PATH) - 1);
|
||||||
if (spawn(path, argc, (const char **)argv) == (uint64_t)-1) {
|
if (spawn(path, argc, (const char **)argv) == EXIT_CODE_NOT_FOUND) {
|
||||||
PRINT_S("terminal: program not found\n");
|
PRINT_S("terminal: program not found\n");
|
||||||
}
|
}
|
||||||
memory_free(path);
|
memory_free(path);
|
||||||
@@ -140,7 +141,7 @@ static void on_cancel_pressed() {
|
|||||||
|
|
||||||
static void on_disconnect_pressed() {
|
static void on_disconnect_pressed() {
|
||||||
PRINT_S("^D\n");
|
PRINT_S("^D\n");
|
||||||
exit();
|
exit(EXIT_CODE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_ctrl_character_pressed(char c) {
|
static void on_ctrl_character_pressed(char c) {
|
||||||
|
|||||||
+3
-2
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "src/lib/util.h"
|
||||||
#include <stdint.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);
|
||||||
@@ -10,7 +11,7 @@ uint64_t getcwd(uint64_t max, void *to);
|
|||||||
|
|
||||||
uint64_t chdir(const char *path);
|
uint64_t chdir(const char *path);
|
||||||
|
|
||||||
uint64_t spawn(const char *path, uint64_t argc, const char **argv);
|
exit_code_t spawn(const char *path, uint64_t argc, const char **argv);
|
||||||
|
|
||||||
uint64_t readdir(const char *path, uint64_t index, uint64_t max, char *to);
|
uint64_t readdir(const char *path, uint64_t index, uint64_t max, char *to);
|
||||||
|
|
||||||
@@ -18,4 +19,4 @@ uint64_t open(const char *path);
|
|||||||
|
|
||||||
uint64_t close(uint64_t fd);
|
uint64_t close(uint64_t fd);
|
||||||
|
|
||||||
void exit();
|
void exit(exit_code_t code);
|
||||||
|
|||||||
Reference in New Issue
Block a user