aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authoruser <user@clank>2026-09-24 23:08:35 +0200
committeruser <user@clank>2026-09-24 23:08:35 +0200
commit1430515ad419f2fddeb0265337a0da043901411b (patch)
treee94c53cb7d59ca4826242b81afeb3de3c655d02e /docs
parentusr: touch, tr, rev, cut, uniq (diff)
downloadgbos-1430515ad419f2fddeb0265337a0da043901411b.tar.gz
gbos-1430515ad419f2fddeb0265337a0da043901411b.tar.xz
gbos-1430515ad419f2fddeb0265337a0da043901411b.zip
fs: hard links - ln(1), and rm that removes a NAME
gbfs has carried I_NLINK since the beginning and nothing ever incremented it, so a file could only have one name. SYS_LINK adds a second directory entry pointing at the same inode: the data is stored once, and both names read it. That makes rm's job different. It now decrements the link count and only frees the inode and its blocks when the LAST name goes - removing one of two links used to free blocks the other still pointed at. Refused, with the reasons that matter here: linking a directory (it would make a cycle the tree walkers cannot survive), an existing name, and anything under /bin, which is ROM. The syscall takes a request block because the trap needs HL for its dispatch table - and ln copies both paths to the stack first, since that block is a static living at $A000, on top of the command line it is reading.
Diffstat (limited to 'docs')
-rw-r--r--docs/internals.md9
1 files changed, 9 insertions, 0 deletions
diff --git a/docs/internals.md b/docs/internals.md
index f630025..c9f721a 100644
--- a/docs/internals.md
+++ b/docs/internals.md
@@ -234,6 +234,10 @@ blocks 4.. data blocks
the damage once something else touched the neighbouring inode.
- **One-block data cache.** Two files open at once thrash it: `cp` of a 3 KiB
file alternates read/write blocks per byte and takes ~25s. Correct, slow.
+- **Hard links.** `ln` is a second directory entry pointing at one inode;
+ `I_NLINK` existed from the start and nothing ever incremented it. `rm`
+ therefore removes a NAME: it decrements the count and only frees the inode
+ and its blocks when the last link goes.
- **Open modes** are read / write / append. There is no seek syscall, so
`O_APPEND` (open at EOF) is the only way to add to a file - which is what
makes `>>`, and therefore building a multi-line script on the device,
@@ -289,6 +293,11 @@ gbos programs are written in **C**, compiled with **SDCC** (the `sm83` port):
Arguments: the shell leaves `"cmd\0args\0"` at `$A000`; the child inherits it
through `fork`, `getargs()` returns the raw string, `argv_parse()` tokenizes.
+**The wall clock.** An MBC5 cart has no RTC, so `SYS_SETTIME` stores a unix
+stamp plus the tick it was taken at, and `SYS_GETTIME` adds the elapsed ticks
+back (`ntpdate` gets the stamp from SNTP, `date` formats it). It does not
+survive a power cycle - which is what `/rc` is for.
+
**Scripts.** `sh` is the same program interactively and as a script runner: it
asks `isatty()` (SYS_ISATTY: is stdin the console?) and, when stdin is a file,
drops the prompt and the echo. EOF ends that shell - only pid 1 on the console