From fc6f690727aac2b5c9bd368f9b13188fb0ba36a7 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 16 Jul 2026 13:07:28 +0200 Subject: fs: reject open()/read() on a directory (EISDIR) open() now checks the target's inode type: opening a directory as a file returns $FE (EISDIR) instead of a valid fd, so 'cat docs' no longer streams the raw directory block as bytes. cat reports 'is a directory'; wc/head/save treat any invalid fd (>3) as an open failure. (ls is unaffected - it uses the structural opendir/list path, not open/getb.) --- c/cat.c | 3 ++- c/gbos.h | 1 + c/head.c | 4 ++-- c/save.c | 2 +- c/wc.c | 4 ++-- src/fs.asm | 10 ++++++++++ 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/c/cat.c b/c/cat.c index dde58cd..790cb88 100644 --- a/c/cat.c +++ b/c/cat.c @@ -6,7 +6,8 @@ void main(void) { if (argc > 0) { unsigned char fd = open(argv[0], O_READ); int ch; - if (fd == NOFD) { puts("cat: no such file"); nl(); return; } + if (fd == EISDIR) { puts("cat: is a directory"); nl(); return; } + if (fd == NOFD) { puts("cat: no such file"); nl(); return; } while ((ch = fgetc(fd)) >= 0) putc((char)ch); close(fd); } else { diff --git a/c/gbos.h b/c/gbos.h index c93414f..2a99c0e 100644 --- a/c/gbos.h +++ b/c/gbos.h @@ -34,6 +34,7 @@ void poweroff(void); /* clean emulator shutdown (saves) */ #define O_READ 0 #define O_WRITE 1 #define NOFD 0xFF +#define EISDIR 0xFE /* open() failed: path is a directory */ /* process control (c/libc.s) */ unsigned char fork(void); diff --git a/c/head.c b/c/head.c index e8bf846..3298e54 100644 --- a/c/head.c +++ b/c/head.c @@ -16,10 +16,10 @@ void main(void) { } if (fname) { fd = open(fname, O_READ); - if (fd == NOFD) { puts("head: no such file"); nl(); return; } + if (fd > 3) { puts("head: no such file"); nl(); return; } } for (;;) { - if (fd == NOFD) { char c = readc(); if (c == EOF) break; ch = c; } + if (fd > 3) { char c = readc(); if (c == EOF) break; ch = c; } else { ch = fgetc(fd); if (ch < 0) break; } if (lines < n) putc((char)ch); if (ch == '\n') lines++; diff --git a/c/save.c b/c/save.c index dd2b8cd..1755fea 100644 --- a/c/save.c +++ b/c/save.c @@ -7,7 +7,7 @@ void main(void) { char c; if (argc < 1) { puts("usage: save "); nl(); return; } fd = open(argv[0], O_WRITE); - if (fd == NOFD) { puts("save: cannot create"); nl(); return; } + if (fd > 3) { puts("save: cannot create"); nl(); return; } for (;;) { c = readc(); if (c == EOF) break; diff --git a/c/wc.c b/c/wc.c index 424876d..4fa48ee 100644 --- a/c/wc.c +++ b/c/wc.c @@ -14,10 +14,10 @@ void main(void) { for (i = 0; i < argc; i++) if (argv[i][0] != '-') { fname = argv[i]; break; } if (fname) { fd = open(fname, O_READ); - if (fd == NOFD) { puts("wc: no such file"); nl(); return; } + if (fd > 3) { puts("wc: no such file"); nl(); return; } } for (;;) { - if (fd == NOFD) { char c = readc(); if (c == EOF) break; ch = c; } + if (fd > 3) { char c = readc(); if (c == EOF) break; ch = c; } else { ch = fgetc(fd); if (ch < 0) break; } chars++; if (ch == '\n') lines++; diff --git a/src/fs.asm b/src/fs.asm index d543b0f..a4ad77e 100644 --- a/src/fs.asm +++ b/src/fs.asm @@ -678,6 +678,13 @@ sys_open:: ld [wFsDir], a call dir_find ; A = target inode or 0 ld [wFsInode], a + or a + jr z, .notdir ; doesn't exist yet: no type to check + call inode_ptr + ld a, [hl] ; I_TYPE + cp IT_DIR + jr z, .isdir ; can't open a directory as a file +.notdir ld a, [wFsMode] or a jr nz, .write @@ -730,6 +737,9 @@ sys_open:: ld a, c cp OF_MAX jr c, .ofl +.isdir + ld a, $FE ; EISDIR: is a directory + ret .fail ld a, $FF ret -- cgit v1.3.1-sl0p