ref: 5d34077110dc3c09b256f68ea3fe017dd0451273
dir: /lib/c/_fpopen.c/
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include "syscall.h" #undef fopen FILE * _fpopen(const char * restrict fname, const char * restrict mode, FILE * restrict fp) { int i, flags, fd, rw, bin; flags = rw = bin = 0; if (mode[0] == '\0') goto einval; for (i = 1; mode[i]; ++i) { switch (mode[i]) { case '+': if (rw) goto einval; rw = 1; break; case 'b': if (bin) goto einval; bin = 1; break; default: goto einval; } } switch (mode[0]) { case 'a': flags |= O_APPEND | O_CREAT; goto wrflags; case 'w': flags |= O_TRUNC | O_CREAT; wrflags: flags |= (rw) ? O_RDWR : O_WRONLY; break; case 'r': flags = (rw) ? O_RDWR : O_RDONLY; break; default: einval: errno = EINVAL; return NULL; } if ((fd = _open(name, flags)) < 0) return NULL; if (fp->buf == NULL) { if ((fp->buf = malloc(BUFSIZ)) == NULL) { close(fd); errno = ENOMEM; return NULL; } fp->flags |= _IOALLOC; } fp->fd = fd; if (!bin) fp->flags |= _IOTEXT; if (flags & O_RDWR) fp->flags |= _IORW; else if (flags & O_RDONLY) fp->flags |= _IOREAD; else fp->flags |= _IOWRITE; fp->lp = fp->rp = fp->wp = NULL; return fp; }