diff options
author | dzwdz | 2022-08-19 15:37:42 +0200 |
---|---|---|
committer | dzwdz | 2022-08-19 15:37:42 +0200 |
commit | 05f93a814a9b5fa6b0f3223fc51566c84b92d158 (patch) | |
tree | b430bda5fd26c3cd7e273eda31171bf94100f9f1 | |
parent | 0ed2f796d7723af8321f35d4ef5e6781ea41e36d (diff) |
user/libc: fextflags, add nonbuffering mode for fread
useful for e.g. `hexdump -r /kdev/eth` to see packets as they come in
-rw-r--r-- | src/user/app/shell/builtins.c | 8 | ||||
-rw-r--r-- | src/user/lib/file.c | 21 | ||||
-rw-r--r-- | src/user/lib/file.h | 1 | ||||
-rw-r--r-- | src/user/lib/include/stdio.h | 5 |
4 files changed, 27 insertions, 8 deletions
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c index 4a7b79c..23a8221 100644 --- a/src/user/app/shell/builtins.c +++ b/src/user/app/shell/builtins.c @@ -26,6 +26,7 @@ static void cmd_cat(int argc, char **argv) { eprintf("couldn't open %s", argv[i]); return; } + if (!strcmp(argv[i], "!stdin")) fextflags(file, FEXT_NOFILL); for (;;) { int len = fread(buf, 1, sizeof buf, file); if (len <= 0) break; @@ -76,10 +77,11 @@ void cmd_hexdump(int argc, char **argv) { bool canonical = !strcmp(argv[0], "hd"); size_t readlen = ~0; size_t pos = 0; + bool raw = false; int c; optind = 0; - while ((c = getopt(argc, argv, "Cn:s:")) != -1) { + while ((c = getopt(argc, argv, "Cn:s:r")) != -1) { switch (c) { case 'C': canonical = true; @@ -90,6 +92,9 @@ void cmd_hexdump(int argc, char **argv) { case 's': pos = strtol(optarg, NULL, 0); break; + case 'r': /* "raw" mode, print data as soon as it's read without buffering */ + raw = true; + break; default: return; } @@ -103,6 +108,7 @@ void cmd_hexdump(int argc, char **argv) { eprintf("couldn't open %s", argv[optind]); return; } + if (raw) fextflags(file, FEXT_NOFILL); fseek(file, pos, SEEK_SET); bool skipped = false; while (pos < readlen) { diff --git a/src/user/lib/file.c b/src/user/lib/file.c index c8acbfb..f2b74b1 100644 --- a/src/user/lib/file.c +++ b/src/user/lib/file.c @@ -87,10 +87,11 @@ FILE *fdopen(int fd, const char *mode) { FILE *f; f = malloc(sizeof *f); if (!f) return NULL; + f->fd = fd; f->pos = mode[0] == 'a' ? -1 : 0; f->eof = false; - f->fd = fd; f->error = false; + f->extflags = 0; return f; } @@ -110,6 +111,12 @@ FILE *file_clone(const FILE *f, const char *mode) { return f2; } +int fextflags(FILE *f, int extflags) { + int old = f->extflags; + f->extflags = extflags; + return old; +} + static void fadvance(long amt, FILE *f) { bool pos_neg = f->pos < 0; f->pos += amt; @@ -133,16 +140,16 @@ size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict f) { if (res < 0) { f->error = true; errno = -res; - return pos/size; + break; } else if (res == 0) { f->eof = true; - return pos/size; - } else { - pos += res; - fadvance(res, f); + break; } + pos += res; + fadvance(res, f); + if (f->extflags & FEXT_NOFILL) break; } - return nitems; + return pos == total ? nitems : (pos/size); } size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict f) { diff --git a/src/user/lib/file.h b/src/user/lib/file.h index 8652566..604b070 100644 --- a/src/user/lib/file.h +++ b/src/user/lib/file.h @@ -6,4 +6,5 @@ struct _LIBC_FILE { long pos; bool eof; bool error; + int extflags; }; diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h index 4d9cf94..b0d34a7 100644 --- a/src/user/lib/include/stdio.h +++ b/src/user/lib/include/stdio.h @@ -9,6 +9,10 @@ #define SEEK_CUR 2 #define SEEK_END 3 +/* stop fread() from trying to fill the entire buffer before returning + * i.e. it will call _syscall_read() exactly once */ +#define FEXT_NOFILL 1 + int printf(const char *restrict fmt, ...); int fprintf(FILE *restrict f, const char *restrict fmt, ...); @@ -24,6 +28,7 @@ FILE *fopen(const char *path, const char *mode); FILE *freopen(const char *path, const char *mode, FILE *); FILE *fdopen(int fd, const char *mode); FILE *file_clone(const FILE *, const char *mode); +int fextflags(FILE *, int extflags); int fclose(FILE *); int fflush(FILE *f); |