Refuse a directory whose last entries cannot be named as a parent

A parent is an entry index PLUS ONE in two bytes, so entry 65535 has no
parent number: adding one wraps to zero, and zero is the root. Eight
entries to a block, so 8192 directory blocks reaches it and SplitDisk
formatted that happily.

It does not fail by refusing, which is why it was worth chasing rather than
reasoning about. Reproduced on a disk built for it: mkdir /deep/child, with
/deep at entry 65535, printed 'Made "/deep/child" as entry 0' and put child
in the ROOT. Listing /deep then showed nothing, because the search is for a
parent of 65536 and the entry carries zero - so the same mkdir succeeded
again, and again, and five entries called /child piled up in the root.
Duplicate names in one directory are the one thing rename refuses outright,
on the grounds that a search answers with whichever it meets first and the
rest can never be reached; this manufactured them one per attempt.

8191 blocks is the most, giving 65528 entries. Refused when formatting and
again when reading, in both implementations, because a disk claiming more
was made by something that never checked. On the machine only the high byte
of the count has to be looked at: anything from 0x20 up is too many.

Three checks, all of which fail with their guard removed. The machine's
disk claims the size rather than having it, so the test image is 64 blocks
that lie rather than sixteen megabytes that do not - mounting is refused at
the geometry, which is read out of block 0.
This commit is contained in:
Anachronaut
2026-08-25 23:47:02 -04:00
parent 634650cab9
commit ce0f18f4ef
9 changed files with 129 additions and 1 deletions
+8
View File
@@ -345,6 +345,14 @@ cosmosCopyCompare | CosmOS/Source/cosmos.asm | run | cosmosCop
# help and cd and exit from down there rather than just looking at the prompt. A prompt
# that is merely wrong is a cosmetic fault; this one was writing into other variables.
cosmosDeep | CosmOS/Source/cosmos.asm | run | cosmosDeep.in | - | disks/deep.img
# A disk claiming a directory of 8192 blocks, which is 65536 entries. The last of those is
# entry 65535, and the parent field is an index PLUS ONE in two bytes - so it wraps to
# zero, which means the root. Anything created in such a directory goes into the root
# while the caller is told it went where it asked, and looking there afterwards finds
# nothing, so the same create works again and again and fills the root with entries of one
# name. Refused at mount, which is the only place it can be refused once and for all.
cosmosBigDir | CosmOS/Source/cosmos.asm | run | cosmosBigDir.in | - | disks/bigdir.img
# Reading a disk that has directories on it. The machine can walk a path at this point but
# cannot make a directory, so the disk is built by the host tool and read here - which is
# the two implementations checking each other rather than either checking itself.