Man page - fopencookie(3)

Packages contains this manual

Available languages:

en fr ja ru

Manual

FOPENCOOKIE

名 前
書 式
説 明
返 り 値
属 性
準 拠

プ ロ グ ラ ム の ソ ー ス
関 連 項 目
こ の 文 書 に つ い て

名 前

fopencookie - 独 自 の ス ト リ ー ム を オ ー プ ン す る

書 式

#define _GNU_SOURCE /* feature_test_macros(7) 参 照 */
#include <stdio.h>

FILE *fopencookie(void * cookie , const char * mode ,
cookie_io_functions_t
io_funcs );

説 明

fopencookie () を 使 う と 、 プ ロ グ ラ マ ー は 標 準 I/O ス ト リ ー ム の 独 自 の 実 装 を 作 成 す る こ と が で き る 。 こ の 実 装 は ス ト リ ー ム の デ ー タ を 自 分 が 選 ん だ 場 所 に 格 納 す る こ と が で き る 。 例 え ば 、 fopencookie () は fmemopen (3) を 実 装 す る の に 使 用 さ れ て い る 。 fmemopen (3) は メ モ リ ー 上 の バ ッ フ ァ ー に 格 納 さ れ た デ ー タ に 対 す る ス ト リ ー ム イ ン タ ー フ ェ ー ス を 提 供 し て い る 。

独 自 の ス ト リ ー ム を 作 成 す る た め に は 、 プ ロ グ ラ マ ー は 以 下 を 行 う 必 要 が あ る 。

*

ス ト リ ー ム に 対 す る I/O を 実 行 す る 際 に 標 準 I/O ラ イ ブ ラ リ が 内 部 で 使 用 す る 4 つ の "フ ッ ク " 関 数 を 実 装 す る 。

*

"cookie" デ ー タ 型 を 定 義 す る 。 "cookie" デ ー タ 型 は 、 上 記 の フ ッ ク 関 数 が 使 用 す る 管 理 情 報 (例 え ば 、 デ ー タ を 格 納 す る 場 所 な ど ) を 提 供 す る 構 造 体 で あ る 。 標 準 の I/O パ ッ ケ ー ジ に は こ の cookie の 内 容 に 関 す る 情 報 を 持 た な い が (し た が っ て fopencookie () に 渡 さ れ る 際 の 型 は void * で あ る )、 フ ッ ク 関 数 が 呼 び 出 さ れ る 際 に 第 一 引 数 と し て cookie が 渡 さ れ る 。

*

fopencookie () を 呼 び 出 し て 、 新 し い ス ト リ ー ム を オ ー プ ン し 、 そ の ス ト リ ー ム に cookie と フ ッ ク 関 数 を 関 連 付 け る 。

fopencookie () 関 数 は fopen (3) と 同 様 の 機 能 を 持 つ 。 新 し い ス ト リ ー ム を オ ー プ ン し 、 そ の ス ト リ ー ム に 対 し て 操 作 を 行 う の に 使 用 す る FILE オ ブ ジ ェ ク ト へ の ポ イ ン タ ー を 返 す 。

cookie 引 数 は 、 新 し い ス ト リ ー ム に 関 連 付 け ら れ る 呼 び 出 し 元 の cookie 構 造 体 へ の ポ イ ン タ ー で あ る 。 こ の ポ イ ン タ ー は 、 標 準 I/O ラ イ ブ ラ リ が 以 下 で 説 明 す る フ ッ ク 関 数 の い ず れ か を 呼 び 出 す 際 に 第 1 引 数 と し て 渡 さ れ る 。

mode 引 数 は fopen (3) と 同 じ 意 味 を 持 つ 。 指 定 で き る モ ー ド は r , w , a , r+ , w+ , a+ で あ る 。 詳 細 は fopen (3) を 参 照 。

