summaryrefslogtreecommitdiff
path: root/userland
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-11-22 21:07:36 +0100
committerAnton Kling <anton@kling.gg>2023-11-22 21:07:36 +0100
commitbf2d121899c028eed140b679b4e059db8af91fe8 (patch)
tree3e3fe6cc4c6cfe7090fb8ab8a2141f8ad9788631 /userland
parentf0af695b6c3289a041e8fce8926721063796c596 (diff)
LibC: Add fflush() and buffer writes to file descriptors
Diffstat (limited to 'userland')
-rw-r--r--userland/libc/include/stdio.h10
-rw-r--r--userland/libc/libc.c9
-rw-r--r--userland/libc/stdio/fflush.c3
-rw-r--r--userland/libc/stdio/stdin.c25
-rw-r--r--userland/libc/stdio/vdprintf.c65
-rw-r--r--userland/libc/stdio/vfprintf.c1
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;
}