Files
snark13 057dd615ba libc: квирки DSS — возврат WRITE и лимит манипуляторов; тесты fdmax/fbench
- 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>
2026-07-06 16:09:29 +03:00

54 lines
2.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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;
}