io_funcs 引 数 は 、 こ の ス ト リ ー ム を 実 装 す る の に 使 用 さ れ る プ ロ グ ラ マ ー が 定 義 し た 関 数 を 指 す 4 つ の フ ィ ー ル ド を 持 つ 構 造 体 で あ る 。 こ の 構 造 体 は 以 下 の よ う に 定 義 さ れ て い る 。

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;

4 つ の フ ィ ー ル ド の 詳 細 は 以 下 の と お り で あ る 。
cookie_read_function_t *read

こ の 関 数 は ス ト リ ー ム に 対 す る read 操 作 を 実 装 す る 。 呼 び 出 さ れ る 際 、 3 つ の 引 数 を 受 け 取 る 。

ssize_t read(void *cookie, char *buf, size_t size);

引 数 buf size は 、 そ れ ぞ れ 、 入 力 デ ー タ を 配 置 で き る バ ッ フ ァ ー と そ の バ ッ フ ァ ー の サ イ ズ で あ る 。 関 数 の 結 果 と し て 、 read 関 数 は buf に コ ピ ー さ れ た バ イ ト 数 を 、 フ ァ イ ル 末 尾 の 場 合 は 0 を 、 エ ラ ー の 場 合 は -1 を 返 す 。 read 関 数 は ス ト リ ー ム の オ フ セ ッ ト を 適 切 に 更 新 す べ き で あ る 。

*read が ヌ ル ポ イ ン タ ー の 場 合 、 独 自 の ス ト リ ー ム か ら の 読 み 出 し は 常 に フ ァ イ ル 末 尾 (end of file) を 返 す 。

cookie_write_function_t *write

こ の 関 数 は ス ト リ ー ム に 対 す る write 操 作 を 実 装 す る 。 呼 び 出 さ れ る 際 、 3 つ の 引 数 を 受 け 取 る 。

ssize_t write(void *cookie, const char *buf, size_t size);

引 数 buf size は 、 そ れ ぞ れ 、 ス ト リ ー ム へ の 出 力 す る デ ー タ が 入 っ た バ ッ フ ァ ー と そ の バ ッ フ ァ ー の サ イ ズ で あ る 。 関 数 の 結 果 と し て 、 write 関 数 は buf か ら コ ピ ー さ れ た バ イ ト 数 を 返 し 、 エ ラ ー の 場 合 は -1 を 返 す 。 (こ の 関 数 は 負 の 値 を 返 し て は な ら な い 。 ) write 関 数 は ス ト リ ー ム の オ フ セ ッ ト を 適 切 に 更 新 す べ き で あ る 。

*write が ヌ ル ポ イ ン タ ー の 場 合 、 こ の ス ト リ ー ム へ の 出 力 は 破 棄 さ れ る 。

cookie_seek_function_t *seek

こ の 関 数 は ス ト リ ー ム に 対 す る seek 操 作 を 実 装 す る 。 呼 び 出 さ れ る 際 、 3 つ の 引 数 を 受 け 取 る 。

int seek(void *cookie, off64_t *offset, int whence);

*offset 引 数 は 新 し い フ ァ イ ル オ フ セ ッ ト を 指 定 す る 。 新 し い オ フ セ ッ ト は whence に 以 下 の 値 の ど れ が 指 定 さ れ た か に 応 じ て 決 ま る 。
SEEK_SET

ス ト リ ー ム オ フ セ ッ ト を 、 ス ト リ ー ム の 先 頭 か ら *offset バ イ ト の 位 置 に 設 定 す る 。

SEEK_CUR

ス ト リ ー ム の 現 在 の オ フ セ ッ ト に *offset を 加 算 す る 。

SEEK_END

ス ト リ ー ム の オ フ セ ッ ト を 、 ス ト リ ー ム の サ イ ズ に *offset を 足 し た 場 所 に 設 定 す る 。

関 数 が 返 る 前 に 、 seek 関 数 は ス ト リ ー ム の 新 し い オ フ セ ッ ト を 示 す よ う に *offset を 更 新 す べ き で あ る 。

