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; }
void _stdio_validate_FILE(const FILE *stream) { #ifdef __UCLIBC_HAS_THREADS__ assert(((unsigned int)(stream->__user_locking)) <= 2); #endif #warning Define a constant for minimum possible valid __filedes? assert(stream->__filedes >= -3); if (stream->__filedes < 0) { /* assert((stream->__filedes != -1) */ /* #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ /* || (stream->__cookie == &stream->__filedes) /\* custom *\/ */ /* #endif */ /* ); */ /* assert((stream->__filedes == -1) || __STDIO_STREAM_IS_FBF(stream)); */ assert(!__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream) || __STDIO_STREAM_IS_NARROW(stream)); assert(!__STDIO_STREAM_IS_FAKE_VSSCANF(stream) || __STDIO_STREAM_IS_NARROW(stream)); #ifdef __STDIO_STREAM_IS_FAKE_VSWPRINTF assert(!__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream) || __STDIO_STREAM_IS_WIDE(stream)); #endif #ifdef __STDIO_STREAM_IS_FAKE_VSWSCANF assert(!__STDIO_STREAM_IS_FAKE_VSWSCANF(stream) || __STDIO_STREAM_IS_WIDE(stream)); #endif } #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ if (stream->__cookie != &stream->__filedes) { /* custom */ assert(stream->__filedes == -1); } #endif /* Can not be both narrow and wide oriented at the same time. */ assert(!(__STDIO_STREAM_IS_NARROW(stream) && __STDIO_STREAM_IS_WIDE(stream))); /* The following impossible case is used to disable a stream. */ if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) == (__FLAG_READONLY|__FLAG_WRITEONLY) ) { assert(stream->__modeflags == (__FLAG_READONLY|__FLAG_WRITEONLY)); assert(stream->__filedes == -1); #ifdef __STDIO_BUFFERS assert(stream->__bufpos == stream->__bufstart); assert(stream->__bufread == stream->__bufstart); # ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ assert(stream->__bufputc_u == stream->__bufstart); # endif # ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ assert(stream->__bufgetc_u == stream->__bufstart); # endif #endif } if (__STDIO_STREAM_IS_READONLY(stream)) { /* assert(!__STDIO_STREAM_IS_WRITEONLY(stream)); */ assert(!__STDIO_STREAM_IS_WRITING(stream)); if (stream->__modeflags & __FLAG_UNGOT) { assert(((unsigned)(stream->__ungot[1])) <= 1); assert(!__FEOF_UNLOCKED(stream)); } } if (__STDIO_STREAM_IS_WRITEONLY(stream)) { /* assert(!__STDIO_STREAM_IS_READONLY(stream)); */ assert(!__STDIO_STREAM_IS_READING(stream)); assert(!(stream->__modeflags & __FLAG_UNGOT)); } if (__STDIO_STREAM_IS_NBF(stream)) { /* We require that all non buffered streams have no buffer. */ assert(!__STDIO_STREAM_BUFFER_SIZE(stream)); } assert((stream->__modeflags & __MASK_BUFMODE) <= __FLAG_NBF); #ifdef __STDIO_BUFFERS /* Ensure __bufstart <= __bufpos <= __bufend. */ assert(stream->__bufpos >= stream->__bufstart); assert(stream->__bufpos <= stream->__bufend); /* Ensure __bufstart <= __bufread <= __bufend. */ assert(stream->__bufread >= stream->__bufstart); assert(stream->__bufread <= stream->__bufend); #endif /* If EOF, then we must have no buffered readable or ungots. */ if (__FEOF_UNLOCKED(stream)) { #ifdef __STDIO_BUFFERS assert(stream->__bufpos == stream->__bufread); #endif assert(!(stream->__modeflags & __FLAG_UNGOT)); } if (!__STDIO_STREAM_IS_WRITING(stream)) { #ifdef __STDIO_BUFFERS /* If not writing, then putc macro must be disabled. */ # ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ assert(stream->__bufputc_u == stream->__bufstart); # endif #endif } if (!__STDIO_STREAM_IS_READING(stream)) { /* If not reading, then can not have ungots. */ assert(!(stream->__modeflags & __FLAG_UNGOT)); #ifdef __STDIO_BUFFERS /* Ensure __bufread == __bufstart. */ assert(stream->__bufread == stream->__bufstart); /* If not reading, then getc macro must be disabled. */ # ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ assert(stream->__bufgetc_u == stream->__bufstart); # endif #endif } if (__STDIO_STREAM_IS_READING(stream)) { assert(!__STDIO_STREAM_IS_WRITING(stream)); #ifdef __STDIO_BUFFERS /* Ensure __bufpos <= __bufread. */ assert(stream->__bufpos <= stream->__bufread); /* Ensure __bufgetc_u is valid. */ # ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ assert(stream->__bufgetc_u >= stream->__bufstart); assert(stream->__bufgetc_u <= stream->__bufread); # endif #endif } if (__STDIO_STREAM_IS_WRITING(stream)) { assert(!__STDIO_STREAM_IS_READING(stream)); #ifdef __STDIO_BUFFERS # ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ assert(stream->__bufputc_u >= stream->__bufstart); assert(stream->__bufputc_u <= stream->__bufend); # endif #endif } /* If have an ungotten char, then getc (and putc) must be disabled. */ /* Also, wide streams must have the getc/putc macros disabled. */ if ((stream->__modeflags & __FLAG_UNGOT) || __STDIO_STREAM_IS_WIDE(stream) ) { #ifdef __STDIO_BUFFERS # ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ assert(stream->__bufputc_u == stream->__bufstart); # endif # ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ assert(stream->__bufgetc_u == stream->__bufstart); # endif #endif } /* TODO -- filepos? ungot_width? filedes? nextopen? */ }