/* 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 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)