diff --git a/Makefile.build b/Makefile.build index 2d43ff2d270d8e2caff7a87971321c7e590617ff..d136a6f1c1e8fbc60df45bc898ef0d96fd7f53ed 100644 --- a/Makefile.build +++ b/Makefile.build @@ -71,6 +71,7 @@ userprog_SRC += userprog/syscall_create.c userprog_SRC += userprog/syscall_remove.c userprog_SRC += userprog/syscall_write.c userprog_SRC += userprog/file_descriptors_map.c +userprog_SRC += userprog/syscall_read.c # No virtual memory code yet. #vm_SRC = vm/file.c # Some file. diff --git a/userprog/syscall.c b/userprog/syscall.c index e6abc56803da28b385bb69fa7b493d30496ddcc9..fb62a79e4a8e648b19c08c774ef33dfcef5ca417 100644 --- a/userprog/syscall.c +++ b/userprog/syscall.c @@ -79,6 +79,9 @@ syscall_handler (struct intr_frame *f UNUSED) case SYSCALL_OPEN: syscall_open(f); break; + case SYSCALL_READ: + syscall_read(f); + break; case SYSCALL_FILESIZE: syscall_filesize(f); break; diff --git a/userprog/syscall_read.c b/userprog/syscall_read.c new file mode 100644 index 0000000000000000000000000000000000000000..67f7d9858ea87ecc23b717a9b8dee1353d323abe --- /dev/null +++ b/userprog/syscall_read.c @@ -0,0 +1,42 @@ +/* + * The Read System Call + * + * Authored by Joshua Saxby + */ +#include <stddef.h> +#include "devices/input.h" +#include "filesys/file.h" +#include "system_calls.h" +#include "threads/interrupt.h" + +void syscall_read(struct intr_frame *f) { + // first argument is syscall code (already handled) + int fd = *((int*)f->esp + 1); // file descriptor is second argument + char* buffer = (void*)(*((int*)f->esp + 2)); // buffer is third argument + unsigned size = *((unsigned*)((int*)f->esp + 3)); // size to read is fourth + // reading from stdin (keyboard) is a special case + switch (fd) { + case 0: { + // read from keyboard for as many bytes as requested + for (size_t i = 0; i < size; i++) { + *(buffer + i) = input_getc(); + } + f->eax = size; + break; + } + case 1: // stdout + case 2: // stderr + f->eax = -1; // it is a mistake to attempt to read from stdout or stderr + break; + default: { + // otherwise, we need to read from a file denoted by fd + struct file* file_to_read = get_associated_file_pointer(fd); + if (file_to_read == NULL) { + f->eax = -1; // invalid file descriptor + break; + } + f->eax = file_read(file_to_read, buffer, size); + break; + } + } +} diff --git a/userprog/system_calls.h b/userprog/system_calls.h index ce7ae18823f34dd39916c550db655291e0f7c6d3..b22867040cc55488aa61fdffd7dca93e74638288 100644 --- a/userprog/system_calls.h +++ b/userprog/system_calls.h @@ -36,6 +36,13 @@ void syscall_wait(struct intr_frame *f); */ void syscall_create(struct intr_frame *f); +/* + * Reads size bytes from the file open as fd into buffer. + * Returns the number of bytes actually read (0 at end of file), or -1 if the + * file could not be read (due to a condition other than end of file). + */ +void syscall_read(struct intr_frame *f); + /* * Writes size bytes from buffer to the open file fd. * Returns the number of bytes actually written, which may be less than size if