summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/user/app/shell/builtins.c2
-rw-r--r--src/user/lib/file.c39
-rw-r--r--src/user/lib/include/stdio.h2
3 files changed, 27 insertions, 16 deletions
diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c
index e272cf3..d0a2e3a 100644
--- a/src/user/app/shell/builtins.c
+++ b/src/user/app/shell/builtins.c
@@ -13,7 +13,7 @@ static void cmd_cat(int argc, const char **argv) {
if (argv[1])
file = fopen(argv[1], "r");
else
- file = file_clone(stdin);
+ file = file_clone(stdin, "r");
if (!file) {
eprintf("couldn't open");
diff --git a/src/user/lib/file.c b/src/user/lib/file.c
index b55a19d..ffea99b 100644
--- a/src/user/lib/file.c
+++ b/src/user/lib/file.c
@@ -18,21 +18,31 @@ FILE *fopen(const char *path, const char *mode) {
FILE *f;
handle_t h;
int flags = 0;
- if (mode[0] == 'w' || mode[0] == 'a')
- flags |= OPEN_CREATE;
-
- h = _syscall_open(path, strlen(path), flags);
- if (h < 0) {
- errno = -h;
+ if (path && path[0] == '!') {
+ /* special handling for "!files" */
+ path++;
+ if (!strcmp(path, "stdin")) return file_clone(stdin, mode);
+ if (!strcmp(path, "stdout")) return file_clone(stdout, mode);
+ if (!strcmp(path, "stderr")) return file_clone(stderr, mode);
+ errno = -1;
return NULL;
- }
+ } else {
+ if (mode[0] == 'w' || mode[0] == 'a')
+ flags |= OPEN_CREATE;
- if (mode[0] == 'w')
- _syscall_write(h, NULL, 0, 0, WRITE_TRUNCATE);
+ h = _syscall_open(path, strlen(path), flags);
+ if (h < 0) {
+ errno = -h;
+ return NULL;
+ }
- f = fdopen(h, mode);
- if (!f) close(h);
- return f;
+ if (mode[0] == 'w')
+ _syscall_write(h, NULL, 0, 0, WRITE_TRUNCATE);
+
+ f = fdopen(h, mode);
+ if (!f) close(h);
+ return f;
+ }
}
FILE *freopen(const char *path, const char *mode, FILE *f) {
@@ -70,12 +80,12 @@ FILE *fdopen(int fd, const char *mode) {
return f;
}
-FILE *file_clone(const FILE *f) {
+FILE *file_clone(const FILE *f, const char *mode) {
handle_t h = _syscall_dup(f->fd, -1, 0);
FILE *f2;
if (h < 0) return NULL;
- f2 = fdopen(h, "r+");
+ f2 = fdopen(h, mode);
if (!f2) {
close(h);
return NULL;
@@ -105,6 +115,7 @@ size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict f) {
return 0;
while (pos < total) {
+ // TODO shouldn't repeat reads
long res = _syscall_read(f->fd, buf + pos, total - pos, f->pos);
if (res < 0) {
f->error = true;
diff --git a/src/user/lib/include/stdio.h b/src/user/lib/include/stdio.h
index fd4a676..74c5230 100644
--- a/src/user/lib/include/stdio.h
+++ b/src/user/lib/include/stdio.h
@@ -25,7 +25,7 @@ extern FILE *const stdin, *const stdout, *const stderr;
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 *);
+FILE *file_clone(const FILE *, const char *mode);
int fclose(FILE *);
int fflush(FILE *f);