summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/user/app/shell/builtins.c8
-rw-r--r--src/user/lib/file.c21
-rw-r--r--src/user/lib/file.h1
-rw-r--r--src/user/lib/include/stdio.h5
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);