diff --git a/userprog/syscall_write.c b/userprog/syscall_write.c index e866540fc8ac6aa518dc0dc925028c95f7ca36db..98aeb142ddd9b52187ac7dbba13d30a3043bb960 100644 --- a/userprog/syscall_write.c +++ b/userprog/syscall_write.c @@ -4,10 +4,16 @@ * Authored by Joshua Saxby */ #include <stdio.h> +#include "filesys/file.h" #include "lib/kernel/stdio.h" #include "system_calls.h" #include "threads/interrupt.h" +// the maximum number of characters to write to the console in one go +static const size_t CONSOLE_WRITE_MAX_SIZE = 255; + +static void write_to_console(const char* buffer, size_t size); + void syscall_write(struct intr_frame *f) { // first argument is syscall code (already handled) int fd = *((int*)f->esp + 1); // file descriptor is second argument @@ -15,14 +21,35 @@ void syscall_write(struct intr_frame *f) { unsigned size = *((unsigned*)((int*)f->esp + 3)); // size to write is fourth // writing to stdout or stderr (fd in {1, 2}) is a special case switch (fd) { - case 1: - // case 2: - // TODO: split up output into reasonable-sized chunks - putbuf((const char*)buffer, size); + case 1: // stdin + case 2: // stderr + write_to_console((const char*)buffer, size); f->eax = size; break; - default: - // XXX: unimplemented for now - break; + default: { + // otherwise, we need to write to a file denoted by fd + struct file* file_to_write = (struct file*)fd; + f->eax = file_write(file_to_write, buffer, size); + break; + } + } +} + +static void write_to_console(const char* buffer, size_t size) { + // refuse to write more than a certain limit of chars at a time to console + if (size <= CONSOLE_WRITE_MAX_SIZE) { + putbuf(buffer, size); + } else { + const char* cursor = buffer; + size_t chars_left = size; + do { + size_t write_amount = ( + chars_left < CONSOLE_WRITE_MAX_SIZE + ? chars_left : CONSOLE_WRITE_MAX_SIZE + ); + putbuf(cursor, write_amount); + cursor += write_amount; + chars_left -= write_amount; + } while (chars_left > 0); } }