.\" -*- coding: UTF-8 -*- '\" t .\" Copyright (c) 2008, Linux Foundation, written by Michael Kerrisk .\" .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH fopencookie 3 "29 декабря 2023 г." "Linux man\-pages 6.06" .SH ИМЯ fopencookie \- open a custom stream .SH LIBRARY Standard C library (\fIlibc\fP, \fI\-lc\fP) .SH СИНТАКСИС .nf \fB#define _GNU_SOURCE\fP /* See feature_test_macros(7) */ \fB#define _FILE_OFFSET_BITS 64\fP \fB#include \fP .P \fBFILE *fopencookie(void *restrict \fP\fIcookie\fP\fB, const char *restrict \fP\fImode\fP\fB,\fP \fB cookie_io_functions_t \fP\fIio_funcs\fP\fB);\fP .fi .SH ОПИСАНИЕ Функция \fBfopencookie\fP() позволяет программисту создать нестандартную реализацию стандартного потока ввода\-вывода. Эта реализация может хранить данные потока в расположении по своему выбору; например, \fBfopencookie\fP() используется для реализации функции \fBfmemopen\fP(3), которая предоставляет потоковый интерфейс для данных, хранящихся в буфере в памяти. .P Для создания нестандартного потока программист должен: .IP \[bu] 3 Реализовать четыре «обрабатывающих» (hook) функции, которые используются внутри стандартной библиотеки ввода\-вывода при операциях ввода\-вывода над потоком. .IP \[bu] Define a "cookie" data type, a structure that provides bookkeeping information (e.g., where to store data) used by the aforementioned hook functions. The standard I/O package knows nothing about the contents of this cookie (thus it is typed as \fIvoid\~*\fP when passed to \fBfopencookie\fP()), but automatically supplies the cookie as the first argument when calling the hook functions. .IP \[bu] Вызвать \fBfopencookie\fP() для открытия нового потока и связывания cookie и обрабатывающими функциями с этим потоком. .P Функция \fBfopencookie\fP() подобна \fBfopen\fP(3): она открывает новый поток и возвращает указатель на объект \fIFILE\fP, который используется для работы с потоком. .P Аргумент \fIcookie\fP — это указатель на структуру cookie вызывающего, которая связывается с новым потоком. Данный указатель передаётся в первом аргументе в моменты, когда стандартная библиотека ввода\-вывода вызывает одну из обрабатывающих функций, описанных ниже. .P Аргумент \fImode\fP служит той же цели что и для \fBfopen\fP(3). Поддерживаются следующие режимы: \fIr\fP, \fIw\fP, \fIa\fP, \fIr+\fP, \fIw+\fP и \fIa+\fP. Подробности смотрите в \fBfopen\fP(3). .P Аргумент \fIio_funcs\fP — это структура, которая содержит четыре поля с задаваемыми программистом обрабатывающими функциями, которые используются для реализации этого потока. Структура определена как .P .in +4n .EX typedef struct { cookie_read_function_t *read; cookie_write_function_t *write; cookie_seek_function_t *seek; cookie_close_function_t *close; } cookie_io_functions_t; .EE .in .P Поля: .TP \fIcookie_read_function_t *read\fP Эта функция реализует операции чтения из потока. Она вызывается с тремя аргументами: .IP .in +4n .EX ssize_t read(void *cookie, char *buf, size_t size); .EE .in .IP Аргументы \fIbuf\fP и \fIsize\fP — буфер для получаемых данных и его размер. В качестве результата функция \fIread\fP возвращает количество байт, скопированных в \fIbuf\fP, 0 — при окончании файла и \-1 при ошибке. Функция \fIread\fP обновляет смещение в потоке соответствующим образом. .IP Если значение \fI*read\fP равно null, то при чтении из нестандартного потока всегда возвращается конец файла. .TP \fIcookie_write_function_t *write\fP Эта функция реализует операции записи в поток. Она вызывается с тремя аргументами: .IP .in +4n .EX ssize_t write(void *cookie, const char *buf, size_t size); .EE .in .IP Аргументы \fIbuf\fP и \fIsize\fP — буфер для выходных данных и его размер (данные, записываемые в поток). В качестве результата функция \fIwrite\fP возвращает количество байт, скопированных из \fIbuf\fP, и 0 при ошибке (функция не должна возвращать отрицательное значение). Функция \fIwrite\fP обновляет смещение в потоке соответствующим образом. .IP Если значение \fI*write\fP равно null, то вывод в поток отбрасывается. .TP \fIcookie_seek_function_t *seek\fP Эта функция реализует операции смещения в потоке. Она вызывается с тремя аргументами: .IP .in +4n .EX int seek(void *cookie, off_t *offset, int whence); .EE .in .IP В аргументе \fI*offset\fP указывается новое файловое смещение, зависящее от значения \fIwhence\fP: .RS .TP \fBSEEK_SET\fP Значение смещения приравнивается \fI*offset\fP байт от начала потока. .TP \fBSEEK_CUR\fP Значение \fI*offset\fP должно быть добавлено к текущему смещению в потоке. .TP \fBSEEK_END\fP Значение смещения приравнивается к размеру потока плюс \fI*offset\fP. .RE .IP Перед возвратом функция \fIseek\fP должна обновить \fI*offset\fP, чтобы показать новое смещение в потоке. .IP В качестве результата функция \fIseek\fP должна возвращать 0 при успешном выполнении и \-1 при ошибке. .IP Если значение \fI*seek\fP равно null, то операции смещения в потоке выполнить невозможно. .TP \fIcookie_close_function_t *close\fP Эта функция закрывает поток. Обрабатывающая функция может выполнить такие операции как освобождение буферов, выделенных для потока. При вызове она принимает один аргумент: .IP .in +4n .EX int close(void *cookie); .EE .in .IP Аргумент \fIcookie\fP — это cookie, которую программист передал при вызове \fBfopencookie\fP(). .IP В качестве результата функция \fIclose\fP должна возвращать 0 при успешном выполнении и \fBEOF\fP при ошибке. .IP Если значение \fI*close\fP равно NULL, то при закрытии потока не выполняется никаких действий. .SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" .\" .SH ERRORS .\" It's not clear if errno ever gets set... При успешном выполнении \fBfopencookie\fP() возвращает указатель на новый поток. При ошибке возвращается NULL. .SH АТРИБУТЫ Описание терминов данного раздела смотрите в \fBattributes\fP(7). .TS allbox; lbx lb lb l l l. Интерфейс Атрибут Значение T{ .na .nh \fBfopencookie\fP() T} Безвредность в нитях MT\-Safe .TE .SH СТАНДАРТЫ GNU. .SH ПРИМЕРЫ Программа, представленная ниже, реализует нестандартный поток, свойства которого похожи (но не одинаковы) на свойство потока, получаемого от \fBfmemopen\fP(3). Она реализует поток, данные которого хранятся в буфере памяти. Программа записывает свои аргументы командной строки в поток, а затем перемещается по потоку, читая два из каждых пяти символов и записывая их в стандартный вывод. Сеанс оболочки, демонстрирующий использование программы: .P .in +4n .EX $\fB ./a.out \[aq]hello world\[aq]\fP /he/ / w/ /d/ Reached end of file .EE .in .P Заметим, что представленную версию можно сильно улучшить, добавив обработку ошибок (например, открытие потока с cookie, которая уже имеет открытый поток; закрытие потока, который уже был закрыт). .SS "Исходный код программы" .\" SRC BEGIN (fopencookie.c) \& .EX #define _GNU_SOURCE #include #include #include #include #include \& #define INIT_BUF_SIZE 4 \& struct memfile_cookie { char *buf; /* Dynamically sized buffer for data */ size_t allocated; /* Size of buf */ size_t endpos; /* Number of characters in buf */ off_t offset; /* Current file offset in buf */ }; \& ssize_t memfile_write(void *c, const char *buf, size_t size) { char *new_buff; struct memfile_cookie *cookie = c; \& /* Buffer too small? Keep doubling size until big enough. */ \& while (size + cookie\->offset > cookie\->allocated) { new_buff = realloc(cookie\->buf, cookie\->allocated * 2); if (new_buff == NULL) return \-1; cookie\->allocated *= 2; cookie\->buf = new_buff; } \& memcpy(cookie\->buf + cookie\->offset, buf, size); \& cookie\->offset += size; if (cookie\->offset > cookie\->endpos) cookie\->endpos = cookie\->offset; \& return size; } \& ssize_t memfile_read(void *c, char *buf, size_t size) { ssize_t xbytes; struct memfile_cookie *cookie = c; \& /* Fetch minimum of bytes requested and bytes available. */ \& xbytes = size; if (cookie\->offset + size > cookie\->endpos) xbytes = cookie\->endpos \- cookie\->offset; if (xbytes < 0) /* offset may be past endpos */ xbytes = 0; \& memcpy(buf, cookie\->buf + cookie\->offset, xbytes); \& cookie\->offset += xbytes; return xbytes; } \& int memfile_seek(void *c, off_t *offset, int whence) { off_t new_offset; struct memfile_cookie *cookie = c; \& if (whence == SEEK_SET) new_offset = *offset; else if (whence == SEEK_END) new_offset = cookie\->endpos + *offset; else if (whence == SEEK_CUR) new_offset = cookie\->offset + *offset; else return \-1; \& if (new_offset < 0) return \-1; \& cookie\->offset = new_offset; *offset = new_offset; return 0; } \& int memfile_close(void *c) { struct memfile_cookie *cookie = c; \& free(cookie\->buf); cookie\->allocated = 0; cookie\->buf = NULL; \& return 0; } \& int main(int argc, char *argv[]) { cookie_io_functions_t memfile_func = { .read = memfile_read, .write = memfile_write, .seek = memfile_seek, .close = memfile_close }; FILE *stream; struct memfile_cookie mycookie; size_t nread; char buf[1000]; \& /* Set up the cookie before calling fopencookie(). */ \& mycookie.buf = malloc(INIT_BUF_SIZE); if (mycookie.buf == NULL) { perror("malloc"); exit(EXIT_FAILURE); } \& mycookie.allocated = INIT_BUF_SIZE; mycookie.offset = 0; mycookie.endpos = 0; \& stream = fopencookie(&mycookie, "w+", memfile_func); if (stream == NULL) { perror("fopencookie"); exit(EXIT_FAILURE); } \& /* Write command\-line arguments to our file. */ \& for (size_t j = 1; j < argc; j++) if (fputs(argv[j], stream) == EOF) { perror("fputs"); exit(EXIT_FAILURE); } \& /* Read two bytes out of every five, until EOF. */ \& for (long p = 0; ; p += 5) { if (fseek(stream, p, SEEK_SET) == \-1) { perror("fseek"); exit(EXIT_FAILURE); } nread = fread(buf, 1, 2, stream); if (nread == 0) { if (ferror(stream) != 0) { fprintf(stderr, "fread failed\en"); exit(EXIT_FAILURE); } printf("Reached end of file\en"); break; } \& printf("/%.*s/\en", (int) nread, buf); } \& free(mycookie.buf); \& exit(EXIT_SUCCESS); } .EE .\" SRC END .SH ЗАМЕЧАНИЯ \fB_FILE_OFFSET_BITS\fP should be defined to be 64 in code that uses non\-null \fIseek\fP or that takes the address of \fBfopencookie\fP, if the code is intended to be portable to traditional 32\-bit x86 and ARM platforms where \fBoff_t\fP's width defaults to 32 bits. .SH "СМ. ТАКЖЕ" \fBfclose\fP(3), \fBfmemopen\fP(3), \fBfopen\fP(3), \fBfseek\fP(3) .PP .SH ПЕРЕВОД Русский перевод этой страницы руководства был сделан Azamat Hackimov , Dmitry Bolkhovskikh , Yuri Kozlov и Иван Павлов . .PP Этот перевод является бесплатной документацией; прочитайте .UR https://www.gnu.org/licenses/gpl-3.0.html Стандартную общественную лицензию GNU версии 3 .UE или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. .PP Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на .MT man-pages-ru-talks@lists.sourceforge.net .ME .