From c920ea363635ae03e3c3575271d9acbe29d63e6d Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Wed, 30 Apr 2025 10:50:37 -0400 Subject: inflate / deflate --- user/deflate.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ user/include/unistd.h | 26 +++++++++++++++++++- user/inflate.c | 41 +++++++++++++++++++++++++++++++ user/lib/fopen.c | 37 ++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 user/deflate.c create mode 100644 user/inflate.c create mode 100644 user/lib/fopen.c diff --git a/user/deflate.c b/user/deflate.c new file mode 100644 index 0000000..35018d0 --- /dev/null +++ b/user/deflate.c @@ -0,0 +1,68 @@ +#include +#include + +int main(int argc, char **argv) +{ + FILE *in, *out; + int length_bytes = 0, length = 0, tracking = EOF, next; + + if (argc != 3) { + fprintf(stderr, "usage: deflate in out\n"); + return 1; + } + + in = fopen(argv[1], "rb"); + if (in == NULL) { + fprintf(stderr, "cannot read: %s\n", argv[1]); + return 1; + } + + out = fopen(argv[2], "wb"); + if (out == NULL) { + fprintf(stderr, "cannot write %s\n", argv[2]); + return 1; + } + + while (next = getc(in), next != EOF) { + int diff; + + if (tracking == EOF) { + tracking = next; + length = 1; + length_bytes = 0; + continue; + } + + diff = tracking - next; + diff = diff < 1 ? -diff : diff; + if (diff < 2) + next = tracking; + + if (tracking == next) { + length++; + if (length == 255) { + length_bytes++; + length = 0; + } + continue; + } + + // write output + for (int i = 0; i < length_bytes; i++) + putc(255, out); + putc(length, out); + putc(tracking, out); + tracking = next; + length = 1; + length_bytes = 0; + } + + if (length) { + for (int i = 0; i < length_bytes; i++) + putc(255, out); + putc(length, out); + putc(tracking, out); + } + + return 0; +} diff --git a/user/include/unistd.h b/user/include/unistd.h index f080917..cad3a81 100644 --- a/user/include/unistd.h +++ b/user/include/unistd.h @@ -16,6 +16,20 @@ typedef unsigned short pid_t; +enum { + S_SET = 0, + S_CUR = 1, + S_END = 2, +}; + +enum { + O_CREATE = 0x01, + O_RDONLY = 0x02, + O_WRONLY = 0x04, + O_APPEND = 0x08, + O_RDWR = O_RDONLY | O_WRONLY, +}; + /** * terminates the calling process and does not return. * @@ -65,7 +79,7 @@ extern void exec(const char *filename, char **args); * @param filename - the name of the file to open * @return the file descriptior of the open file or a negative error code. */ -extern int open(const char *filename); +extern int open(const char *filename, int flags); /** * closes a stream with the given file descriptior @@ -94,6 +108,16 @@ extern int read(int fd, void *buffer, size_t nbytes); */ extern int write(int fd, const void *buffer, size_t nbytes); +/** + * seek a file + * + * @param fd - file stream to seek + * @param off - offset to seek + * @param whence - whence to seek + * @return 0 on success, or an error code + */ +extern int seek(int fd, long int off, int whence); + /** * gets the pid of the calling process * diff --git a/user/inflate.c b/user/inflate.c new file mode 100644 index 0000000..2f7a3d6 --- /dev/null +++ b/user/inflate.c @@ -0,0 +1,41 @@ +#include +#include + +int main(int argc, char **argv) +{ + FILE *in, *out; + int length, value; + + if (argc != 3) { + fprintf(stderr, "usage: inflate in out\n"); + return 1; + } + + in = fopen(argv[1], "rb"); + if (in == NULL) { + fprintf(stderr, "cannot read: %s\n", argv[1]); + return 1; + } + + out = fopen(argv[2], "wb"); + if (out == NULL) { + fprintf(stderr, "cannot write %s\n", argv[2]); + return 1; + } + + while (1) { + length = getc(in); + value = getc(in); + + if (length == EOF) + break; + + if (value == EOF) + return 1; + + for (int i = 0; i < length; i++) + putc(value, out); + } + + return 0; +} diff --git a/user/lib/fopen.c b/user/lib/fopen.c new file mode 100644 index 0000000..cb2529f --- /dev/null +++ b/user/lib/fopen.c @@ -0,0 +1,37 @@ +#include +#include + +FILE *fopen(const char *restrict filename, const char *restrict modes) +{ + int flags = 0; + int fd; + + char c; + while (c = *modes, c) { + switch (c) { + case 'r': + flags |= O_RDONLY; + break; + case 'w': + flags |= O_CREATE | O_WRONLY; + break; + case 'a': + flags |= O_APPEND; + break; + case '+': + flags |= O_RDWR; + break; + default: + return NULL; + } + } + + if (flags == 0) + return NULL; + + fd = open(filename, flags); + if (fd < 0) + return NULL; + + return (FILE *)(uintptr_t)fd; +} -- cgit v1.2.3-freya