wint_t ungetwc(wint_t c, register FILE *stream) { __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); /* debugging only */ /* Note: Even if c == WEOF, we need to initialize/verify the * stream's orientation and ensure the stream is in reading * mode (if readable and properly oriented). */ if ((!__STDIO_STREAM_IS_WIDE_READING(stream) && __STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE)) || ((stream->__modeflags & __FLAG_UNGOT) && ((stream->__modeflags & 1) || stream->__ungot[1])) || (c == WEOF) ) { c = WEOF; } else { /* In the wide case, getc macros should already be disabled. */ /* __STDIO_STREAM_DISABLE_GETC(stream); */ /* Flag this as a user ungot, as scanf does the necessary fixup. */ stream->__ungot[1] = 1; stream->__ungot[(++stream->__modeflags) & 1] = c; /* Note: ungot_width is handled by fgetwc. */ __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ } __STDIO_STREAM_VALIDATE(stream); __STDIO_AUTO_THREADUNLOCK(stream); return c; }
int FSEEK(register FILE *stream, OFFSET_TYPE offset, int whence) { #if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) return fseeko64(stream, offset, whence); #else __offmax_t pos = offset; int retval = -1; __STDIO_AUTO_THREADLOCK_VAR; if (((unsigned int) whence) > 2) { __set_errno(EINVAL); } else { __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); if ((!__STDIO_STREAM_IS_WRITING(stream) || !__STDIO_COMMIT_WRITE_BUFFER(stream)) && ((whence != SEEK_CUR) || (__stdio_adjust_position(stream, &pos) >= 0)) && (__SEEK(stream, &pos, whence) >= 0) ) { /* Clear reading/writing modes, EOF, and ungots. */ stream->__modeflags &= ~(__MASK_READING|__FLAG_WRITING|__FLAG_EOF); /* Make sure all pointers are reset. */ __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); __STDIO_STREAM_DISABLE_GETC(stream); __STDIO_STREAM_DISABLE_PUTC(stream); /* We reinitialize the mbstate object. Doing so is * implementation defined behavior. */ #ifdef __STDIO_MBSTATE __INIT_MBSTATE(&(stream->__state)); #endif #ifdef __UCLIBC_HAS_WCHAR__ stream->__ungot_width[0] = 0; #endif retval = 0; } __STDIO_STREAM_VALIDATE(stream); __STDIO_AUTO_THREADUNLOCK(stream); } return retval; #endif }
int ungetc(int c, register FILE *stream) { __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); #ifdef __UCLIBC_MJN3_ONLY__ #warning CONSIDER: Make fast ungetc an option? #endif #ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ /* If buffered narrow reading with no ungot slots filled, and if not * ungetting a different char than the one last read from the buffer, * we can simply decrement the position and not worry about disabling * the getc macros. This will cut down on overhead in applications * that use getc/ungetc extensively (like gcc). */ /* NOTE: If we can use getc, then we are buffered narrow reading with * no ungot slots filled. */ if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream) && (c != EOF) && (stream->__bufpos > stream->__bufstart) && (stream->__bufpos[-1] == ((unsigned char)c)) ) { --stream->__bufpos; __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ } else #endif /* Note: Even if c == EOF, we need to initialize/verify the * stream's orientation and ensure the stream is in reading * mode (if readable and properly oriented). */ if ((!__STDIO_STREAM_IS_NARROW_READING(stream) && __STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW)) || ((stream->__modeflags & __FLAG_UNGOT) && ((stream->__modeflags & 1) || stream->__ungot[1])) ) { c = EOF; } else if (c != EOF) { __STDIO_STREAM_DISABLE_GETC(stream); /* Flag this as a user ungot, as scanf does the necessary fixup. */ stream->__ungot[1] = 1; stream->__ungot[(++stream->__modeflags) & 1] = c; __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ } __STDIO_STREAM_VALIDATE(stream); __STDIO_AUTO_THREADUNLOCK(stream); return c; }
OFFSET_TYPE_T FTELL(register FILE *stream) { #if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) __offmax_t pos = __ftello64(stream); if ((sizeof(long) >= sizeof(__offmax_t)) || (((long) pos) == pos)) { return ((long) pos); } else { __set_errno(EOVERFLOW); return -1; } #else __offmax_t pos = 0; __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); if ((__SEEK(stream, &pos, SEEK_CUR) < 0) || (__stdio_adjust_position(stream, &pos) < 0)) { pos = -1; } __STDIO_AUTO_THREADUNLOCK(stream); return pos; #endif }
FILE *fmemopen(void *s, size_t len, const char *modes) { FILE *fp; register __fmo_cookie *cookie; size_t i; if ((cookie = malloc(sizeof(__fmo_cookie))) != NULL) { cookie->len = len; cookie->eof = cookie->pos = 0; /* pos and eof adjusted below. */ cookie->dynbuf = 0; if (((cookie->buf = s) == NULL) && (len > 0)) { if ((cookie->buf = malloc(len)) == NULL) { goto EXIT_cookie; } cookie->dynbuf = 1; *cookie->buf = 0; /* If we're appending, treat as empty file. */ } #ifndef __BCC__ fp = fopencookie(cookie, modes, _fmo_io_funcs); #else fp = fopencookie(cookie, modes, &_fmo_io_funcs); #endif /* Note: We don't need to worry about locking fp in the thread case * as the only possible access would be a close or flush with * nothing currently in the FILE's write buffer. */ if (fp != NULL) { cookie->fp = fp; if (fp->__modeflags & __FLAG_READONLY) { cookie->eof = len; } if ((fp->__modeflags & __FLAG_APPEND) && (len > 0)) { for (i = 0 ; i < len ; i++) { if (cookie->buf[i] == 0) { break; } } cookie->eof = cookie->pos = i; /* Adjust eof and pos. */ } __STDIO_STREAM_VALIDATE(fp); return fp; } } if (!s) { free(cookie->buf); } EXIT_cookie: free(cookie); return NULL; }
void clearerr(register FILE *stream) { __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); __CLEARERR_UNLOCKED(stream); __STDIO_AUTO_THREADUNLOCK(stream); }
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; }
int fwide(register FILE *stream, int mode) { __STDIO_AUTO_THREADLOCK_VAR; __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); if (mode && !(stream->__modeflags & (__FLAG_WIDE|__FLAG_NARROW))) { stream->__modeflags |= ((mode > 0) ? __FLAG_WIDE : __FLAG_NARROW); } mode = (stream->__modeflags & __FLAG_WIDE) - (stream->__modeflags & __FLAG_NARROW); assert((stream->__modeflags & (__FLAG_WIDE|__FLAG_NARROW)) != (__FLAG_WIDE|__FLAG_NARROW)); __STDIO_AUTO_THREADUNLOCK(stream); return mode; }
wint_t fgetwc_unlocked(register FILE *stream) { wint_t wi; wchar_t wc[1]; int n; size_t r; unsigned char sbuf[1]; __STDIO_STREAM_VALIDATE(stream); wi = WEOF; /* Prepare for failure. */ if (__STDIO_STREAM_IS_WIDE_READING(stream) || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE) ) { if (stream->__modeflags & __FLAG_UNGOT) { /* Any ungetwc()s? */ if (((stream->__modeflags & 1) || stream->__ungot[1])) { stream->__ungot_width[0] = 0; /* Application ungot... */ } else { /* scanf ungot */ stream->__ungot_width[0] = stream->__ungot_width[1]; } wi = stream->__ungot[(stream->__modeflags--) & 1]; stream->__ungot[1] = 0; goto DONE; } if (!stream->__bufstart) { /* Ugh... stream isn't buffered! */ /* Munge the stream temporarily to use a 1-byte buffer. */ munge_stream(stream, sbuf); ++stream->__bufend; } if (stream->__state.__mask == 0) { /* If last was a complete char */ stream->__ungot_width[0] = 0; /* then reset the width. */ } LOOP: if ((n = __STDIO_STREAM_BUFFER_RAVAIL(stream)) == 0) { goto FILL_BUFFER; } r = mbrtowc(wc, stream->__bufpos, n, &stream->__state); if (((ssize_t) r) >= 0) { /* Success... */ if (r == 0) { /* Nul wide char... means 0 byte for us so */ ++r; /* increment r and handle below as single. */ } stream->__bufpos += r; stream->__ungot_width[0] += r; wi = *wc; goto DONE; } if (r == ((size_t) -2)) { /* Potentially valid but incomplete and no more buffered. */ stream->__bufpos += n; /* Update bufpos for stream. */ stream->__ungot_width[0] += n; FILL_BUFFER: if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */ goto LOOP; } if (!__FERROR_UNLOCKED(stream)) { /* EOF with no error. */ if (!stream->__state.__mask) { /* No partial wchar. */ goto DONE; } /* EOF but partially complete wchar. */ /* TODO: should EILSEQ be set? */ __set_errno(EILSEQ); } } /* If we reach here, either r == ((size_t)-1) and mbrtowc set errno * to EILSEQ, or r == ((size_t)-2) and stream is in an error state * or at EOF with a partially complete wchar. Make sure stream's * error indicator is set. */ stream->__modeflags |= __FLAG_ERROR; DONE: if (stream->__bufstart == sbuf) { /* Need to un-munge the stream. */ munge_stream(stream, NULL); } } __STDIO_STREAM_VALIDATE(stream); return wi; }
void __clearerr_unlocked(register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); __CLEARERR_UNLOCKED(stream); }
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 */ }
int ftrylockfile(FILE *stream) { __STDIO_STREAM_VALIDATE(stream); return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream); }
int __fputc_unlocked(int c, register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); /* First the fast path. We're good to go if putc macro enabled. */ if (__STDIO_STREAM_CAN_USE_BUFFER_ADD(stream)) { __STDIO_STREAM_BUFFER_ADD(stream, ((unsigned char) c)); return (unsigned char) c; } /* Next quickest... writing and narrow oriented, but macro * disabled and/or buffer is full. */ if (__STDIO_STREAM_IS_NARROW_WRITING(stream) || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW) ) { if (__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream)) { return (unsigned char) c; } if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */ /* The buffer is full and/or the stream is line buffered. */ if (!__STDIO_STREAM_BUFFER_WAVAIL(stream) /* Buffer full? */ && __STDIO_COMMIT_WRITE_BUFFER(stream) /* Commit failed! */ ) { goto BAD; } #ifdef __UCLIBC_MJN3_ONLY__ #warning CONSIDER: Should we fail if the commit fails but we now have room? #endif __STDIO_STREAM_BUFFER_ADD(stream, ((unsigned char) c)); if (IS_STD_STREAM(stream)) { if( __STDIO_COMMIT_WRITE_BUFFER(stream)) { /* Commit failed! */ __STDIO_STREAM_BUFFER_UNADD(stream); /* Undo the write! */ goto BAD; } } else if (__STDIO_STREAM_IS_LBF(stream)) { if ((((unsigned char) c) == '\n') && __STDIO_COMMIT_WRITE_BUFFER(stream)) { /* Commit failed! */ __STDIO_STREAM_BUFFER_UNADD(stream); /* Undo the write! */ goto BAD; } } } else { /* NOTE: Do not try to save space by moving uc to the top of * the file, as that dramaticly increases runtime. */ unsigned char uc = (unsigned char) c; if (! __stdio_WRITE(stream, &uc, 1)) { goto BAD; } } return (unsigned char) c; } BAD: return EOF; }
int fclose(register FILE *stream) { int rv = 0; __STDIO_AUTO_THREADLOCK_VAR; #ifdef __STDIO_HAS_OPENLIST #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) /* First, remove the file from the open file list. */ { FILE *ptr; __STDIO_THREADLOCK_OPENLIST_DEL; __STDIO_THREADLOCK_OPENLIST_ADD; ptr = _stdio_openlist; if ((ptr = _stdio_openlist) == stream) { _stdio_openlist = stream->__nextopen; } else { while (ptr) { if (ptr->__nextopen == stream) { ptr->__nextopen = stream->__nextopen; break; } ptr = ptr->__nextopen; } } __STDIO_THREADUNLOCK_OPENLIST_ADD; __STDIO_THREADUNLOCK_OPENLIST_DEL; } #endif #endif __STDIO_AUTO_THREADLOCK(stream); __STDIO_STREAM_VALIDATE(stream); #ifdef __STDIO_BUFFERS /* Write any pending buffered chars. */ if (__STDIO_STREAM_IS_WRITING(stream)) { rv = fflush_unlocked(stream); } #endif if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */ rv = EOF; } stream->__filedes = -1; /* We need a way for freopen to know that a file has been closed. * Since a file can't be both readonly and writeonly, that makes * an effective signal. It also has the benefit of disabling * transitions to either reading or writing. */ #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) /* Before we mark the file as closed, make sure we increment the openlist use count * so it isn't freed under us while still cleaning up. */ __STDIO_OPENLIST_INC_USE; #endif stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE); stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY); #ifndef NDEBUG __STDIO_STREAM_RESET_GCS(stream); /* Reinitialize everything (including putc since fflush could fail). */ __STDIO_STREAM_DISABLE_GETC(stream); __STDIO_STREAM_DISABLE_PUTC(stream); __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); # ifdef __UCLIBC_HAS_WCHAR__ stream->__ungot_width[0] = 0; # endif # ifdef __STDIO_MBSTATE __INIT_MBSTATE(&(stream->__state)); # endif #endif __STDIO_AUTO_THREADUNLOCK(stream); __STDIO_STREAM_FREE_BUFFER(stream); #ifdef __UCLIBC_MJN3_ONLY__ #warning REMINDER: inefficient - locks and unlocks twice and walks whole list #endif #if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) /* inefficient - locks/unlocks twice and walks whole list */ __STDIO_OPENLIST_INC_DEL_CNT; __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ #else __STDIO_STREAM_FREE_FILE(stream); #endif return rv; }
int ferror(register FILE *stream) { __STDIO_STREAM_VALIDATE(stream); return __FERROR_UNLOCKED(stream); }
void funlockfile(FILE *stream) { __STDIO_STREAM_VALIDATE(stream); __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream); }