057dd615ba
- ESTEX WRITE ($14) на успехе возвращает DE=0, а НЕ счётчик записанного (вопреки докам; solid-c в своём fflush тоже отключил сравнение по счётчику) — write() теперь судит по CF/A: CF=0&A=0 → n, CF=0&A!=0 → ENOSPC/-1 - DSS выдаёт 8 манипуляторов (fd 2..9; fd 1 держит шелл под запущенный exe), а 9-й OPEN не возвращает 06h — ВЕШАЕТ систему; предохранитель _fd_guard: счётчик в open()/close(), отказ EMFILE без захода в DSS - tests/fdmax — эмпирика лимита (8 хендлов, затем EMFILE=6); tests/fbench — бенчмарк буферизации (floor 512-байтными read, оценка небуферизованного по 1-байтным, fgetc/fgets/fputc) - filetest расширен: raw-probe возврата write, сценарий r+ (чтение-запись-чтение с инвалидацией буфера), ungetc, fprintf Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54 lines
2.3 KiB
C
54 lines
2.3 KiB
C
/*
|
||
* write — блочная запись в файловый хендл ESTEX.
|
||
*
|
||
* ESTEX WRITE ($14): A=handle, HL=буфер, DE=число байт
|
||
* → CF=err с кодом в A.
|
||
*
|
||
* КВИРК (подтверждён в MAME, DSS 1.71.57, 2026-07-06): вопреки докам
|
||
* («DE = реальное количество записанных байт») на успехе DE = 0.
|
||
* Достоверный признак полной записи — A = 0 при CF = 0 (как у READ,
|
||
* где A=0 «всё», A=FFh «меньше»); solid-c в своём fflush так же
|
||
* закомментировал сравнение по DE и проверяет A. Поэтому:
|
||
* CF=1 → errno из A, возврат -1;
|
||
* CF=0, A=0 → всё записано, возврат n (запрошенного);
|
||
* CF=0, A!=0 → частичная запись (диск полон), реальный счётчик
|
||
* неизвестен → errno=ENOSPC, возврат -1.
|
||
*
|
||
* ABI-паттерн идентичен read() — см. read.c.
|
||
*/
|
||
|
||
#include <unistd.h>
|
||
|
||
int write(int fd, const void *buf, size_t n) __naked
|
||
{
|
||
(void)fd; (void)buf; (void)n;
|
||
__asm
|
||
pop iy ; IY = адрес возврата
|
||
pop bc ; BC = n (стековый аргумент)
|
||
ld a, l ; A = handle
|
||
ex de, hl ; HL = buf
|
||
ld d, b
|
||
ld e, c ; DE = n
|
||
push bc ; n нужен после RST (всё клобберится)
|
||
push ix
|
||
push iy ; сохранить адрес возврата через RST
|
||
ld c, #0x14 ; ESTEX WRITE
|
||
rst #0x10
|
||
pop iy
|
||
pop ix
|
||
pop bc ; BC = n
|
||
jr c, _write_err
|
||
or a, a ; A=0 — всё записано (DE недостоверен)
|
||
jr nz, _write_short
|
||
ld d, b
|
||
ld e, c ; вернуть запрошенное n
|
||
jp (iy)
|
||
_write_short:
|
||
ld a, #10 ; ENOSPC (DSS 0Ah No free space)
|
||
_write_err:
|
||
call __errno_set
|
||
ld de, #-1
|
||
jp (iy)
|
||
__endasm;
|
||
}
|