functions which open in-memory FILE stream variants all shared a tail with __fdopen, adding the FILE structure to stdio's open file list. replacing this common tail with a function call reduces code size and duplication of logic. the list is also partially encapsulated now. function signatures were chosen to facilitate tail call optimization and reduce the need for additional accessor functions. with these changes, static linked programs that do not use stdio no longer have an open file list at all.
61 lines
1.4 KiB
C
61 lines
1.4 KiB
C
#include "stdio_impl.h"
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
FILE *__fdopen(int fd, const char *mode)
|
|
{
|
|
FILE *f;
|
|
struct winsize wsz;
|
|
|
|
/* Check for valid initial mode character */
|
|
if (!strchr("rwa", *mode)) {
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
/* Allocate FILE+buffer or fail */
|
|
if (!(f=malloc(sizeof *f + UNGET + BUFSIZ))) return 0;
|
|
|
|
/* Zero-fill only the struct, not the buffer */
|
|
memset(f, 0, sizeof *f);
|
|
|
|
/* Impose mode restrictions */
|
|
if (!strchr(mode, '+')) f->flags = (*mode == 'r') ? F_NOWR : F_NORD;
|
|
|
|
/* Apply close-on-exec flag */
|
|
if (strchr(mode, 'e')) __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC);
|
|
|
|
/* Set append mode on fd if opened for append */
|
|
if (*mode == 'a') {
|
|
int flags = __syscall(SYS_fcntl, fd, F_GETFL);
|
|
if (!(flags & O_APPEND))
|
|
__syscall(SYS_fcntl, fd, F_SETFL, flags | O_APPEND);
|
|
f->flags |= F_APP;
|
|
}
|
|
|
|
f->fd = fd;
|
|
f->buf = (unsigned char *)f + sizeof *f + UNGET;
|
|
f->buf_size = BUFSIZ;
|
|
|
|
/* Activate line buffered mode for terminals */
|
|
f->lbf = EOF;
|
|
if (!(f->flags & F_NOWR) && !__syscall(SYS_ioctl, fd, TIOCGWINSZ, &wsz))
|
|
f->lbf = '\n';
|
|
|
|
/* Initialize op ptrs. No problem if some are unneeded. */
|
|
f->read = __stdio_read;
|
|
f->write = __stdio_write;
|
|
f->seek = __stdio_seek;
|
|
f->close = __stdio_close;
|
|
|
|
if (!libc.threaded) f->lock = -1;
|
|
|
|
/* Add new FILE to open file list */
|
|
return __ofl_add(f);
|
|
}
|
|
|
|
weak_alias(__fdopen, fdopen);
|