Convert directory reading to generic stream
This commit is contained in:
+56
-15
@@ -205,39 +205,80 @@ typedef struct {
|
|||||||
stream_t stream;
|
stream_t stream;
|
||||||
fs_node_t *node;
|
fs_node_t *node;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
} fat16_stream_t;
|
} fat16_file_stream_t;
|
||||||
|
|
||||||
static uint64_t stream_write(__attribute__((unused)) const stream_t *self, __attribute__((unused)) const char *from,
|
static uint64_t file_stream_write(__attribute__((unused)) const stream_t *self, __attribute__((unused)) const char *from,
|
||||||
__attribute__((unused)) uint64_t bytes) {
|
__attribute__((unused)) uint64_t bytes) {
|
||||||
return (uint64_t)-1;
|
return (uint64_t)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t stream_read(const stream_t *self, uint64_t max, char *to) {
|
static uint64_t file_stream_read(const stream_t *self, uint64_t max, char *to) {
|
||||||
fat16_stream_t *fss = (fat16_stream_t *)self;
|
fat16_file_stream_t *ffs = (fat16_file_stream_t *)self;
|
||||||
if (fss->offset >= fss->node->size) {
|
if (ffs->offset >= ffs->node->size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
uint64_t remaining = fss->node->size - fss->offset;
|
uint64_t remaining = ffs->node->size - ffs->offset;
|
||||||
uint64_t to_read = remaining > max ? max : remaining;
|
uint64_t to_read = remaining > max ? max : remaining;
|
||||||
fat16_read(fss->node, fss->offset, to_read, to);
|
fat16_read(ffs->node, ffs->offset, to_read, to);
|
||||||
fss->offset += to_read;
|
ffs->offset += to_read;
|
||||||
return to_read;
|
return to_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stream_close(stream_t *self) {
|
static void file_stream_close(stream_t *self) {
|
||||||
fat16_stream_t *fss = (fat16_stream_t *)self;
|
fat16_file_stream_t *ffs = (fat16_file_stream_t *)self;
|
||||||
fat16_close(fss->node);
|
fat16_close(ffs->node);
|
||||||
|
memory_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
stream_t stream;
|
||||||
|
fs_node_t *node;
|
||||||
|
uint64_t index;
|
||||||
|
} fat16_directory_stream_t;
|
||||||
|
|
||||||
|
static uint64_t directory_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 directory_stream_read(const 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++);
|
||||||
|
if (!node) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint64_t length = string_length(node->name);
|
||||||
|
uint64_t to_read = length + 1 > max ? max : length + 1;
|
||||||
|
memory_copy(node->name, to_read, to);
|
||||||
|
to[max - 1] = '\0';
|
||||||
|
|
||||||
|
return to_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void directory_stream_close(stream_t *self) {
|
||||||
|
fat16_directory_stream_t *fds = (fat16_directory_stream_t *)self;
|
||||||
|
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(const fs_node_t *source) {
|
||||||
fat16_stream_t *result = memory_allocate(sizeof(fat16_node_t));
|
if (!source->is_dir) {
|
||||||
result->stream.read = stream_read;
|
fat16_file_stream_t *result = memory_allocate(sizeof(fat16_file_stream_t));
|
||||||
result->stream.write = stream_write;
|
result->stream.read = file_stream_read;
|
||||||
result->stream.close = stream_close;
|
result->stream.write = file_stream_write;
|
||||||
|
result->stream.close = file_stream_close;
|
||||||
result->node = fat16_open_again(source);
|
result->node = fat16_open_again(source);
|
||||||
result->offset = 0;
|
result->offset = 0;
|
||||||
return (stream_t *)result;
|
return (stream_t *)result;
|
||||||
|
} else {
|
||||||
|
fat16_directory_stream_t *result = memory_allocate(sizeof(fat16_directory_stream_t));
|
||||||
|
result->stream.read = directory_stream_read;
|
||||||
|
result->stream.write = directory_stream_write;
|
||||||
|
result->stream.close = directory_stream_close;
|
||||||
|
result->node = fat16_open_again(source);
|
||||||
|
result->index = 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) {
|
||||||
|
|||||||
+1
-28
@@ -152,31 +152,6 @@ static exit_code_t spawn(const char *path, uint64_t argc, const char **argv) {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t readdir(const char *path, uint64_t index, uint64_t max, char *to) {
|
|
||||||
fs_node_t *dir = path_open_directory(current_process->root, current_process->cwd, path);
|
|
||||||
if (!dir) {
|
|
||||||
return (uint64_t)-1;
|
|
||||||
}
|
|
||||||
fs_node_t *item = fs_open_at(dir, index);
|
|
||||||
if (!item) {
|
|
||||||
if (dir != current_process->root) {
|
|
||||||
fs_close(dir);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
uint64_t length = string_length(item->name);
|
|
||||||
uint64_t size = length > max - 1 ? max - 1 : length;
|
|
||||||
memory_copy(item->name, size, to);
|
|
||||||
to[size] = '\0';
|
|
||||||
|
|
||||||
fs_close(item);
|
|
||||||
if (dir != current_process->root) {
|
|
||||||
fs_close(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t open(const char *path) {
|
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;
|
||||||
@@ -203,7 +178,7 @@ static void exit(exit_code_t 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
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, __attribute__((unused)) uint64_t arg4) {
|
||||||
switch (func) {
|
switch (func) {
|
||||||
case SYSCALL_READ:
|
case SYSCALL_READ:
|
||||||
return read(arg1, arg2, (char *)arg3);
|
return read(arg1, arg2, (char *)arg3);
|
||||||
@@ -215,8 +190,6 @@ uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t
|
|||||||
return chdir((const char *)arg1);
|
return chdir((const char *)arg1);
|
||||||
case SYSCALL_SPAWN:
|
case SYSCALL_SPAWN:
|
||||||
return spawn((const char *)arg1, arg2, (const char **)arg3);
|
return spawn((const char *)arg1, arg2, (const char **)arg3);
|
||||||
case SYSCALL_READDIR:
|
|
||||||
return readdir((const char *)arg1, arg2, arg3, (char *)arg4);
|
|
||||||
case SYSCALL_OPEN:
|
case SYSCALL_OPEN:
|
||||||
return open((const char *)arg1);
|
return open((const char *)arg1);
|
||||||
case SYSCALL_CLOSE:
|
case SYSCALL_CLOSE:
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#define SYSCALL_GETCWD 2
|
#define SYSCALL_GETCWD 2
|
||||||
#define SYSCALL_CHDIR 3
|
#define SYSCALL_CHDIR 3
|
||||||
#define SYSCALL_SPAWN 4
|
#define SYSCALL_SPAWN 4
|
||||||
#define SYSCALL_READDIR 5
|
|
||||||
#define SYSCALL_OPEN 6
|
#define SYSCALL_OPEN 6
|
||||||
#define SYSCALL_CLOSE 7
|
#define SYSCALL_CLOSE 7
|
||||||
#define SYSCALL_EXIT 60
|
#define SYSCALL_EXIT 60
|
||||||
|
|||||||
+18
-11
@@ -6,21 +6,28 @@
|
|||||||
#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 i = 0;
|
uint64_t fd = open(path);
|
||||||
while (1) {
|
|
||||||
char out[100];
|
if (fd == (uint64_t)-1) {
|
||||||
uint64_t s = readdir(path, i, 100, out);
|
|
||||||
if (!s) {
|
|
||||||
return EXIT_CODE_OK;
|
|
||||||
}
|
|
||||||
if (s == (uint64_t)-1) {
|
|
||||||
PRINT_S("ls: path does not exist\n");
|
PRINT_S("ls: path does not exist\n");
|
||||||
return EXIT_CODE_GENERAL_FAILURE;
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
PRINT_D(out);
|
|
||||||
PRINT_S("\n");
|
char buffer[100];
|
||||||
i++;
|
uint64_t bytes;
|
||||||
|
while ((bytes = read(fd, 100, buffer))) {
|
||||||
|
if (bytes == (uint64_t)-1) {
|
||||||
|
PRINT_S("ls: could not read directory\n");
|
||||||
|
close(fd);
|
||||||
|
return EXIT_CODE_GENERAL_FAILURE;
|
||||||
}
|
}
|
||||||
|
write(1, buffer, bytes - 1);
|
||||||
|
PRINT_S("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit_code_t main(uint64_t argc, const char **argv) {
|
exit_code_t main(uint64_t argc, const char **argv) {
|
||||||
|
|||||||
@@ -30,13 +30,6 @@ spawn:
|
|||||||
syscall
|
syscall
|
||||||
ret
|
ret
|
||||||
|
|
||||||
global readdir
|
|
||||||
readdir:
|
|
||||||
mov r10, rcx
|
|
||||||
mov rax, 5
|
|
||||||
syscall
|
|
||||||
ret
|
|
||||||
|
|
||||||
global open
|
global open
|
||||||
open:
|
open:
|
||||||
mov rax, 6
|
mov rax, 6
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ uint64_t chdir(const char *path);
|
|||||||
|
|
||||||
exit_code_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 open(const char *path);
|
uint64_t open(const char *path);
|
||||||
|
|
||||||
uint64_t close(uint64_t fd);
|
uint64_t close(uint64_t fd);
|
||||||
|
|||||||
Reference in New Issue
Block a user