Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места. Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
6.2 KiB
Sprinter Commander: рекурсивный F5 одного каталога 0.2/P15
Дата: 9 сентября 2026 года.
Статус: основной и отрицательные сценарии PASS в MAME 0.288 / BIOS 3.06 /
DSS 1.71.57 на HDD D:.
Реализованный контракт
Если в активной панели нет выбранной группы и cursor стоит на обычном каталоге, F5 рекурсивно создаёт одноимённое дерево в каталоге passive panel:
- обход breadth-first, без рекурсии C-стека;
- каждый файл проходит прежний crash-safe
temp -> commitи общий 4-КБ copy-buffer в выделенной странице W3; - одновременно открыты не более source и temp;
- пустые каталоги создаются;
- existing target не объединяется и не перезаписывается;
- Esc проверяется между каталогами и на каждом 4-КБ шаге файла;
- при cancel/error уже committed-файлы и созданные каталоги остаются, temp текущего файла удаляется;
- CWD процесса восстанавливается и passive panel перечитывается после изменения target.
Начиная с P16 выбранные каталоги также добавляются как несколько roots в ту же очередь. Этот документ фиксирует более узкий single-root срез P15.
Память обхода
sc_tree на время одной операции выделяет одну дополнительную EMM-страницу.
Первые 256 байт сохраняют исходный CWD. Остаток содержит 1008 узлов по 16
байт: parent index + DOS 8.3 component + depth. Абсолютный путь строится
перед операцией по цепочке parent; фиксированный предел глубины — 32, а общий
предел пути остаётся 255 символов.
4-КБ данные файла не смешиваются с traversal queue и не размещаются в W2.
W3 отображается только внутри bank_read/write и bank_read_page/ bank_write_page; вызовы сами восстанавливают прежнюю страницу.
До добавления root проверяется, что каталог passive panel не совпадает с source root и не лежит внутри него. Это запрещает саморастущее копирование.
Проверка
Fixture включает пустой каталог, файлы размером 0, 15, 16 и 4097 байт и цепочку из 16 вложенных уровней. MAME сообщил точный итог:
Tree copied: 4 files; 19 dirs.
После выхода source и target извлечены из CHD и сравнены как полные деревья:
PASS: recursive tree copied exactly; depth=16; no temp.
Повторный F5 остановился до изменения файлов: DSS вернул EISDIR (errno 15) для уже существующего target-каталога. Контрольные состояния:
- source TREE и пустой target;
- успех 4 files / 19 dirs;
- repeat остановлен на existing target;
- passive panel перечитана;
- Esc удалил temp большого файла;
- target внутри source отклонён до mutation;
- чистый возврат в DSS.
Отдельный cancel-fixture начал копирование BIG.BIN размером 4 МБ и подал
Esc до commit. Target root остался как определённый частичный результат,
файл и temp отсутствуют, source не изменён:
PASS: tree cancel removed active temp; source intact; no BIG commit.
Self-target fixture расположил passive panel в SOURCE\TREE\INNER. Операция
остановилась с errno 14 (EINVAL отображается libc на родной DSS
EUNKOP) до первого mkdir; INNER остался пустым:
PASS: target-inside-source refused before mutation.
Компоновка и размер
Конфигурация --memory big --safe --max-allocs 3000:
| Область | После P14 | После P15 | Изменение |
|---|---|---|---|
_CODE W2 |
9503 | 9503 | 0 |
| данные W2 | 3268 | 3524 | +256 |
| свободная куча W2 | 2077 | 1821 | -256 |
| BANK1 | 6477 | 9687 | +3210 |
| BANK2 | 13388 | 14547 | +1159 |
SPRCMD.EXE |
43080 | 43080 | 0 |
256 байт W2 — единственный ffblk_t traversal engine. Крупная очередь
динамическая и в эти числа не входит. BANK1/BANK2 имеют соответственно 6697
и 1837 байт запаса; межбанковый аудит чист.
Воспроизведение
make hdd-p15-tree-copy ALLOCS=3000
tests/run_mame_hdd.sh build/hdd/p15_tree_copy.chd \
tests/mame_p15_tree_copy.lua artifacts/mame-p15/local 60
tests/check_p15_tree_copy_hdd.sh build/hdd/p15_tree_copy.chd
make hdd-p15-tree-cancel hdd-p15-tree-self ALLOCS=3000
tests/run_mame_hdd.sh build/hdd/p15_tree_cancel.chd \
tests/mame_p15_tree_cancel.lua artifacts/mame-p15/cancel 48
tests/check_p15_tree_cancel_hdd.sh build/hdd/p15_tree_cancel.chd
tests/run_mame_hdd.sh build/hdd/p15_tree_self.chd \
tests/mame_p15_tree_self.lua artifacts/mame-p15/self 48
tests/check_p15_tree_self_hdd.sh build/hdd/p15_tree_self.chd