ptg10805159
914 Solutions to Selected Exercises Appendix C
static int type_to_flags(const char *__restrict type);
static off_t find_end(char *buf, size_t len);
FILE *
fmemopen(void *__restrict buf, size_t size,
const char *__restrict type)
{
struct memstream *ms;
FILE *fp;
if (size == 0) {
errno = EINVAL;
return(NULL);
}
if ((ms = malloc(sizeof(struct memstream))) == NULL) {
errno = ENOMEM;
return(NULL);
}
if ((ms->flags = type_to_flags(type)) == 0) {
errno = EINVAL;
free(ms);
return(NULL);
}
if (buf == NULL) {
if ((ms->flags & (MS_READ|MS_WRITE)) !=
(MS_READ|MS_WRITE)) {
errno = EINVAL;
free(ms);
return(NULL);
}
if ((ms->buf = malloc(size)) == NULL) {
errno = ENOMEM;
free(ms);
return(NULL);
}
ms->rsize = size;
ms->flags |= MS_MYBUF;
ms->curpos = 0;
}else {
ms->buf = buf;
ms->rsize = size;
if (ms->flags & MS_APPEND)
ms->curpos = find_end(ms->buf, ms->rsize);
else
ms->curpos = 0;
}
if (ms->flags & MS_APPEND) { /* "a" mode */
ms->vsize = ms->curpos;
}else if (ms->flags & MS_TRUNCATE) { /* "w" mode */
ms->vsize = 0;
}else { /* "r" mode */