diff options
| author | user <user@clank> | 2026-09-24 12:48:51 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-24 12:48:51 +0200 |
| commit | 65b53de14dc6918db39b6ee6dc032f805182daad (patch) | |
| tree | 6af7b52262321a3cbe11e1d472ca2938df2fc37e /usr/mv.c | |
| parent | sh: run scripts, and >> redirection (diff) | |
| download | gbos-65b53de14dc6918db39b6ee6dc032f805182daad.tar.gz gbos-65b53de14dc6918db39b6ee6dc032f805182daad.tar.xz gbos-65b53de14dc6918db39b6ee6dc032f805182daad.zip | |
usr: ls -l, df, mv, tail, tee, sleep, help, poweroff
Filling in the core utilities the box was missing:
- ls -l: type, links and size, now that stat() exists. The screen is 40
columns, so it is "d 1 256 name", not the GNU sprawl. Sizes were
previously unknowable except one file at a time with wc -c.
- df: blocks and inodes, used and free, on the 32 KiB cart disk.
- mv: no rename syscall, so it is cp + rm - and the copy has to finish before
the source goes, or a failure loses the file.
- tail [-n N]: no seek syscall, so it streams the input through a ring of N
lines rather than jumping to the end. N is capped by that ring.
- tee: the missing half of a pipeline - `cat big | tee copy | wc -l`.
- sleep: the thing every script needs; the kernel counts 1/64 s ticks.
- help: lists every command the shell knows, walked out of the kernel's own
name table. The box previously had no way to tell you what it could do.
- poweroff: the only safe way to stop a gbos that has data on it. The cart's
battery RAM is written when the emulator exits cleanly, so killing it loses
the whole filesystem - it comes back "formatted". Found while testing /rc.
Diffstat (limited to '')
| -rw-r--r-- | usr/mv.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/usr/mv.c b/usr/mv.c new file mode 100644 index 0000000..76d9e62 --- /dev/null +++ b/usr/mv.c @@ -0,0 +1,51 @@ +#include "gbos.h" +/* mv SRC DST: there is no rename syscall, so this is cp + rm. The copy has to + * succeed before the source is removed - a half-copied DST plus a deleted SRC + * loses the file. */ + +static unsigned char streq(const char *a, const char *b) { + while (*a && *a == *b) { + a++; + b++; + } + return (unsigned char)(*a == *b); +} + +void main(void) { + char *argv[4]; + unsigned char argc = argv_parse(argv, 4); + unsigned char in, out; + int ch; + + if (argc < 2) { + puts("usage: mv SRC DST"); + nl(); + sexit(2); + } + if (streq(argv[0], argv[1])) sexit(0); /* nothing to do */ + + in = open(argv[0], O_READ); + if (in == EISDIR) { + puts("mv: SRC is a directory"); + nl(); + sexit(2); + } + if (in == NOFD) { + puts("mv: no such file: "); + puts(argv[0]); + nl(); + sexit(2); + } + out = open(argv[1], O_WRITE); + if (out > 3) { + puts("mv: cannot create "); + puts(argv[1]); + nl(); + close(in); + sexit(2); + } + while ((ch = fgetc(in)) >= 0) fputc(out, (char)ch); + close(in); + close(out); + fremove(argv[0]); /* only now is it safe */ +} |
