Libs-dev/libio/ru

From KolibriOS wiki
Revision as of 17:22, 5 January 2022 by Leency (talk | contribs)
Jump to navigation Jump to search

В настоящий момент, libio предоставляет API только для работы с файлами (хотя изначально в планах были также и другие типы взаимодействия, например, шины).

По умолчанию, библиотека комплируется с поддержкой имён файлов в OEM кодировке. Поддержка имён файлов в Unicode присутствует, однако требует изменения включаемого файла и пересборки библиотеки.

В большинстве случаев, libio следует прототипам функций POSIX. Для каждой функции, где это возможно, указан её POSIX эквивалент.

Функции (перебор файлов)

file_find_first

Найти первый файл с соответствующими атрибутами и маской в указанной директории.

Прототип:

proc file.find_first _dir, _mask, _attr

Агрументы:

_dir → asciiz
директория, в которой нужно производить поиск
_mask → asciiz
маска файла, с использованием шаблонных символов
_attr → dword
маска атрибутов файла (комбинация констант FA_*)

Результат:

eaxFileInfo*
0 (ошибка) / указатель на структуру с информацией о найденном файле (используется как дескриптор поиска)

file_find_next

Найти следующий файл, соответствующий критериям.

Прототип:

proc file.find_next _findd

Аргументы:

_finddFileInfo*
дескриптор поиска (см. file_find_first)

Результат:

eaxFileInfo*
0 (ошибка) / указатель на структуру с информацией о найденном файле (используется как дескриптор поиска)

file_find_close

Закрыть дескриптор поиска и освободить память.

Прототип:

proc file.find_close _findd

Аргументы:

_finddFileInfo*
дескриптор поиска (см. file_find_first)

Результат:

eax → dword
код возврата функции освобождения памяти

Функции (работа с отдельным файлом)

file_size

Получить размер файла.

Прототип:

proc file.size _name

Аргументы:

_name → asciiz
путь к файлу (абсолютный или относительный)

Результат:

eax → dword
-1 (ошибка) / размер файла (в байтах, до 2 гигабайт)

Замечания:

используйте file_err для получения расширенной информации об ошибке

file_open

Открыть файл.

Прототип:

proc file.open _name, _mode

Аргументы:

_name → asciiz
путь к файлу (абсолютный или относительный)
_mode → dword
режим работы с файлом (комбинация констант O_*)

Результат:

eax → InternalFileInfo*
0 (ошибка) / дескриптор файла

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

FILE *result = fopen(_name, _mode);

file_read

Прочитать данные из файла.

Прототип:

proc file.read _filed, _buf, _buflen

Аргументы:

_filed → InternalFileInfo*
дескриптор файла (см. file_open)
_buf → byte*
буфер для размещения прочитанных данных
_buflen → dword
размер буфера (количество байт, которое необходимо прочитать)

Результат:

eax → dword
-1 (ошибка) / количество прочитанных байт

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

size_t result = fread(_buf, _buflen, 1, _filed);

file_write

Записать данные в файл.

Прототип:

proc file.write _filed, _buf, _buflen

Аргументы:

_filed → InternalFileInfo*
дескриптор файла (см. file_open)
_buf → byte*
буфер с данными для записи
_buflen → dword
размер буфера (количество байт, которое необходимо записать)

Результат:

eax → dword
-1 (ошибка) / количество записанных байт

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

size_t result = fwrite(_buf, _buflen, 1, _filed);

file_seek

Установить позицию файлового указателя.

Прототип:

proc file.seek _filed, _where, _origin

Аргументы:

_filed → InternalFileInfo*
дескриптор файла (см. file_open)
_where → dword
смещение в файле (в байтах) начиная от указанного исходного места
_origin → dword
исходное место, от которого рассчитывается позиция (одна из констант SEEK_*)

Результат:

eax → dword
-1 (ошибка) / 0

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

int result = fseek(_filed, _where, _origin);

file_iseof

Определить, находится ли файловый указатель в конце файла.

Прототип:

proc file.eof? _filed

Аргументы:

_filed → InternalFileInfo*
дескриптор файла (см. file_open)

Результат:

eax → dword
ложь / истина

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

int result = feof(_filed);

file_truncate (file_seteof)

Установить размер файла в текущее значение позиции файлового указателя.

Прототип:

proc file.truncate _filed

Аргументы:

_filed → InternalFileInfo*
дескриптор файла (см. file_open)

Результат:

eax → dword
-1 (ошибка) / 0

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

int result = ftruncate(fileno(_filed), ftell(_filed));

file_tell

Получить текущее значение позиции файлового указателя.

Прототип:

proc file.tell _filed

Аргументы:

_filed → InternalFileInfo*
дескриптор файоа (см. file_open)

Результат:

eax → dword
-1 (ошибка) / позиция файлового указателя

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

long result = ftell(_filed);

file_close

Закрыть файл.

Прототип:

proc file.close _filed

Аргументы:

_filed → InternalFileInfo*
дескриптор файла (см. file_open)

Результат:

eax → dword
-1 (ошибка) / 0

Замечания:

используйте file_err для получения расширенной информации об ошибке

POSIX эквивалент:

int result = fclose(_filed);

