void perror(const char *s) { char msgbuf[NL_TEXTMAX]; struct iovec *v; struct iovec iov[4]; v = iov; if (s != NULL && *s != '\0') { v->iov_base = (char *)s; v->iov_len = strlen(s); v++; v->iov_base = ": "; v->iov_len = 2; v++; } strerror_r(errno, msgbuf, sizeof(msgbuf)); v->iov_base = msgbuf; v->iov_len = strlen(v->iov_base); v++; v->iov_base = "\n"; v->iov_len = 1; FLOCKFILE(stderr); __sflush(stderr); (void)_writev(stderr->_file, iov, (v - iov) + 1); stderr->_flags &= ~__SOFF; FUNLOCKFILE(stderr); }
/* * Helper function for `fprintf to unbuffered unix file': creates a * temporary buffer. We only work on write-only files; this avoids * worries about ungetc buffers and so forth. */ static int __sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) { int ret; FILE fake; struct __sfileext fakeext; unsigned char buf[BUFSIZ]; _FILEEXT_SETUP(&fake, &fakeext); /* copy the important variables */ fake._flags = fp->_flags & ~__SNBF; fake._file = fp->_file; fake._cookie = fp->_cookie; fake._write = fp->_write; #ifdef notyet fake._orientation = fp->_orientation; fake._mbstate = fp->_mbstate; #endif /* set up the buffer */ fake._bf._base = fake._p = buf; fake._bf._size = fake._w = sizeof(buf); fake._lbfsize = 0; /* not actually used, but Just In Case */ /* do the work, then copy any error status */ ret = __vfwprintf(&fake, locale, fmt, ap); if (ret >= 0 && __sflush(&fake)) ret = WEOF; if (fake._flags & __SERR) fp->_flags |= __SERR; return (ret); }
/* * Flush a single file, or (if fp is NULL) all files. * MT-safe version */ int fflush(FILE *fp) { int retval; if (fp == NULL) return (_fwalk(sflush_locked)); FLOCKFILE(fp); /* * There is disagreement about the correct behaviour of fflush() * when passed a file which is not open for reading. According to * the ISO C standard, the behaviour is undefined. * Under linux, such an fflush returns success and has no effect; * under Windows, such an fflush is documented as behaving instead * as fpurge(). * Given that applications may be written with the expectation of * either of these two behaviours, the only safe (non-astonishing) * option is to return EBADF and ask that applications be fixed. */ if ((fp->pub._flags & (__SWR | __SRW)) == 0) { errno = EBADF; retval = EOF; } else { retval = __sflush(fp); } FUNLOCKFILE(fp); return (retval); }
int fclose(FILE *fp) { int r; if (fp->_flags == 0) { /* not open! */ errno = EBADF; return (EOF); } FLOCKFILE(fp); WCIO_FREE(fp); r = fp->_flags & __SWR ? __sflush(fp) : 0; if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) r = EOF; if (fp->_flags & __SMBF) free((char *)fp->_bf._base); if (HASUB(fp)) FREEUB(fp); if (HASLB(fp)) FREELB(fp); fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ fp->_flags = 0; /* Release this FILE for reuse. */ FUNLOCKFILE(fp); return (r); }
int fclose(FILE *fp) { int r; if (fp->_flags == 0) /* not open! */ { errno = EBADF; return (EOF); } FLOCKFILE(fp); r = fp->_flags & __SWR ? __sflush(fp) : 0; if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) r = EOF; if (fp->_flags & __SMBF) FREE((char *)fp->_bf._base); if (HASUB(fp)) FREEUB(fp); if (HASLB(fp)) FREELB(fp); fp->_file = -1; fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ fp->_flags = 0; /* Release this FILE for reuse. */ osal_mutex_delete(fp->_extra->fl_mutex); FUNLOCKFILE(fp); return (r); }
static int lflush(FILE *fp) { _DIAGASSERT(fp != NULL); if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) return __sflush(fp); return 0; }
int __sflush_locked(FILE *fp) { int r; FLOCKFILE(fp); r = __sflush(fp); FUNLOCKFILE(fp); return (r); }
static int sflush_locked(FILE *fp) { int ret; FLOCKFILE(fp); ret = __sflush(fp); FUNLOCKFILE(fp); return (ret); }
/* * Write the given character into the (probably full) buffer for * the given file. Flush the buffer out if it is or becomes full, * or if c=='\n' and the file is line buffered. */ int __swbuf(int c, FILE *fp) { int n; _SET_ORIENTATION(fp, -1); /* * In case we cannot write, or longjmp takes us out early, * make sure _w is 0 (if fully- or un-buffered) or -_bf._size * (if line buffered) so that we will get called again. * If we did not do this, a sufficient number of putc() * calls might wrap _w from negative to positive. */ fp->_w = fp->_lbfsize; if (cantwrite(fp)) { errno = EBADF; return (EOF); } c = (unsigned char)c; /* * If it is completely full, flush it out. Then, in any case, * stuff c into the buffer. If this causes the buffer to fill * completely, or if c is '\n' and the file is line buffered, * flush it (perhaps a second time). The second flush will always * happen on unbuffered streams, where _bf._size==1; __sflush() * guarantees that putc() will always call wbuf() by setting _w * to 0, so we need not do anything else. */ n = fp->_p - fp->_bf._base; if (n >= fp->_bf._size) { if (__sflush(fp)) return (EOF); n = 0; } fp->_w--; *fp->_p++ = c; if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n')) if (__sflush(fp)) return (EOF); return (c); }
/* * ftell: return current offset. */ long ftell(FILE *fp) { off_t pos; FLOCKFILE(fp); if (fp->_seek == NULL) { FUNLOCKFILE(fp); errno = ESPIPE; /* historic practice */ return -1L; } /* * Find offset of underlying I/O object, then * adjust for buffered bytes. */ (void)__sflush(fp); /* may adjust seek offset on append stream */ if (fp->_flags & __SOFF) pos = fp->_offset; else { pos = (*fp->_seek)(fp->_cookie, (off_t)0, SEEK_CUR); if (pos == -1L) { FUNLOCKFILE(fp); return (long)pos; } } if (fp->_flags & __SRD) { /* * Reading. Any unread characters (including * those from ungetc) cause the position to be * smaller than that in the underlying object. */ pos -= fp->_r; if (HASUB(fp)) pos -= fp->_ur; } else if (fp->_flags & __SWR && fp->_p != NULL) { /* * Writing. Any buffered characters cause the * position to be greater than that in the * underlying object. */ pos += fp->_p - fp->_bf._base; } FUNLOCKFILE(fp); if (__long_overflow(pos)) { errno = EOVERFLOW; return -1L; } return (long)pos; }
/* Flush a single file, or (if fp is NULL) all files. */ int fflush(register FILE *fp) { if (fp == NULL) return (_fwalk(__sflush)); if ((fp->_flags & (__SWR | __SRW)) == 0) { errno = EBADF; return (EOF); } return (__sflush(fp)); }
static int lflush(FILE *fp) { int ret = 0; if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) { FLOCKFILE(fp); ret = __sflush(fp); FUNLOCKFILE(fp); } return (ret); }
/* * Flush a single file, or (if fp is NULL) all files. * Non-MT-safe version */ int __fflush(FILE *fp) { int retval; if (fp == NULL) return (_fwalk(sflush_locked)); if ((fp->_flags & (__SWR | __SRW)) == 0) retval = 0; else retval = __sflush(fp); return (retval); }
static int lflush(FILE *fp) { _DIAGASSERT(fp != NULL); if(fp == NULL) { errno = EINVAL; return (EOF); } if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) return (__sflush(fp)); return (0); }
/* * Flush a single file, or (if fp is NULL) all files. * Non-MT-safe version */ int __fflush(FILE *fp) { int retval; if (fp == NULL) return (_fwalk(sflush_locked)); if ((fp->pub._flags & (__SWR | __SRW)) == 0) { errno = EBADF; retval = EOF; } else { retval = __sflush(fp); } return (retval); }
int fflush_unlocked(FILE *fp) { int r; if (fp == NULL) return (_fwalk(__sflush)); if ((fp->_flags & (__SWR | __SRW)) == 0) { errno = EBADF; r = EOF; } else { r = __sflush(fp); } return (r); }
/* Flush a single file, or (if fp is NULL) all files. */ int fflush(FILE *fp) { int r; if (fp == NULL) return (_fwalk(__sflush_locked)); FLOCKFILE(fp); if ((fp->_flags & (__SWR | __SRW)) == 0) { errno = EBADF; r = EOF; } else r = __sflush(fp); FUNLOCKFILE(fp); return (r); }
int fflush ( FAST FILE * fp /* stream to flush */ ) { if (OBJ_VERIFY (fp, fpClassId) != OK) return (EOF); /* ANSI specifies that fflush (NULL) will flush all task's file pointers. * The problem is that we don't keep such a list today so we return EOF * for now. */ if ((fp == NULL) || ((fp->_flags & __SWR) == 0)) { errno = EBADF; return (EOF); } return (__sflush(fp)); }
int fflush( FILE *fp ) { int ret; /* Check fp */ if (fp == NULL) { errnoSet(EBADF); ret = EOF; } else { /* Check class */ if (OBJ_VERIFY(fp, fpClassId) != OK) { errnoSet(EBADF); ret = EOF; } else { /* Check flags */ if ((fp->_flags & __SWR) == 0) { errnoSet(EBADF); ret = EOF; } else { /* Flush */ ret = __sflush(fp); } } } return ret; }
int fclose(FILE *fp) { int r; if (fp->_flags == 0) { /* not open! */ errno = EBADF; return (EOF); } FLOCKFILE(fp); r = fp->_flags & __SWR ? __sflush(fp) : 0; if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0) r = EOF; if (fp->_flags & __SMBF) free((char *)fp->_bf._base); if (HASUB(fp)) FREEUB(fp); if (HASLB(fp)) FREELB(fp); fp->_file = -1; fp->_r = fp->_w = 0; /* Mess up if reaccessed. */ /* * Lock the spinlock used to protect __sglue list walk in * __sfp(). The __sfp() uses fp->_flags == 0 test as an * indication of the unused FILE. * * Taking the lock prevents possible compiler or processor * reordering of the writes performed before the final _flags * cleanup, making sure that we are done with the FILE before * it is considered available. */ STDIO_THREAD_LOCK(); fp->_flags = 0; /* Release this FILE for reuse. */ STDIO_THREAD_UNLOCK(); FUNLOCKFILE(fp); return (r); }
/* * Seek the given file to the given offset. * `Whence' must be one of the three SEEK_* macros. */ int fseeko(FILE *fp, off_t offset, int whence) { fpos_t (*seekfn)(void *, fpos_t, int); fpos_t target, curoff; size_t n; struct stat st; int havepos; /* make sure stdio is set up */ if (!__sdidinit) __sinit(); /* * Have to be able to seek. */ if ((seekfn = fp->_seek) == NULL || isatty(__sfileno(fp))) { __sseterr(fp, ESPIPE); /* historic practice */ return (EOF); } /* * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. * After this, whence is either SEEK_SET or SEEK_END. */ FLOCKFILE(fp); switch (whence) { case SEEK_CUR: /* * In order to seek relative to the current stream offset, * we have to first find the current stream offset a la * ftell (see ftell for details). */ __sflush(fp); /* may adjust seek offset on append stream */ if (fp->_flags & __SOFF) curoff = fp->_offset; else { curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); if (curoff == (fpos_t)-1) { FUNLOCKFILE(fp); return (EOF); } } if (fp->_flags & __SRD) { curoff -= fp->_r; if (HASUB(fp)) curoff -= fp->_ur; } else if (fp->_flags & __SWR && fp->_p != NULL) curoff += fp->_p - fp->_bf._base; offset += curoff; whence = SEEK_SET; havepos = 1; break; case SEEK_SET: case SEEK_END: curoff = 0; /* XXX just to keep gcc quiet */ havepos = 0; break; default: FUNLOCKFILE(fp); __sseterr(fp, EINVAL); return (EOF); } /* * Can only optimise if: * reading (and not reading-and-writing); * not unbuffered; and * this is a `regular' Unix file (and hence seekfn==__sseek). * We must check __NBF first, because it is possible to have __NBF * and __SOPT both set. */ if (fp->_bf._base == NULL) __smakebuf(fp); if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT)) goto dumb; if ((fp->_flags & __SOPT) == 0) { if (seekfn != __sseek || fp->_file < 0 || __libc_fstat(fp->_file, &st) || (st.st_mode & S_IFMT) != S_IFREG) { fp->_flags |= __SNPT; goto dumb; } fp->_blksize = st.st_blksize; fp->_flags |= __SOPT; } /* * We are reading; we can try to optimise. * Figure out where we are going and where we are now. */ if (whence == SEEK_SET) target = offset; else { if (__libc_fstat(fp->_file, &st)) goto dumb; target = st.st_size + offset; } if (!havepos) { if (fp->_flags & __SOFF) curoff = fp->_offset; else { curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR); if (curoff == POS_ERR) goto dumb; } curoff -= fp->_r; if (HASUB(fp)) curoff -= fp->_ur; } /* * Compute the number of bytes in the input buffer (pretending * that any ungetc() input has been discarded). Adjust current * offset backwards by this count so that it represents the * file offset for the first byte in the current input buffer. */ if (HASUB(fp)) { curoff += fp->_r; /* kill off ungetc */ n = fp->_up - fp->_bf._base; curoff -= n; n += fp->_ur; } else { n = fp->_p - fp->_bf._base; curoff -= n; n += fp->_r; } /* * If the target offset is within the current buffer, * simply adjust the pointers, clear EOF, undo ungetc(), * and return. (If the buffer was modified, we have to * skip this; see fgetln.c.) */ if ((fp->_flags & __SMOD) == 0 && target >= curoff && target < curoff + n) { int o = target - curoff; fp->_p = fp->_bf._base + o; fp->_r = n - o; if (HASUB(fp)) FREEUB(fp); fp->_flags &= ~__SEOF; FUNLOCKFILE(fp); return (0); } /* * The place we want to get to is not within the current buffer, * but we can still be kind to the kernel copyout mechanism. * By aligning the file offset to a block boundary, we can let * the kernel use the VM hardware to map pages instead of * copying bytes laboriously. Using a block boundary also * ensures that we only read one block, rather than two. */ curoff = target & ~(fp->_blksize - 1); if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) == POS_ERR) goto dumb; fp->_r = 0; fp->_p = fp->_bf._base; if (HASUB(fp)) FREEUB(fp); fp->_flags &= ~__SEOF; n = target - curoff; if (n) { if (__srefill(fp) || fp->_r < n) goto dumb; fp->_p += n; fp->_r -= n; } FUNLOCKFILE(fp); return (0); /* * We get here if we cannot optimise the seek ... just * do it. Allow the seek function to change fp->_bf._base. */ dumb: if (__sflush(fp) || (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) { FUNLOCKFILE(fp); return (EOF); } /* success: clear EOF indicator and discard ungetc() data */ if (HASUB(fp)) FREEUB(fp); fp->_p = fp->_bf._base; fp->_r = 0; /* fp->_w = 0; */ /* unnecessary (I think...) */ fp->_flags &= ~__SEOF; FUNLOCKFILE(fp); return (0); }
/* * Set one of the three kinds of buffering, optionally including * a buffer. */ int setvbuf(FILE *fp, char *buf, int mode, size_t size) { int ret, flags; size_t iosize; int ttyflag; /* * Verify arguments. The `int' limit on `size' is due to this * particular implementation. Note, buf and size are ignored * when setting _IONBF. */ if (mode != _IONBF) if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0) return (EOF); /* * Write current buffer, if any. Discard unread input (including * ungetc data), cancel line buffering, and free old buffer if * malloc()ed. We also clear any eof condition, as if this were * a seek. */ ret = 0; (void)__sflush(fp); if (HASUB(fp)) FREEUB(fp); WCIO_FREE(fp); fp->_r = fp->_lbfsize = 0; flags = fp->_flags; if (flags & __SMBF) free((void *)fp->_bf._base); flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT | __SEOF); /* If setting unbuffered mode, skip all the hard work. */ if (mode == _IONBF) goto nbf; /* * Find optimal I/O size for seek optimization. This also returns * a `tty flag' to suggest that we check isatty(fd), but we do not * care since our caller told us how to buffer. */ flags |= __swhatbuf(fp, &iosize, &ttyflag); if (size == 0) { buf = NULL; /* force local allocation */ size = iosize; } /* Allocate buffer if needed. */ if (buf == NULL) { if ((buf = malloc(size)) == NULL) { /* * Unable to honor user's request. We will return * failure, but try again with file system size. */ ret = EOF; if (size != iosize) { size = iosize; buf = malloc(size); } } if (buf == NULL) { /* No luck; switch to unbuffered I/O. */ nbf: fp->_flags = flags | __SNBF; fp->_w = 0; fp->_bf._base = fp->_p = fp->_nbuf; fp->_bf._size = 1; return (ret); } flags |= __SMBF; } /* * Kill any seek optimization if the buffer is not the * right size. * * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)? */ if (size != iosize) flags |= __SNPT; /* * Fix up the FILE fields, and set __cleanup for output flush on * exit (since we are buffered in some way). */ if (mode == _IOLBF) flags |= __SLBF; fp->_flags = flags; fp->_bf._base = fp->_p = (unsigned char *)buf; fp->_bf._size = size; /* fp->_lbfsize is still 0 */ if (flags & __SWR) { /* * Begin or continue writing: see __swsetup(). Note * that __SNBF is impossible (it was handled earlier). */ if (flags & __SLBF) { fp->_w = 0; fp->_lbfsize = -fp->_bf._size; } else fp->_w = size; } else { /* begin/continue reading, or stay in intermediate state */ fp->_w = 0; } __atexit_register_cleanup(_cleanup); return (ret); }
int _ftello(FILE *fp, fpos_t *offset) { fpos_t pos; size_t n; int dflags; if (fp->_seek == NULL) { errno = ESPIPE; /* historic practice */ return (1); } /* * Find offset of underlying I/O object, then * adjust for buffered bytes. */ if (fp->_flags & __SOFF) pos = fp->_offset; else { pos = _sseek(fp, (fpos_t)0, SEEK_CUR); if (pos == -1) return (1); } if (fp->_flags & __SRD) { /* * Reading. Any unread characters (including * those from ungetc) cause the position to be * smaller than that in the underlying object. */ if ((pos -= (HASUB(fp) ? fp->_ur : fp->_r)) < 0) { fp->_flags |= __SERR; errno = EIO; return (1); } if (HASUB(fp)) pos -= fp->_r; /* Can be negative at this point. */ } else if ((fp->_flags & __SWR) && fp->_p != NULL) { dflags = 0; if (fp->_flags & __SAPP) dflags = O_APPEND; else if (fp->_file != -1 && (dflags = _fcntl(fp->_file, F_GETFL)) < 0) return (1); if ((dflags & O_APPEND) && (pos = _sseek(fp, (fpos_t)0, SEEK_END)) == -1) { if ((fp->_flags & __SOPT) || __sflush(fp) || (pos = _sseek(fp, (fpos_t)0, SEEK_CUR)) == -1) return (1); else { *offset = pos; return (0); } } /* * Writing. Any buffered characters cause the * position to be greater than that in the * underlying object. */ n = fp->_p - fp->_bf._base; if (pos > OFF_MAX - n) { errno = EOVERFLOW; return (1); } pos += n; } *offset = pos; return (0); }
/* * Refill a stdio buffer. * Return EOF on eof or error, 0 otherwise. */ int __srefill(FILE *fp) { _DIAGASSERT(fp != NULL); if(fp == NULL) { errno = EINVAL; return (EOF); } /* make sure stdio is set up */ if (!__sdidinit) __sinit(); fp->_r = 0; /* largely a convenience for callers */ /* SysV does not make this test; take it out for compatibility */ if (fp->_flags & __SEOF) { return (EOF); } /* if not already reading, have to be reading and writing */ if ((fp->_flags & __SRD) == 0) { if ((fp->_flags & __SRW) == 0) { errno = EBADF; fp->_flags |= __SERR; //<dvm> Allows differentiation between errors and EOF return (EOF); } /* switch to reading */ if (fp->_flags & __SWR) { if (__sflush(fp)) { return (EOF); } fp->_flags &= ~__SWR; fp->_w = 0; fp->_lbfsize = 0; } fp->_flags |= __SRD; } else { /* * We were reading. If there is an ungetc buffer, * we must have been reading from that. Drop it, * restoring the previous buffer (if any). If there * is anything in that buffer, return. */ if (HASUB(fp)) { FREEUB(fp); if ((fp->_r = fp->_ur) != 0) { fp->_p = fp->_up; return (0); } } } if (fp->_bf._base == NULL) __smakebuf(fp); /* * Before reading from a line buffered or unbuffered file, * flush all line buffered output files, per the ANSI C * standard. */ if (fp->_flags & (__SLBF|__SNBF)) { rwlock_rdlock(&__sfp_lock); (void) _fwalk(lflush); rwlock_unlock(&__sfp_lock); } fp->_p = fp->_bf._base; fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size); fp->_flags &= ~__SMOD; /* buffer contents are again pristine */ if (fp->_r <= 0) { if (fp->_r == 0) fp->_flags |= __SEOF; else { fp->_r = 0; fp->_flags |= __SERR; } return (EOF); } return (0); }
/* * Seek the given file to the given offset. * `Whence' must be one of the three SEEK_* macros. */ int _fseeko(FILE *fp, off_t offset, int whence, int ltest) { fpos_t (*seekfn)(void *, fpos_t, int); fpos_t target, curoff, ret; size_t n; struct stat st; int havepos; /* * Have to be able to seek. */ if ((seekfn = fp->_seek) == NULL) { errno = ESPIPE; /* historic practice */ return (-1); } /* * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. * After this, whence is either SEEK_SET or SEEK_END. */ switch (whence) { case SEEK_CUR: /* * In order to seek relative to the current stream offset, * we have to first find the current stream offset via * ftell (see ftell for details). */ if (_ftello(fp, &curoff)) return (-1); if (curoff < 0) { /* Unspecified position because of ungetc() at 0 */ errno = ESPIPE; return (-1); } if (offset > 0 && curoff > OFF_MAX - offset) { errno = EOVERFLOW; return (-1); } offset += curoff; if (offset < 0) { errno = EINVAL; return (-1); } if (ltest && offset > LONG_MAX) { errno = EOVERFLOW; return (-1); } whence = SEEK_SET; havepos = 1; break; case SEEK_SET: if (offset < 0) { errno = EINVAL; return (-1); } case SEEK_END: curoff = 0; /* XXX just to keep gcc quiet */ havepos = 0; break; default: errno = EINVAL; return (-1); } /* * Can only optimise if: * reading (and not reading-and-writing); * not unbuffered; and * this is a `regular' Unix file (and hence seekfn==__sseek). * We must check __NBF first, because it is possible to have __NBF * and __SOPT both set. */ if (fp->_bf._base == NULL) __smakebuf(fp); if (fp->pub._flags & (__SWR | __SRW | __SNBF | __SNPT)) goto dumb; if ((fp->pub._flags & __SOPT) == 0) { if (seekfn != __sseek || fp->pub._fileno < 0 || _fstat(fp->pub._fileno, &st) || (st.st_mode & S_IFMT) != S_IFREG) { fp->pub._flags |= __SNPT; goto dumb; } fp->_blksize = st.st_blksize; fp->pub._flags |= __SOPT; } /* * We are reading; we can try to optimise. * Figure out where we are going and where we are now. */ if (whence == SEEK_SET) target = offset; else { if (_fstat(fp->pub._fileno, &st)) goto dumb; if (offset > 0 && st.st_size > OFF_MAX - offset) { errno = EOVERFLOW; return (-1); } target = st.st_size + offset; if ((off_t)target < 0) { errno = EINVAL; return (-1); } if (ltest && (off_t)target > LONG_MAX) { errno = EOVERFLOW; return (-1); } } if (!havepos && _ftello(fp, &curoff)) goto dumb; /* * (If the buffer was modified, we have to * skip this; see fgetln.c.) */ if (fp->pub._flags & __SMOD) goto abspos; /* * Compute the number of bytes in the input buffer (pretending * that any ungetc() input has been discarded). Adjust current * offset backwards by this count so that it represents the * file offset for the first byte in the current input buffer. */ if (HASUB(fp)) { curoff += fp->pub._r; /* kill off ungetc */ n = fp->_up - fp->_bf._base; curoff -= n; n += fp->_ur; } else { n = fp->pub._p - fp->_bf._base; curoff -= n; n += fp->pub._r; } /* * If the target offset is within the current buffer, * simply adjust the pointers, clear EOF, undo ungetc(), * and return. */ if (target >= curoff && target < curoff + n) { size_t o = target - curoff; fp->pub._p = fp->_bf._base + o; fp->pub._r = n - o; if (HASUB(fp)) FREEUB(fp); fp->pub._flags &= ~__SEOF; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (0); } abspos: /* * The place we want to get to is not within the current buffer, * but we can still be kind to the kernel copyout mechanism. * By aligning the file offset to a block boundary, we can let * the kernel use the VM hardware to map pages instead of * copying bytes laboriously. Using a block boundary also * ensures that we only read one block, rather than two. */ curoff = target & ~(fp->_blksize - 1); if (_sseek(fp, curoff, SEEK_SET) == POS_ERR) goto dumb; fp->pub._r = 0; fp->pub._p = fp->_bf._base; if (HASUB(fp)) FREEUB(fp); n = target - curoff; if (n) { if (__srefill(fp) || fp->pub._r < n) goto dumb; fp->pub._p += n; fp->pub._r -= n; } fp->pub._flags &= ~__SEOF; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (0); /* * We get here if we cannot optimise the seek ... just * do it. Allow the seek function to change fp->_bf._base. */ dumb: if (__sflush(fp) || (ret = _sseek(fp, (fpos_t)offset, whence)) == POS_ERR) return (-1); if (ltest && ret > LONG_MAX) { fp->pub._flags |= __SERR; errno = EOVERFLOW; return (-1); } /* success: clear EOF indicator and discard ungetc() data */ if (HASUB(fp)) FREEUB(fp); fp->pub._p = fp->_bf._base; fp->pub._r = 0; /* fp->pub._w = 0; */ /* unnecessary (I think...) */ fp->pub._flags &= ~__SEOF; memset(WCIO_GET(fp), 0, sizeof(struct wchar_io_data)); return (0); }
/* * Re-direct an existing, open (probably) file to some other file. * ANSI is written such that the original file gets closed if at * all possible, no matter what. */ FILE * freopen(const char *file, const char *mode, register FILE *fp) { register int f; int flags, isopen, oflags, sverrno, wantfd; if ((flags = __sflags(mode, &oflags)) == 0) { (void) fclose(fp); return (NULL); } if (!__sdidinit) __sinit(); /* * There are actually programs that depend on being able to "freopen" * descriptors that weren't originally open. Keep this from breaking. * Remember whether the stream was open to begin with, and which file * descriptor (if any) was associated with it. If it was attached to * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin) * should work. This is unnecessary if it was not a Unix file. */ if (fp->_flags == 0) { fp->_flags = __SEOF; /* hold on to it */ isopen = 0; wantfd = -1; } else { /* flush the stream; ANSI doesn't require this. */ if (fp->_flags & __SWR) (void) __sflush(fp); /* if close is NULL, closing is a no-op, hence pointless */ isopen = fp->_close != NULL; if ((wantfd = fp->_file) < 0 && isopen) { (void) (*fp->_close)(fp->_cookie); isopen = 0; } } /* Get a new descriptor to refer to the new file. */ #ifdef __ORCAC__ /* * ORCA/C uses "callee cleans up", so the third arg to open(2) * can be given if and only if it is expected. */ f = (oflags & O_CREAT) ? open(file, oflags, DEFFILEMODE) : open(file, oflags); #else f = open(file, oflags, DEFFILEMODE); #endif if (f < 0 && isopen) { /* If out of fd's close the old one and try again. */ #ifdef __GNO__ if (errno == EMFILE) { /* no ENFILE for GNO */ #else if (errno == ENFILE || errno == EMFILE) { #endif (void) (*fp->_close)(fp->_cookie); isopen = 0; f = open(file, oflags, DEFFILEMODE); } } sverrno = errno; /* * Finish closing fp. Even if the open succeeded above, we cannot * keep fp->_base: it may be the wrong size. This loses the effect * of any setbuffer calls, but stdio has always done this before. */ if (isopen) (void) (*fp->_close)(fp->_cookie); if (fp->_flags & __SMBF) free((char *)fp->_bf._base); fp->_w = 0; fp->_r = 0; fp->_p = NULL; fp->_bf._base = NULL; fp->_bf._size = 0; fp->_lbfsize = 0; if (HASUB(fp)) FREEUB(fp); fp->_ub._size = 0; if (HASLB(fp)) FREELB(fp); fp->_lb._size = 0; if (f < 0) { /* did not get it after all */ fp->_flags = 0; /* set it free */ errno = sverrno; /* restore in case _close clobbered */ return (NULL); } /* * If reopening something that was open before on a real file, try * to maintain the descriptor. Various C library routines (perror) * assume stderr is always fd STDERR_FILENO, even if being freopen'd. */ if (wantfd >= 0 && f != wantfd) { if (dup2(f, wantfd) >= 0) { (void) close(f); f = wantfd; } } fp->_flags = flags; fp->_file = f; fp->_cookie = fp; fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; return (fp); }
int fseek ( FAST FILE * fp, /* stream */ long offset, /* offset from <whence> */ int whence /* position to offset from: */ /* SEEK_SET = beginning */ /* SEEK_CUR = current position */ /* SEEK_END = end-of-file */ ) { fpos_t target; fpos_t curoff; size_t n; struct stat st; int havepos; BOOL doStat; if (OBJ_VERIFY (fp, fpClassId) != OK) return (ERROR); /* * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. * After this, whence is either SEEK_SET or SEEK_END. */ switch (whence) { case SEEK_CUR: /* * In order to seek relative to the current stream offset, * we have to first find the current stream offset a la * ftell (see ftell for details). */ if (fp->_flags & __SOFF) curoff = fp->_offset; else { curoff = __sseek (fp, (fpos_t)0, SEEK_CUR); if (curoff == -1L) return (EOF); } if (fp->_flags & __SRD) { curoff -= fp->_r; if (HASUB(fp)) curoff -= fp->_ur; } else if (fp->_flags & __SWR && fp->_p != NULL) curoff += fp->_p - fp->_bf._base; offset += curoff; whence = SEEK_SET; havepos = 1; break; case SEEK_SET: case SEEK_END: curoff = 0; /* XXX just to keep gcc quiet */ havepos = 0; break; default: errno = EINVAL; return (EOF); } /* * Can only optimise if: * reading (and not reading-and-writing); * not unbuffered; and * this is a `regular' Unix file (and hence seekfn==__sseek). * We must check __NBF first, because it is possible to have __NBF * and __SOPT both set. */ if (fp->_bf._base == NULL) __smakebuf (fp); if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT)) goto dumb; doStat = ioctl (fp->_file, FIOFSTATGET, (int)&st); if ((fp->_flags & __SOPT) == 0) { if ((fp->_file < 0 || (doStat) || (st.st_mode & S_IFMT) != S_IFREG)) { fp->_flags |= __SNPT; goto dumb; } fp->_blksize = st.st_blksize; fp->_flags |= __SOPT; } /* * We are reading; we can try to optimise. * Figure out where we are going and where we are now. */ if (whence == SEEK_SET) target = offset; else { if (doStat) goto dumb; target = st.st_size + offset; } if (!havepos) { if (fp->_flags & __SOFF) curoff = fp->_offset; else { curoff = __sseek (fp, 0L, SEEK_CUR); if (curoff == POS_ERR) goto dumb; } curoff -= fp->_r; if (HASUB(fp)) curoff -= fp->_ur; } /* * Compute the number of bytes in the input buffer (pretending * that any ungetc() input has been discarded). Adjust current * offset backwards by this count so that it represents the * file offset for the first byte in the current input buffer. */ if (HASUB(fp)) { n = fp->_up - fp->_bf._base; curoff -= n; n += fp->_ur; } else { n = fp->_p - fp->_bf._base; curoff -= n; n += fp->_r; } /* * If the target offset is within the current buffer, * simply adjust the pointers, clear EOF, undo ungetc(), * and return. (If the buffer was modified, we have to * skip this; see fgetline.c.) */ if (((fp->_flags & __SMOD) == 0) && (target >= curoff) && (target < (curoff + n))) { FAST int o = target - curoff; fp->_p = fp->_bf._base + o; fp->_r = n - o; if (HASUB(fp)) FREEUB(fp); fp->_flags &= ~__SEOF; return (0); } /* * The place we want to get to is not within the current buffer, * but we can still be kind to the kernel copyout mechanism. * By aligning the file offset to a block boundary, we can let * the kernel use the VM hardware to map pages instead of * copying bytes laboriously. Using a block boundary also * ensures that we only read one block, rather than two. */ curoff = target & ~(fp->_blksize - 1); if (__sseek (fp, curoff, SEEK_SET) == POS_ERR) goto dumb; fp->_r = 0; if (HASUB(fp)) FREEUB(fp); fp->_flags &= ~__SEOF; n = target - curoff; if (n) { if (__srefill (fp) || fp->_r < n) goto dumb; fp->_p += n; fp->_r -= n; } return (0); /* * We get here if we cannot optimise the seek ... just * do it. Allow the seek function to change fp->_bf._base. */ dumb: if ((__sflush (fp)) || (__sseek (fp, offset, whence) == POS_ERR)) return (EOF); /* success: clear EOF indicator and discard ungetc() data */ if (HASUB(fp)) FREEUB(fp); fp->_p = fp->_bf._base; fp->_r = 0; /* fp->_w = 0; */ /* unnecessary (I think...) */ fp->_flags &= ~__SEOF; return (0); }
/* * Re-direct an existing, open (probably) file to some other file. * ANSI is written such that the original file gets closed if at * all possible, no matter what. */ FILE * freopen(const char *file, const char *mode, FILE *fp) { int f; int flags, isopen, oflags, sverrno, wantfd; if ((flags = __sflags(mode, &oflags)) == 0) { (void) fclose(fp); return (NULL); } if (!__sdidinit) __sinit(); /* * There are actually programs that depend on being able to "freopen" * descriptors that weren't originally open. Keep this from breaking. * Remember whether the stream was open to begin with, and which file * descriptor (if any) was associated with it. If it was attached to * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin) * should work. This is unnecessary if it was not a Unix file. */ if (fp->_flags == 0) { fp->_flags = __SEOF; /* hold on to it */ isopen = 0; wantfd = -1; } else { /* flush the stream; ANSI doesn't require this. */ if (fp->_flags & __SWR) (void) __sflush(fp); /* if close is NULL, closing is a no-op, hence pointless */ isopen = fp->_close != NULL; if ((wantfd = fp->_file) < 0 && isopen) { (void) (*fp->_close)(fp->_cookie); isopen = 0; } } /* Get a new descriptor to refer to the new file. */ f = open(file, oflags, DEFFILEMODE); if (f < 0 && isopen) { /* If out of fd's close the old one and try again. */ if (errno == ENFILE || errno == EMFILE) { (void) (*fp->_close)(fp->_cookie); isopen = 0; f = open(file, oflags, DEFFILEMODE); } } sverrno = errno; /* * Finish closing fp. Even if the open succeeded above, we cannot * keep fp->_base: it may be the wrong size. This loses the effect * of any setbuffer calls, but stdio has always done this before. */ if (isopen && f != wantfd) (void) (*fp->_close)(fp->_cookie); if (fp->_flags & __SMBF) free((char *)fp->_bf._base); fp->_w = 0; fp->_r = 0; fp->_p = NULL; fp->_bf._base = NULL; fp->_bf._size = 0; fp->_lbfsize = 0; if (HASUB(fp)) FREEUB(fp); _UB(fp)._size = 0; WCIO_FREE(fp); if (HASLB(fp)) FREELB(fp); fp->_lb._size = 0; if (f < 0) { /* did not get it after all */ fp->_flags = 0; /* set it free */ errno = sverrno; /* restore in case _close clobbered */ return (NULL); } /* * If reopening something that was open before on a real file, try * to maintain the descriptor. Various C library routines (perror) * assume stderr is always fd STDERR_FILENO, even if being freopen'd. */ if (wantfd >= 0 && f != wantfd) { if (dup2(f, wantfd) >= 0) { (void) close(f); f = wantfd; } } fp->_flags = flags; fp->_file = f; fp->_cookie = fp; fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; /* * When opening in append mode, even though we use O_APPEND, * we need to seek to the end so that ftell() gets the right * answer. If the user then alters the seek pointer, or * the file extends, this will fail, but there is not much * we can do about this. (We could set __SAPP and check in * fseek and ftell.) */ if (oflags & O_APPEND) (void) __sseek((void *)fp, (fpos_t)0, SEEK_END); return (fp); }
int __sungetc(int c, FILE *fp) { if (c == EOF) return (EOF); if (!__sdidinit) __sinit(); /*FLOCKFILE(fp);*/ _SET_ORIENTATION(fp, -1); if ((fp->_flags & __SRD) == 0) { /* * Not already reading: no good unless reading-and-writing. * Otherwise, flush any current write stuff. */ if ((fp->_flags & __SRW) == 0) { error: /*FUNLOCKFILE(fp);*/ return (EOF); } if (fp->_flags & __SWR) { if (__sflush(fp)) goto error; fp->_flags &= ~__SWR; fp->_w = 0; fp->_lbfsize = 0; } fp->_flags |= __SRD; } c = (unsigned char)c; /* * If we are in the middle of ungetc'ing, just continue. * This may require expanding the current ungetc buffer. */ if (HASUB(fp)) { if (fp->_r >= _UB(fp)._size && __submore(fp)) goto error; *--fp->_p = c; inc_ret: fp->_r++; /*FUNLOCKFILE(fp);*/ return (c); } fp->_flags &= ~__SEOF; /* * If we can handle this by simply backing up, do so, * but never replace the original character. * (This makes sscanf() work when scanning `const' data.) */ if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c) { fp->_p--; goto inc_ret; } /* * Create an ungetc buffer. * Initially, we will use the `reserve' buffer. */ fp->_ur = fp->_r; fp->_up = fp->_p; _UB(fp)._base = fp->_ubuf; _UB(fp)._size = sizeof(fp->_ubuf); fp->_ubuf[sizeof(fp->_ubuf) - 1] = c; fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1]; fp->_r = 1; /*FUNLOCKFILE(fp);*/ return (c); }
/* * Refill a stdio buffer. * Return EOF on eof or error, 0 otherwise. */ int __srefill(FILE *fp) { /* make sure stdio is set up */ if (!__sdidinit) __sinit(); ORIENT(fp, -1); fp->_r = 0; /* largely a convenience for callers */ /* SysV does not make this test; take it out for compatibility */ if (fp->_flags & __SEOF) return (EOF); /* if not already reading, have to be reading and writing */ if ((fp->_flags & __SRD) == 0) { if ((fp->_flags & __SRW) == 0) { errno = EBADF; fp->_flags |= __SERR; return (EOF); } /* switch to reading */ if (fp->_flags & __SWR) { if (__sflush(fp)) return (EOF); fp->_flags &= ~__SWR; fp->_w = 0; fp->_lbfsize = 0; } fp->_flags |= __SRD; } else { /* * We were reading. If there is an ungetc buffer, * we must have been reading from that. Drop it, * restoring the previous buffer (if any). If there * is anything in that buffer, return. */ if (HASUB(fp)) { FREEUB(fp); if ((fp->_r = fp->_ur) != 0) { fp->_p = fp->_up; return (0); } } } if (fp->_bf._base == NULL) __smakebuf(fp); /* * Before reading from a line buffered or unbuffered file, * flush all line buffered output files, per the ANSI C * standard. */ if (fp->_flags & (__SLBF|__SNBF)) { /* Ignore this file in _fwalk to avoid potential deadlock. */ fp->_flags |= __SIGN; (void) _fwalk(lflush); fp->_flags &= ~__SIGN; /* Now flush this file without locking it. */ if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) __sflush(fp); } fp->_p = fp->_bf._base; fp->_r = _sread(fp, (char *)fp->_p, fp->_bf._size); fp->_flags &= ~__SMOD; /* buffer contents are again pristine */ if (fp->_r <= 0) { if (fp->_r == 0) fp->_flags |= __SEOF; else { fp->_r = 0; fp->_flags |= __SERR; } return (EOF); } return (0); }