Manpages

名 前

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); 引 き 数 bufsize は 、 そ れ ぞ れ 、 入 力 デ ー タ を 配 置 で き る バ ッ フ ァ ー と そ の バ ッ フ ァ ー の サ イ ズ で あ る 。 関 数 の 結 果 と し て 、 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); 引 き 数 bufsize は 、 そ れ ぞ れ 、 ス ト リ ー ム へ の 出 力 す る デ ー タ が 入 っ た バ ッ フ ァ ー と そ の バ ッ フ ァ ー の サ イ ズ で あ る 。 関 数 の 結 果 と し て 、 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 が 返 さ れ る 。

準 拠

こ の 関 数 は 非 標 準 の 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;
ssize_t nread;
long p;
int j;
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 (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 (p = 0; ; p += 5) {
if (fseek(stream, p, SEEK_SET) == −1) {
perror("fseek");
exit(EXIT_FAILURE); }
nread = fread(buf, 1, 2, stream);
if (nread == −1) {
perror("fread");
exit(EXIT_FAILURE); }
if (nread == 0) {
printf("Reached end of file\n");
break; }

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

exit(EXIT_SUCCESS); }

関 連 項 目

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

こ の 文 書 に つ い て

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