D4: the machine makes directories too

mkdir and rmdir are the machine's own now, and a file goes where its path says
rather than always in the root. A disk can be organised without the host tool
touching it.

Everything below the surface works in terms of a directory and a name rather
than a path. sbfsWalkParent splits the last name off, walks the rest, and hands
back the two - and the separator stays on the end of the head, which is what
makes one rule cover every kind of path: "/x" leaves "/", which is the root;
"x" leaves nothing, which is where the machine already is; and "A/x" leaves
"A/", which is neither and needs no special case to say so.

Saving works in those two as well, and had to. The careful order a save uses -
make a temporary, write it, delete the original, rename the temporary - only
works if the temporary is made in the SAME directory as the file, because the
rename at the end changes a name and does not move anything. Renaming to a path
naming a different directory is refused for that reason, rather than quietly
being a lie the disk goes along with.

Three things this cost, all found by running it:

mkdir Apps/Deep made /Apps/Apps. The leaf was worked out into SbfsWanted and
then the head was walked - and walking goes through sbfsPathNext, which puts
every name it meets into SbfsWanted on the way past. The head's last name
landed exactly where the leaf was. It has somewhere of its own now.

rmdir took a directory with something still in it, which is the one failure the
whole design is arranged to prevent. Looking for children clobbered DP2 and
rebuilt it from the buffer and the entry count with the subtraction the wrong
way round, so the pointer walked off the end of the block and found nothing.
The comparison goes through a CALL now, like the two beside it, and DP2 comes
back on the entry because a RET puts it there. SplitDisk's "in use but not
reachable from the root" line is what caught it.

Refusing a name longer than twenty two used to read the twenty third character
of a shorter one, which is somebody else's string. It is measured now.

Tests/agree.sh is new and is the gate this rung was for: the same disk built
twice, once with SplitDisk and once with CosmOS, compared byte for byte. The
two share no code and only a written specification, and every field one writes
and the other only reads is checked there and nowhere else - which entry a
thing lands in, which block, what a directory's unused fields hold, the
version, the free count. It caught a wrong parent immediately when that was
broken on purpose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-25 09:18:29 -04:00
co-authored by Claude Opus 5
parent 36ce9f6ccf
commit da91a36d92
13 changed files with 948 additions and 43 deletions
+2
View File
@@ -4,6 +4,8 @@ load <file> read a program off the disk
run [words] start what was loaded, and tell it those words
<name> [words] look where you are and then in /Apps, and start that
cd [path] go to a directory, or to the root with nothing after it
mkdir <path> make a directory
rmdir <path> remove an empty one
delete <file> take it off the disk
rename <file> <to> call it something else
monitor look at memory, change it, and jump into it
+2 -2
View File
@@ -3,11 +3,11 @@ CosmOS
> two stops, and what the registers were at each
break at 400E
A 11 B 22 Q 00 status 00
DP0 2030 DP1 082E DP2 0000 DP3 4000 SP FFFF
DP0 2030 DP1 09BC DP2 0000 DP3 4000 SP FFFF
press a key
break at 4023
A 44 B 55 Q 00 status 00
DP0 2000 DP1 082E DP2 0000 DP3 4000 SP FFF5
DP0 2000 DP1 09BC DP2 0000 DP3 4000 SP FFF5
press a key
carried on to the end
finished
+27
View File
@@ -0,0 +1,27 @@
CosmOS
> 0 files
> made
> made
> made
> Apps <dir>
Notes <dir>
0 files, 2 directories
> /Apps> Deep <dir>
0 files, 1 directory
/Apps> cannot make that: check the path, the name, and whether it is taken
/Apps> made
/Apps> /Notes> Deep <dir>
0 files, 1 directory
/Notes> cannot remove that: it must be a directory, and empty
/Notes> removed
/Notes> that is a directory
/Notes> removed
/Notes> > cannot make that: check the path, the name, and whether it is taken
> cannot remove that: it must be a directory, and empty
> cannot remove that: it must be a directory, and empty
> removed
> removed
> 0 files
> halted
Execution halted.
[exit 0]
+2
View File
@@ -21,6 +21,8 @@ load <file> read a program off the disk
run [words] start what was loaded, and tell it those words
<name> [words] look where you are and then in /Apps, and start that
cd [path] go to a directory, or to the root with nothing after it
mkdir <path> make a directory
rmdir <path> remove an empty one
delete <file> take it off the disk
rename <file> <to> call it something else
monitor look at memory, change it, and jump into it