関 数 の 結 果 と し て 、 seek 関 数 は 成 功 す る と 0 を 、 エ ラ ー の 場 合 -1 を 返 す 。

*seek が ヌ ル ポ イ ン タ ー の 場 合 、 こ の ス ト リ ー ム に 対 し て seek 操 作 を 行 う こ と が で き な い 。

cookie_close_function_t *close

こ の 関 数 は ス ト リ ー ム を ク ロ ー ズ す る 。 こ の フ ッ ク 関 数 で は 、 こ の ス ト リ ー ム に 割 り 当 て ら れ た バ ッ フ ァ ー を 解 放 す る と い っ た こ と が で き る 。 呼 び 出 さ れ る 際 、 1 つ の 引 数 を 受 け 取 る 。

int close(void *cookie);

cookie 引 数 は fopencookie () の 呼 び 出 し 時 に プ ロ グ ラ マ ー が 渡 し た cookie で あ る 。

関 数 の 結 果 と し て 、 close 関 数 は 成 功 す る と 0 を 、 エ ラ ー の 場 合 EOF を 返 す 。

*close が NULL の 場 合 、 ス ト リ ー ム が ク ロ ー ズ さ れ る 際 に 特 別 な 操 作 は 何 も 行 わ れ な い 。

返 り 値

成 功 す る と fopencookie () は 新 し い ス ト リ ー ム へ の ポ イ ン タ ー を 返 す 。 エ ラ ー の 場 合 、 NULL が 返 さ れ る 。

属 性

こ の 節 で 使 用 さ れ て い る 用 語 の 説 明 に つ い て は 、 attributes (7) を 参 照 。

Image grohtml-23032-1.png

準 拠

こ の 関 数 は 非 標 準 の GNU 拡 張 で あ る 。

以 下 の プ ロ グ ラ ム は 、 fmemopen (3) で 利 用 で き る の と 似 た (同 じ で は な い ) 機 能 を 持 つ 独 自 の ス ト リ ー ム を 実 装 し て い る 。 デ ー タ が メ モ リ ー バ ッ フ ァ ー に 格 納 さ れ る ス ト リ ー ム を 実 装 し て い る 。 こ の プ ロ グ ラ ム は 、 コ マ ン ド ラ イ ン 引 数 を ス ト リ ー ム に 書 き 込 み 、 そ れ か ら ス ト リ ー ム を た ど っ て 5 文 字 ご と に 2 文 字 を 読 み 出 し て 、 そ れ を 標 準 出 力 に 書 き 込 む 。 以 下 の シ ェ ル セ ッ シ ョ ン は こ の プ ロ グ ラ ム の 使 用 例 で あ る 。

$ ./a.out 'hello world'
/he/
/ w/
/d/
Reached end of file

こ の プ ロ グ ラ ム を 改 良 し て 様 々 な エ ラ ー 状 況 に 強 く す る こ と も で き る (例 え ば 、 オ ー プ ン 済 み の ス ト リ ー ム に 対 応 す る cookie で ス ト リ ー ム を オ ー プ ン し よ う と し た 、 す で に ク ロ ー ズ さ れ た ス ト リ ー ム を ク ロ ー ズ し よ う と し た 、 な ど )。

プ ロ グ ラ ム の ソ ー ス

#define _GNU_SOURCE
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#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;
} else {
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, off64_t *offset, int whence)
{
off64_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 (int 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\n");
exit(EXIT_FAILURE);
}
printf("Reached end of file\n");
break;
}

printf("/%.*s/\n", (int) nread, buf);
}

exit(EXIT_SUCCESS);
}

関 連 項 目

fclose (3), fmemopen (3), fopen (3), fseek (3)

こ の 文 書 に つ い て

こ の man ペ ー ジ は Linux man-pages プ ロ ジ ェ ク ト の リ リ ー ス 5.10 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は https://www.kernel.org/doc/man-pages/ に 書 か れ て い る 。