Copy joins the read and write streaming services: source and destination are both larger than Data Memory while the program owns one block. Compare reads two files through separate blocks and ignores the bytes past a short final block, which belong to neither file. Between them they exercise empty, exact-block, part-block and 84,000 byte files, and the host extracts the copy afterwards so that two native programs agreeing with each other is not the only oracle. Written by ChatGPT, as their headers record, along with the agree.sh section and the manifest entry that drive them. THIS SHOULD HAVE COME FIRST. The commit before it staged whole files rather than the hunks it meant, so its manifest already names these two programs while their source was still untracked - that commit will not build on its own. Left in place rather than rewritten, since the pair is right and only their order is wrong. NOTES.md is their review of the streaming work. The first item in it is fixed by the commit before this one; the rest are still open. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
107 lines
5.4 KiB
Markdown
107 lines
5.4 KiB
Markdown
# Delete me after these things are fixed
|
|
|
|
Temporary notes from the SBFS v2 and CosmOS review, in priority order.
|
|
|
|
## Streaming writes: reject a final size larger than the reservation
|
|
|
|
`osFileStart` reserves an extent and `osFileWrite` correctly refuses a block index outside
|
|
that extent. `sbfsStreamDone`, however, appears to accept a final block/tail count larger
|
|
than the extent reserved at the start. It writes the larger size into the descriptor and
|
|
then subtracts that size from the reservation when updating the free-block count.
|
|
|
|
A caller could reserve one block, finish while claiming two, and make the file descriptor
|
|
claim a neighboring block that was never allocated and may belong to another file.
|
|
|
|
Before deleting the old destination or modifying the temporary entry, compare the final
|
|
extent (`whole blocks + a possible tail block`) with the reserved extent. Refuse the commit
|
|
if the final extent is larger. Add tests for a final size that is smaller than, equal to,
|
|
and larger than the reservation, including tail/no-tail boundaries.
|
|
|
|
## Protect the temporary-file namespace
|
|
|
|
Whole-file saves and streamed writes use the fixed names `sbfs.part` and `sbfs.out`.
|
|
Starting another operation deletes an existing entry with the corresponding name as stale
|
|
temporary output, but these are otherwise legal user filenames. A real user file with one
|
|
of those names can therefore be deleted.
|
|
|
|
Possible resolutions:
|
|
|
|
- Reserve these names and refuse ordinary creation under them.
|
|
- Use a spare descriptor flag to identify temporary entries, and clean up by identity
|
|
rather than by name.
|
|
- Move temporary artifacts into a defined `/tmp` policy where appropriate. A stream's
|
|
temporary currently needs to be in the destination directory because rename changes a
|
|
name but not a parent, so `/tmp` alone may require adding a move operation.
|
|
|
|
Whatever rule is chosen should be enforced in both SplitDisk and the native SBFS code and
|
|
documented as part of the format or CosmOS policy.
|
|
|
|
## Correct stale CosmOS memory-map documentation
|
|
|
|
`Programs/CosmOS/README.md` currently gives overlapping Data Memory ranges:
|
|
|
|
```text
|
|
CosmOS: 0x0000 through 0x3FFF
|
|
Application: 0x2000 and above
|
|
```
|
|
|
|
The intended 8 KiB system allocation appears to be `0x0000` through `0x1FFF`, with
|
|
applications at `0x2000` and above. The minimal application in the same section still uses
|
|
the old bases (`0x2000` Program and `0x1000` Data), while current applications use `0x4000`
|
|
and `0x2000`. The opening comments in `cosmos.asm` and several monitor examples also retain
|
|
old addresses.
|
|
|
|
The README says `make test` checks these boundaries, but the overlapping table passed.
|
|
Strengthen `Tests/docs.sh` so the documented system endpoints and application bases are
|
|
parsed and checked for agreement/non-overlap.
|
|
|
|
## Establish one portable path-length limit
|
|
|
|
SplitDisk carries paths up to 511 characters, while the native path machinery appears to
|
|
use a 255-byte limit. Paths are not stored on disk, so this does not change the format, but
|
|
the host can construct a tree addressable by a path that CosmOS cannot express in one
|
|
operation.
|
|
|
|
Declare a portable CosmOS/SBFS path limit and have SplitDisk enforce it when modifying an
|
|
image. The native 255-byte limit is reasonable; the important property is agreement and
|
|
documentation. Component names remain limited to 22 bytes independently.
|
|
|
|
## Bound the number of directory entries
|
|
|
|
The parent field is 16 bits and stores `descriptor index + 1`, with zero reserved for the
|
|
root. Descriptor index 65535 therefore cannot be represented as a parent because adding
|
|
one wraps to zero. SplitDisk currently accepts directory sizes large enough to exceed the
|
|
representable parent domain.
|
|
|
|
Define and validate a maximum directory-block/entry count such that every directory entry
|
|
can be named as a parent. Apply the check while formatting and mounting/reading malformed
|
|
images in both implementations.
|
|
|
|
## Document the save/stream crash guarantee precisely
|
|
|
|
The temporary-first ordering protects the old file from expected failures such as no
|
|
contiguous run or a refused block write. It is not power-loss atomic: a reset between
|
|
deleting the old entry and renaming the temporary can lose the destination and leave the
|
|
temporary behind.
|
|
|
|
That is an appropriate tradeoff for SBFS; it does not call for a journal. Document the
|
|
guarantee as protection against normal operation failures rather than full crash
|
|
atomicity. A future boot cleanup or small consistency checker could reclaim unmistakable
|
|
temporary entries, especially if they receive a descriptor flag.
|
|
|
|
## Design strengths worth preserving
|
|
|
|
- Parent-as-index-plus-one makes every version one entry a valid root child without
|
|
conversion.
|
|
- Directories consume one descriptor and no data blocks, leaving the descriptor array as
|
|
the complete allocation map.
|
|
- Files remain contiguous and the block allocator remains ignorant of hierarchy.
|
|
- Path resolution below the service boundary gave existing applications directories
|
|
without changing their interfaces.
|
|
- The current directory is a two-byte identity rather than a stored string, and the shell
|
|
restores it after applications run.
|
|
- The independent host/native implementations and byte-identical disk agreement tests are
|
|
unusually strong validation of the written format.
|
|
- `osFileStart`/`osFileWrite`/`osFileFetch`/`osFileDone` provide the bounded-memory output
|
|
abstraction needed by assemblers, compilers, linkers, and future sequential pipelines.
|