Константы

Режим открытия файла

O_BINARY = 00000000b
O_READ   = 00000001b
O_WRITE  = 00000010b
O_CREATE = 00000100b
O_SHARE  = 00001000b
O_TEXT   = 00010000b

Детальное описание:

O_BINARY
ни коим образом не изменять читаемые/записываемые данные (по умолчанию)
O_READ
открыть файл для чтения
O_WRITE
открыть файл для записи
O_CREATE
создать файл, если его не существует; иначе, открыть уже существующий
O_SHARE
разрещить параллельный доступ в файлу, используя разные дескрипторы (не реализовано)
O_TEXT
заменять символы конфа строки на LF (замещает O_BINARY, не реализовано)

Исходное место перемещения по файлу

SEEK_SET = 0
SEEK_CUR = 1
SEEK_END = 2

Детальное описание:

SEEK_SET
от начала файла
SEEK_CUR
от текущей позиции файлового указателя
SEEK_END
от конца файла

Атрибуты файла

FA_READONLY = 00000001b
FA_HIDDEN   = 00000010b
FA_SYSTEM   = 00000100b
FA_LABEL    = 00001000b
FA_FOLDER   = 00010000b
FA_ARCHIVED = 00100000b
FA_ANY      = 00111111b

Детальное описание:

FA_READONLY
файл только для чтения (запись запрещена)
FA_HIDDEN
файл или директория скрыты (обычно, невидимы для пользователя)
FA_SYSTEM
файл или директория содержат важные данные операционной системы
FA_LABEL
не файл, имя содержит метку диска
FA_FOLDER
не файл, но директория
FA_ARCHIVED
архивный файл (устаревший флаг, используется системой)
FA_ANY
любой из перечисленных атрибутов (используется для указания маски)

Структуры

FileDateTime

Дата и время в формате, возвращаемом системными вызовами.

struct FileDateTime
  union
    time    dd ?
    struct
      sec   db ?
      min   db ?
      hour  db ?
    ends
  ends
  union
    date    dd ?
    struct
      day   db ?
      month db ?
      year  dw ?
    ends
  ends
ends

FileInfoBlock

Дескриптор, используемый системными вызовами для идентификации вызываемой функции и её базовых аргументов. Обычно не должна использоваться в программах напрямую.

struct FileInfoBlock
  Function   dd ?
  Position   dd ?
  Flags      dd ?
  Count      dd ?
  Buffer     dd ?
             db ?
  FileName   dd ?
ends

FileInfoHeader

Дескриптор списка файлов, возвращаемый как результат вызова системной функции 70.1. Обычно не должна использоваться в программах напрямую.

struct FileInfoHeader
  Version    dd ?
  FilesRead  dd ?
  FilesCount dd ?
             rd 5
ends

FileInfoA

OEM версия структуры FileInfo (блока данных входа каталога).

struct FileInfoA
  Attributes   dd ?
  Flags        dd ?
  DateCreate   FileDateTime
  DateAccess   FileDateTime
  DateModify   FileDateTime
  union
    FileSize   dq ?
    struct
      FileSizeLow  dd ?
      FileSizeHigh dd ?
    ends
  ends
  FileName     rb 264
ends

FileInfoW

Unicode версия структуры FileInfo (блока данных входа каталога).

struct FileInfoW
  Attributes   dd ?
  Flags        dd ?
  DateCreate   FileDateTime
  DateAccess   FileDateTime
  DateModify   FileDateTime
  union
    FileSize   dq ?
    struct
      FileSizeLow  dd ?
      FileSizeHigh dd ?
    ends
  ends
  FileName     rw 260
ends

Примеры использования

Небольшой кусок кода, иллюстрирующий открытие файла, чтение 256 байт, перемещения указателя в начало файла, запись прочитанных данных и закрытие дескриптора файла. Заметьте, что может быть успешно прочитано менее 256 байт, поэтому мы запоминаем точное число. Заметьте также, что мы используем "invoke", так как вызов функции — косвенный.

include 'libio/libio.inc'

; ...

        invoke  file_open, filename, O_READ + O_WRITE
        or      eax, eax
        jz      .error

        mov     [fdesc], eax
 
        invoke  file_read, eax, buffer, 256
        mov     [bytes_read], eax
        inc     eax
        jz      .close

        invoke  file_seek, [fdesc], 0, SEEK_SET
        inc     eax
        jz      .close

        invoke  file_write, [fdesc], buffer, [bytes_read]

  .close:
        invoke  file_close, [fdesc]
 
  .error:

; ...

filename   db '/hd0/1/a.dat', 0
fdesc      dd ?
bytes_read dd ?
buffer     db 256 dup(?)

Тот же самый код на языке C может выглядеть так (для сравнения):

    FILE *f = file_open("/hd0/1/a.dat", O_READ | O_WRITE);
    if (f)
    {
        do
        {
            char buffer[256];
            size_t bytes_read = file_read(f, buffer, sizeof(buffer));
            if (bytes_read == -1)
            {
                break;
            }
            if (file_seek(f, 0, SEEK_SET) == -1)
            {
                break;
            }
            file_write(f, buffer, bytes_read);
        }
        while (0);
        file_close(f);
    }