diff options
author | Anton Kling <anton@kling.gg> | 2023-11-22 21:07:36 +0100 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2023-11-22 21:07:36 +0100 |
commit | bf2d121899c028eed140b679b4e059db8af91fe8 (patch) | |
tree | 3e3fe6cc4c6cfe7090fb8ab8a2141f8ad9788631 /userland | |
parent | f0af695b6c3289a041e8fce8926721063796c596 (diff) |
LibC: Add fflush() and buffer writes to file descriptors
Diffstat (limited to 'userland')
-rw-r--r-- | userland/libc/include/stdio.h | 10 | ||||
-rw-r--r-- | userland/libc/libc.c | 9 | ||||
-rw-r--r-- | userland/libc/stdio/fflush.c | 3 | ||||
-rw-r--r-- | userland/libc/stdio/stdin.c | 25 | ||||
-rw-r--r-- | userland/libc/stdio/vdprintf.c | 65 | ||||
-rw-r--r-- | userland/libc/stdio/vfprintf.c | 1 |
6 files changed, 40 insertions, 73 deletions
diff --git a/userland/libc/include/stdio.h b/userland/libc/include/stdio.h index 43700e0..8ac4e59 100644 --- a/userland/libc/include/stdio.h +++ b/userland/libc/include/stdio.h @@ -28,6 +28,7 @@ struct __IO_FILE { size_t (*write)(FILE *, const unsigned char *, size_t); size_t (*read)(FILE *, unsigned char *, size_t); int (*seek)(FILE *, long, int); + void (*fflush)(FILE *); long offset_in_file; int buffered_char; int has_buffered_char; @@ -35,6 +36,8 @@ struct __IO_FILE { uint8_t is_eof; uint8_t has_error; uint64_t file_size; + uint8_t *write_buffer; + uint32_t write_buffer_stored; uint8_t *read_buffer; uint32_t read_buffer_stored; uint32_t read_buffer_has_read; @@ -44,6 +47,7 @@ struct __IO_FILE { size_t write_fd(FILE *f, const unsigned char *s, size_t l); size_t read_fd(FILE *f, unsigned char *s, size_t l); int seek_fd(FILE *stream, long offset, int whence); +void fflush_fd(FILE *f); typedef struct { int fd; @@ -114,8 +118,6 @@ int fsetpos(FILE *stream, const fpos_t *pos); int fgetpos(FILE *restrict stream, fpos_t *restrict pos); char *tmpnam(char *s); int rename(const char *old, const char *new); -size_t getdelim(char ** lineptr, size_t * n, - int delimiter, FILE * stream); -size_t getline(char ** lineptr, size_t * n, - FILE * stream); +size_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *stream); +size_t getline(char **lineptr, size_t *n, FILE *stream); #endif diff --git a/userland/libc/libc.c b/userland/libc/libc.c index dafd502..5fcf9fa 100644 --- a/userland/libc/libc.c +++ b/userland/libc/libc.c @@ -105,7 +105,7 @@ FILE *__stderr_FILE; #define stderr __stderr_FILE void _libc_setup(void) { - __stdin_FILE = malloc(sizeof(FILE)); + __stdin_FILE = calloc(1, sizeof(FILE)); __stdin_FILE->write = write_fd; __stdin_FILE->read = read_fd; __stdin_FILE->seek = NULL; @@ -113,8 +113,9 @@ void _libc_setup(void) { __stdin_FILE->has_error = 0; __stdin_FILE->cookie = NULL; __stdin_FILE->fd = 0; + __stdin_FILE->fflush = fflush_fd; - __stdout_FILE = malloc(sizeof(FILE)); + __stdout_FILE = calloc(1, sizeof(FILE)); __stdout_FILE->write = write_fd; __stdout_FILE->read = read_fd; __stdout_FILE->is_eof = 0; @@ -122,14 +123,16 @@ void _libc_setup(void) { __stdout_FILE->seek = NULL; __stdout_FILE->cookie = NULL; __stdout_FILE->fd = 1; + __stdout_FILE->fflush = fflush_fd; - __stderr_FILE = malloc(sizeof(FILE)); + __stderr_FILE = calloc(1, sizeof(FILE)); __stderr_FILE->write = write_fd; __stderr_FILE->read = read_fd; __stderr_FILE->is_eof = 0; __stderr_FILE->has_error = 0; __stderr_FILE->cookie = NULL; __stderr_FILE->fd = 2; + __stderr_FILE->fflush = fflush_fd; } // Functions preserve the registers ebx, esi, edi, ebp, and esp; while diff --git a/userland/libc/stdio/fflush.c b/userland/libc/stdio/fflush.c index 7a37c79..3042efa 100644 --- a/userland/libc/stdio/fflush.c +++ b/userland/libc/stdio/fflush.c @@ -2,6 +2,7 @@ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html int fflush(FILE *stream) { - // FIXME: Implement + if (stream->fflush) + stream->fflush(stream); return 0; } diff --git a/userland/libc/stdio/stdin.c b/userland/libc/stdio/stdin.c index 2ced1a0..c424cc5 100644 --- a/userland/libc/stdio/stdin.c +++ b/userland/libc/stdio/stdin.c @@ -2,7 +2,7 @@ #include <stdio.h> #include <unistd.h> -size_t write_fd(FILE *f, const unsigned char *s, size_t l) { +size_t raw_write_fd(FILE *f, const unsigned char *s, size_t l) { int rc = pwrite(f->fd, s, l, f->offset_in_file); if (rc == -1) { f->has_error = 1; @@ -12,6 +12,27 @@ size_t write_fd(FILE *f, const unsigned char *s, size_t l) { return rc; } +void fflush_fd(FILE *f) { + raw_write_fd(f, f->write_buffer, f->write_buffer_stored); + f->write_buffer_stored = 0; +} + +size_t write_fd(FILE *f, const unsigned char *s, size_t l) { + if (!f->write_buffer) { + f->write_buffer = malloc(4096); + f->write_buffer_stored = 0; + } + if (l > 4096) { + return raw_write_fd(f, s, l); + } + if (f->write_buffer_stored + l > 4096) { + fflush_fd(f); + } + memcpy(f->write_buffer + f->write_buffer_stored, s, l); + f->write_buffer_stored += l; + return l; +} + size_t non_cache_read_fd(FILE *f, unsigned char *s, size_t l) { int rc = pread(f->fd, s, l, f->offset_in_file); if (rc == 0) @@ -32,7 +53,7 @@ size_t read_fd(FILE *f, unsigned char *s, size_t l) { // syscalls if (l >= 4096) { // Invalidate the cache -f->read_buffer_stored = 0; + f->read_buffer_stored = 0; size_t rc = non_cache_read_fd(f, s, l); f->offset_in_file += rc; diff --git a/userland/libc/stdio/vdprintf.c b/userland/libc/stdio/vdprintf.c index b3fa065..2724c2e 100644 --- a/userland/libc/stdio/vdprintf.c +++ b/userland/libc/stdio/vdprintf.c @@ -3,75 +3,14 @@ #include <string.h> #include <unistd.h> -struct vd_cookie { - int fd; - char *buffer; - uint8_t buf_len; - uint8_t buf_used; - int sent_bytes; -}; - size_t min(size_t a, size_t b) { return (a < b) ? a : b; } -size_t vd_write(FILE *f, const unsigned char *s, size_t l) { - struct vd_cookie *c = f->cookie; - - int clear_buffer = 0; - size_t b_copy = min(l, c->buf_len - (c->buf_used)); - for (int i = 0; i < b_copy; i++) { - c->buffer[c->buf_used + i] = s[i]; - if (s[i] == '\n') - clear_buffer = 1; - } - c->buf_used += b_copy; - - if (clear_buffer) { - int rc = write(c->fd, c->buffer, c->buf_used); - c->buf_used = 0; - if (-1 == rc) { - return (size_t)-1; - } - c->sent_bytes += rc; - } - return l; -} - int vdprintf(int fd, const char *format, va_list ap) { FILE f = { .write = write_fd, .fd = fd, + .fflush = fflush_fd, + .write_buffer = NULL, }; return vfprintf(&f, format, ap); - // return -1; - /* -char buffer[32]; -struct vd_cookie c = {.fd = fd, - .buffer = buffer, - .buf_len = 32, - .buf_used = 0, - .sent_bytes = 0}; -FILE f = { -.write = vd_write, -.cookie = &c, -}; - -// If an output error was encountered, these functions shall return a -// negative value and set errno to indicate the error. -if (-1 == vfprintf(&f, format, ap)) -return -1; - -// Upon successful completion, the dprintf(), -// fprintf(), and printf() functions shall return the number of bytes -// transmitted. - -if(0 == c.buf_used) -return c.sent_bytes; - -// First the current buffer needs to be cleared -int rc = write(fd, buffer, c.buf_used); -if (-1 == rc) { -return -1; -} -c.sent_bytes += rc; -return c.sent_bytes;*/ } diff --git a/userland/libc/stdio/vfprintf.c b/userland/libc/stdio/vfprintf.c index f8d56ea..b2d4902 100644 --- a/userland/libc/stdio/vfprintf.c +++ b/userland/libc/stdio/vfprintf.c @@ -249,5 +249,6 @@ int vfprintf(FILE *f, const char *fmt, va_list ap) { precision = -1; } } + fflush(f); return rc; } |