size_t __stdio_READ(register FILE *stream, unsigned char *buf, size_t bufsize) { ssize_t rv = 0; __STDIO_STREAM_VALIDATE(stream); assert(stream->__filedes >= -1); assert(__STDIO_STREAM_IS_READING(stream)); assert(!__STDIO_STREAM_BUFFER_RAVAIL(stream)); /* Buffer must be empty. */ assert(!(stream->__modeflags & __FLAG_UNGOT)); assert(bufsize); if (!__FEOF_UNLOCKED(stream)) { if (bufsize > SSIZE_MAX) { bufsize = SSIZE_MAX; } #ifdef __UCLIBC_MJN3_ONLY__ #warning EINTR? #endif /* RETRY: */ if ((rv = __READ(stream, buf, bufsize)) <= 0) { if (rv == 0) { __STDIO_STREAM_SET_EOF(stream); } else { /* if (errno == EINTR) goto RETRY; */ __STDIO_STREAM_SET_ERROR(stream); rv = 0; } #ifdef __UCLIBC_MJN3_ONLY__ #warning TODO: Make custom stream read return check optional. #endif #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ } else { assert(rv <= bufsize); if (rv > bufsize) { /* Read more than bufsize! */ abort(); } #endif } } return rv; }
size_t attribute_hidden __stdio_WRITE(register FILE *stream, register const unsigned char *buf, size_t bufsize) { size_t todo; ssize_t rv, stodo; __STDIO_STREAM_VALIDATE(stream); assert(stream->__filedes >= -1); assert(__STDIO_STREAM_IS_WRITING(stream)); assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); /* Buffer must be empty. */ todo = bufsize; do { if (todo == 0) { /* Done? */ __STDIO_STREAM_VALIDATE(stream); return bufsize; } stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX; if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) { #ifdef __UCLIBC_MJN3_ONLY__ #warning TODO: Make custom stream write return check optional. #endif #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ assert(rv <= stodo); if (rv > stodo) { /* Wrote more than stodo! */ /* abort(); */ } #endif todo -= rv; buf += rv; } else #ifdef __UCLIBC_MJN3_ONLY__ #warning EINTR? #endif /* if (errno != EINTR) */ { __STDIO_STREAM_SET_ERROR(stream); #ifdef __STDIO_BUFFERS if ((stodo = __STDIO_STREAM_BUFFER_SIZE(stream)) != 0) { unsigned char *s; if (stodo > todo) { stodo = todo; } s = stream->__bufstart; do { if (((*s = *buf) == '\n') && __STDIO_STREAM_IS_LBF(stream) ) { break; } ++s; ++buf; } while (--stodo); stream->__bufpos = s; todo -= (s - stream->__bufstart); } #endif /* __STDIO_BUFFERS */ __STDIO_STREAM_VALIDATE(stream); return bufsize - todo; } } while (1); }
int fflush_unlocked(register FILE *stream) { #ifdef __STDIO_BUFFERS int retval = 0; #ifdef __UCLIBC_MJN3_ONLY__ #warning REMINDER: should probably define a modeflags type #endif unsigned short bufmask = __FLAG_LBF; #ifndef NDEBUG if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) { __STDIO_STREAM_VALIDATE(stream); /* debugging only */ } #endif if (stream == (FILE *) &_stdio_openlist) { /* Flush all lbf streams. */ stream = NULL; bufmask = 0; } if (!stream) { /* Flush all (lbf) writing streams. */ __STDIO_OPENLIST_INC_USE; __STDIO_THREADLOCK_OPENLIST_ADD; stream = _stdio_openlist; __STDIO_THREADUNLOCK_OPENLIST_ADD; while(stream) { /* We only care about currently writing streams and do not want to * block trying to obtain mutexes on non-writing streams. */ #warning fix for nonatomic #warning unnecessary check if no threads if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */ __MY_STDIO_THREADLOCK(stream); /* Need to check again once we have the lock. */ if (!(((stream->__modeflags | bufmask) ^ (__FLAG_WRITING|__FLAG_LBF) ) & (__FLAG_WRITING|__MASK_BUFMODE)) ) { if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { __STDIO_STREAM_DISABLE_PUTC(stream); __STDIO_STREAM_CLEAR_WRITING(stream); } else { retval = EOF; } } __MY_STDIO_THREADUNLOCK(stream); } stream = stream->__nextopen; } __STDIO_OPENLIST_DEC_USE; } else if (__STDIO_STREAM_IS_WRITING(stream)) { if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { __STDIO_STREAM_DISABLE_PUTC(stream); __STDIO_STREAM_CLEAR_WRITING(stream); } else { retval = EOF; } } #if 0 else if (stream->__modeflags & (__MASK_READING|__FLAG_READONLY)) { /* ANSI/ISO says behavior in this case is undefined but also says you * shouldn't flush a stream you were reading from. As usual, glibc * caters to broken programs and simply ignores this. */ __UNDEFINED_OR_NONPORTABLE; __STDIO_STREAM_SET_ERROR(stream); __set_errno(EBADF); retval = EOF; } #endif #ifndef NDEBUG if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) { __STDIO_STREAM_VALIDATE(stream); /* debugging only */ } #endif return retval; #else /* __STDIO_BUFFERS --------------------------------------- */ #ifndef NDEBUG if ((stream != NULL) #ifdef __STDIO_HAS_OPENLIST && (stream != (FILE *) &_stdio_openlist) #endif ) { __STDIO_STREAM_VALIDATE(stream); /* debugging only */ } #endif #if 0 if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) { /* ANSI/ISO says behavior in this case is undefined but also says you * shouldn't flush a stream you were reading from. As usual, glibc * caters to broken programs and simply ignores this. */ __UNDEFINED_OR_NONPORTABLE; __STDIO_STREAM_SET_ERROR(stream); __set_errno(EBADF); return EOF; } #endif return 0; #endif /* __STDIO_BUFFERS */ }