Files
Sprinter-SDCC/libc/io/open.c
T
snark13 8e389c03f8 Volkov: добавить Sprinter Commander
Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места.

Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
2026-09-10 10:45:30 +03:00

149 lines
4.4 KiB
C
Raw 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.
/*
* open — открыть/создать файл по POSIX-флагам.
*
* Машина состояний флагов: экспонируем POSIX-биты (O_RDONLY/O_WRONLY/
* O_RDWR + O_CREAT/O_EXCL/O_TRUNC/O_APPEND) и диспетчеризуем на три
* входа ESTEX:
*
* $11 OPEN — открыть существующий файл
* $0A CREATE — создать (усечь, если существует), вернуть хендл
* $0B CREATE_NEW — создать, только если файла нет
*
* Три приватных __naked-обёртки делают сырые RST 10h; публичный open()
* — обычный C-оркестратор. IX сохраняется через каждый RST.
* При ошибке errno установлен, возврат -1.
*/
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "_fd_guard.h"
/* ---- сырые ESTEX-обёртки ---------------------------------------------- */
/* ESTEX $11 OPEN: A=режим (1=R, 2=W, 0=R/W), HL=путь → A=хендл, CF=err. */
static int _estex_open_raw(const char *path, int posix_mode) __naked
{
(void)path; (void)posix_mode;
__asm
push ix
;; HL = путь, DE = flags. Низкие биты libc: W=1, R=2, RW=3;
;; ESTEX: RW=0, R=1, W=2. flags=0 оставляем совместимым с R.
ld a, e
and a, #0x03
ld c, #0
or a, a
jr Z, _oopen_read
cp a, #1
jr Z, _oopen_write
cp a, #2
jr Z, _oopen_read
jr _oopen_real ; 3 = read/write
_oopen_read:
ld c, #1
jr _oopen_real
_oopen_write:
ld c, #2
_oopen_real:
ld a, c
ld c, #0x11 ; ESTEX OPEN
rst #0x10
pop ix
jr c, _oopen_err
ld e, a
ld d, #0
ret
_oopen_err:
call __errno_set
ld de, #-1
ret
__endasm;
}
/* ESTEX $0A CREATE: A=атрибут, HL=путь → A=хендл, CF=err.
* Усекает существующий файл. */
static int _estex_create_raw(const char *path) __naked
{
(void)path;
__asm
push ix
xor a, a ; A = 0 (обычный атрибут)
ld c, #0x0A
rst #0x10
pop ix
jr c, _ocreat_err
ld e, a
ld d, #0
ret
_ocreat_err:
call __errno_set
ld de, #-1
ret
__endasm;
}
/* ESTEX $0B CREATE_NEW: A=атрибут, HL=путь → A=хендл, CF=err.
* Падает (errno=EEXIST), если файл уже существует. */
static int _estex_create_new_raw(const char *path) __naked
{
(void)path;
__asm
push ix
xor a, a
ld c, #0x0B
rst #0x10
pop ix
jr c, _ocreatn_err
ld e, a
ld d, #0
ret
_ocreatn_err:
call __errno_set
ld de, #-1
ret
__endasm;
}
/* ---- публичная поверхность --------------------------------------------- */
int open(const char *path, int flags)
{
int fd;
/* Предохранитель: 9-й OPEN вешает DSS (см. _fd_guard.h) —
* отказать самим, не доводя до syscall. */
if (_fd_open_count >= _FD_OPEN_MAX) {
errno = EMFILE;
return -1;
}
if (flags & O_CREAT) {
if (flags & O_EXCL) {
/* Не должен существовать. */
fd = _estex_create_new_raw(path);
} else if (flags & O_TRUNC) {
/* Всегда создать или усечь. */
fd = _estex_create_raw(path);
} else {
/* Открыть, если есть, иначе создать. */
fd = _estex_open_raw(path, flags);
if (fd < 0 && errno == ENOENT) {
fd = _estex_create_raw(path);
}
}
} else {
fd = _estex_open_raw(path, flags);
}
if (fd < 0) {
return -1;
}
_fd_open_count++;
if (flags & O_APPEND) {
/* Встать на конец файла — дальнейшие записи дописывают. */
(void)lseek(fd, 0L, SEEK_END);
}
return fd;
}