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:
@@ -342,3 +342,14 @@ for i in 1 2 3 4 5 6 7 8; do
|
||||
DEEPPATH="$DEEPPATH/abcdefghijklmnopqrst0$i"
|
||||
"$TOOL" mkdir "$DISKS/deep.img" "$DEEPPATH" >/dev/null
|
||||
done
|
||||
|
||||
# A disk whose superblock claims a directory bigger than the parent field can name. Entry
|
||||
# 65535 has no parent number - index plus one wraps to zero, which is the root - so
|
||||
# anything created inside it lands in the root instead while the tool reports success.
|
||||
#
|
||||
# THE CLAIM IS ALL THAT IS NEEDED, so this is a small disk that lies rather than a sixteen
|
||||
# megabyte one that tells the truth. Mounting reads block 0 and gets as far as the
|
||||
# geometry, which is where it is refused. SplitDisk will not make one of these any more,
|
||||
# so the superblock is written by hand.
|
||||
"$TOOL" format "$DISKS/bigdir.img" 64 2 >/dev/null
|
||||
printf '\x20\x00' | dd of="$DISKS/bigdir.img" bs=1 seek=10 conv=notrunc status=none
|
||||
|
||||
Reference in New Issue
Block a user