2 #include "stdio_impl.h"
11 cookie_io_functions_t iofuncs
;
17 unsigned char buf
[UNGET
+BUFSIZ
];
20 static size_t cookieread(FILE *f
, unsigned char *buf
, size_t len
)
22 struct fcookie
*fc
= f
->cookie
;
24 size_t remain
= len
, readlen
= 0;
25 size_t len2
= len
- !!f
->buf_size
;
27 if (!fc
->iofuncs
.read
) goto bail
;
30 ret
= fc
->iofuncs
.read(fc
->cookie
, (char *) buf
, len2
);
31 if (ret
<= 0) goto bail
;
37 if (!f
->buf_size
|| remain
> !!f
->buf_size
) return readlen
;
40 ret
= fc
->iofuncs
.read(fc
->cookie
, (char *) f
->rpos
, f
->buf_size
);
41 if (ret
<= 0) goto bail
;
42 f
->rend
= f
->rpos
+ ret
;
44 buf
[readlen
++] = *f
->rpos
++;
49 f
->flags
|= ret
== 0 ? F_EOF
: F_ERR
;
50 f
->rpos
= f
->rend
= f
->buf
;
54 static size_t cookiewrite(FILE *f
, const unsigned char *buf
, size_t len
)
56 struct fcookie
*fc
= f
->cookie
;
58 size_t len2
= f
->wpos
- f
->wbase
;
59 if (!fc
->iofuncs
.write
) return len
;
62 if (cookiewrite(f
, f
->wpos
, len2
) < len2
) return 0;
64 ret
= fc
->iofuncs
.write(fc
->cookie
, (const char *) buf
, len
);
66 f
->wpos
= f
->wbase
= f
->wend
= 0;
73 static off_t
cookieseek(FILE *f
, off_t off
, int whence
)
75 struct fcookie
*fc
= f
->cookie
;
81 if (!fc
->iofuncs
.seek
) {
85 res
= fc
->iofuncs
.seek(fc
->cookie
, &off
, whence
);
91 static int cookieclose(FILE *f
)
93 struct fcookie
*fc
= f
->cookie
;
94 if (fc
->iofuncs
.close
) return fc
->iofuncs
.close(fc
->cookie
);
98 FILE *fopencookie(void *cookie
, const char *mode
, cookie_io_functions_t iofuncs
)
100 struct cookie_FILE
*f
;
102 /* Check for valid initial mode character */
103 if (!strchr("rwa", *mode
)) {
108 /* Allocate FILE+fcookie+buffer or fail */
109 if (!(f
=malloc(sizeof *f
))) return 0;
111 /* Zero-fill only the struct, not the buffer */
112 memset(&f
->f
, 0, sizeof f
->f
);
114 /* Impose mode restrictions */
115 if (!strchr(mode
, '+')) f
->f
.flags
= (*mode
== 'r') ? F_NOWR
: F_NORD
;
117 /* Set up our fcookie */
118 f
->fc
.cookie
= cookie
;
119 f
->fc
.iofuncs
= iofuncs
;
122 f
->f
.cookie
= &f
->fc
;
123 f
->f
.buf
= f
->buf
+ UNGET
;
124 f
->f
.buf_size
= sizeof f
->buf
- UNGET
;
127 /* Initialize op ptrs. No problem if some are unneeded. */
128 f
->f
.read
= cookieread
;
129 f
->f
.write
= cookiewrite
;
130 f
->f
.seek
= cookieseek
;
131 f
->f
.close
= cookieclose
;
133 /* Add new FILE to open file list */
134 return __ofl_add(&f
->f
);