123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
- *
- * GNU Library General Public License (LGPL) version 2 or later.
- *
- * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
- */
- #include "_stdio.h"
- #if (_IOFBF != 0) || (_IOLBF != 1) || (_IONBF != 2)
- #error Assumption violated -- values of _IOFBF, _IOLBF, _IONBF
- #endif
- #if (__FLAG_FBF != 0) || (__FLAG_NBF != (2*__FLAG_LBF))
- #error Assumption violated for buffering mode flags
- #endif
- libc_hidden_proto(setvbuf)
- int setvbuf(register FILE * __restrict stream, register char * __restrict buf,
- int mode, size_t size)
- {
- #ifdef __STDIO_BUFFERS
- int retval = EOF;
- int alloc_flag = 0;
- __STDIO_AUTO_THREADLOCK_VAR;
- __STDIO_AUTO_THREADLOCK(stream);
- __STDIO_STREAM_VALIDATE(stream);
- if (((unsigned int) mode) > 2) {
- __set_errno(EINVAL);
- goto ERROR;
- }
- /* C99 states that setvbuf may only be used between a successful
- * open of the stream and before any other operation other than
- * an unsuccessful call to setvbuf. */
- #ifdef __STDIO_FLEXIBLE_SETVBUF
- /* If we aren't currently reading (including ungots) or writing,
- * then allow the request to proceed. */
- if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING)) {
- goto ERROR;
- }
- #else
- /* The following test isn't quite as strict as C99, as it will
- * not detect file positioning operations. */
- if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING
- |__FLAG_NARROW|__FLAG_WIDE
- |__FLAG_ERROR|__FLAG_EOF)
- ) {
- goto ERROR;
- }
- #endif
- stream->__modeflags &= ~(__MASK_BUFMODE); /* Clear current mode */
- stream->__modeflags |= mode * __FLAG_LBF; /* and set new one. */
- if ((mode == _IONBF) || !size) {
- size = 0;
- buf = NULL;
- } else if (!buf) {
- if ((__STDIO_STREAM_BUFFER_SIZE(stream) == size) /* Same size or */
- || !(buf = malloc(size)) /* malloc failed, so don't change. */
- ) {
- goto DONE;
- }
- alloc_flag = __FLAG_FREEBUF;
- }
- if (stream->__modeflags & __FLAG_FREEBUF) {
- stream->__modeflags &= ~(__FLAG_FREEBUF);
- free(stream->__bufstart);
- }
- stream->__modeflags |= alloc_flag;
- stream->__bufstart = (unsigned char *) buf;
- stream->__bufend = (unsigned char *) buf + size;
- __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
- __STDIO_STREAM_DISABLE_GETC(stream);
- __STDIO_STREAM_DISABLE_PUTC(stream);
- DONE:
- retval = 0;
- ERROR:
- __STDIO_STREAM_VALIDATE(stream);
- __STDIO_AUTO_THREADUNLOCK(stream);
- return retval;
- #else /* __STDIO_BUFFERS */
- if (mode == _IONBF) {
- return 0;
- }
- if (((unsigned int) mode) > 2) {
- __set_errno(EINVAL);
- }
- return EOF;
- #endif
- }
- libc_hidden_def(setvbuf)
|