예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
/*
 * Various output routines call wsetup to be sure it is safe to write,
 * because either _flags does not include __SWR, or _buf is NULL.
 * _wsetup returns 0 if OK to write, nonzero otherwise.
 */
int
__swsetup(FILE *fp)
{
	/* make sure stdio is set up */
	if (!__sdidinit)
		__sinit();

	/*
	 * If we are not writing, we had better be reading and writing.
	 */
	if ((fp->_flags & __SWR) == 0) {
		if ((fp->_flags & __SRW) == 0)
			return (EOF);
		if (fp->_flags & __SRD) {
			/* clobber any ungetc data */
			if (HASUB(fp))
				FREEUB(fp);
			fp->_flags &= ~(__SRD|__SEOF);
			fp->_r = 0;
			fp->_p = fp->_bf._base;
		}
		fp->_flags |= __SWR;
	}

	/*
	 * Make a buffer if necessary, then set _w.
	 */
	if (fp->_bf._base == NULL) {
		if ((fp->_flags & (__SSTR | __SALC)) == __SSTR)
			return (EOF);
		__smakebuf(fp);
	}
	
	if (fp->_flags & __SLBF) {
		/*
		 * It is line buffered, so make _lbfsize be -_bufsize
		 * for the putc() macro.  We will change _lbfsize back
		 * to 0 whenever we turn off __SWR.
		 */
		fp->_w = 0;
		fp->_lbfsize = -fp->_bf._size;
	} else
		fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size;
	return (0);
}
예제 #4
0
/*
 * fpurge: like fflush, but without writing anything: leave the
 * given FILE's buffer empty.
 */
int
fpurge(FILE *fp)
{
	FLOCKFILE(fp);
	if (!fp->_flags) {
		FUNLOCKFILE(fp);
		errno = EBADF;
		return(EOF);
	}

	if (HASUB(fp))
		FREEUB(fp);
	WCIO_FREE(fp);
	fp->_p = fp->_bf._base;
	fp->_r = 0;
	fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
	FUNLOCKFILE(fp);
	return (0);
}
예제 #5
0
fpos_t _sseek(FILE *fp, fpos_t offset, int whence)
{
	fpos_t ret;
	int serrno, errret;

	serrno = errno;
	errno = 0;
	ret = (*fp->_seek)(fp->_cookie, offset, whence);
	errret = errno;
	if (errno == 0)
		errno = serrno;
	/*
	 * Disallow negative seeks per POSIX.
	 * It is needed here to help upper level caller
	 * in the cases it can't detect.
	 */
	if (ret < 0)
	{
		if (errret == 0)
		{
			if (offset != 0 || whence != SEEK_CUR)
			{
				if (HASUB(fp))
					FREEUB(fp);
				fp->_p = fp->_bf._base;
				fp->_r = 0;
				fp->_flags &= ~__SEOF;
			}
			fp->_flags |= __SERR;
			errno = EINVAL;
		}
		else if (errret == ESPIPE)
			fp->_flags &= ~__SAPP;
		fp->_flags &= ~__SOFF;
		ret = -1;
	}
	else if (fp->_flags & __SOPT)
	{
		fp->_flags |= __SOFF;
		fp->_offset = ret;
	}
	return (ret);
}
예제 #6
0
파일: fpurge.c 프로젝트: 2asoft/freebsd
/*
 * fpurge: like fflush, but without writing anything: leave the
 * given FILE's buffer empty.
 */
int
fpurge(FILE *fp)
{
	int retval;
	FLOCKFILE(fp);
	if (!fp->_flags) {
		errno = EBADF;
		retval = EOF;
	} else {
		if (HASUB(fp))
			FREEUB(fp);
		fp->_p = fp->_bf._base;
		fp->_r = 0;
		fp->_w = fp->_flags & (__SLBF|__SNBF|__SRD) ? 0 : fp->_bf._size;
		retval = 0;
	}
	FUNLOCKFILE(fp);
	return (retval);
}
예제 #7
0
파일: fpurge.c 프로젝트: AgamAgarwal/minix
/*
 * fpurge: like fflush, but without writing anything: leave the
 * given FILE's buffer empty.
 */
int
fpurge(FILE *fp)
{

	_DIAGASSERT(fp != NULL);

	if (fp->_flags == 0) {
		errno = EBADF;
		return EOF;
	}
	FLOCKFILE(fp);
	if (HASUB(fp))
		FREEUB(fp);
	WCIO_FREE(fp);
	fp->_p = fp->_bf._base;
	fp->_r = 0;
	fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
	FUNLOCKFILE(fp);
	return 0;
}
예제 #8
0
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);
}
예제 #9
0
파일: setvbuf.c 프로젝트: fortek/Fly_IQ_245
/*
 * 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);
}
예제 #10
0
파일: refill.c 프로젝트: B-Rich/edk2
/*
 * 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);
}
예제 #11
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);
}
예제 #12
0
파일: freopen.c 프로젝트: JinSeok/GIT_Test
/*
 * 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);
}
예제 #13
0
파일: fseek.c 프로젝트: andy345/vxworks5
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);
    }
예제 #14
0
파일: freopen.c 프로젝트: GnoConsortium/gno
/*
 * 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);
}
예제 #15
0
FILE *freopen( const char *filename, const char *mode, FILE *stream )
{
	register int f;
	int wantfd, isopen, flags, oflags, e;

	if (filename == NULL || filename[0] == '\0')
		return NULL;
        EXCL_START(&stream->_file_lock);
	if ((flags = __sflags(mode, &oflags)) == 0) {
		EXCL_END(&stream->_file_lock);
		(void) fclose(stream);
		return NULL;
	}
	if (!__sdidinit)
		__sinit();

	/*
	 * 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,
	 * so that, e.g., freopen("/dev/stdin", "r", stdin) works.
	 * This is unnecessary if it was not a Unix file.
	 */
	if (stream->_flags == 0) {
		stream->_flags = __SEOF;	/* hold on to it */
		isopen = 0;
		wantfd = -1;
	} else {
		if (stream->_flags & __SWR)
			(void) _fflush(stream);
		/* if close is NULL, closing is a no-op, hence pointless */
		isopen = stream->_close != NULL;
		if ((wantfd = stream->_file) < 0 && isopen) {
			(void) (*stream->_close)(stream->_cookie);
			isopen = 0;
		}
	}

	/*
	 * Now get a new descriptor to refer to the new file.
	 */
	f = _open(filename, oflags, 0666);
	if (f < 0 && isopen) {
		/*
		 * May have used up all descriptors, so close the old
		 * and try again.
		 */
		(void) (*stream->_close)(stream->_cookie);
		isopen = 0;
		f = _open(filename, oflags, 0666);
	}
	e = errno;

	/*
	 * Finish closing stream.  Even if the open succeeded above,
	 * we cannot keep stream->_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) (*stream->_close)(stream->_cookie);
	if (stream->_flags & __SMBF)
		free((char *)stream->_bf._base);
	stream->_w = 0;
	stream->_r = 0;
	stream->_p = NULL;
	stream->_bf._base = NULL;
	stream->_bf._size = 0;
	stream->_lbfsize = 0;
	if (HASUB(stream))
		FREEUB(stream);
	stream->_ub._size = 0;
	if (HASLB(stream))
		FREELB(stream);
	stream->_lb._size = 0;

	if (f < 0) {			/* did not get it after all */
		stream->_flags = 0;		/* set it free */
		errno = e;		/* restore in case _close clobbered */
		EXCL_END(&stream->_file_lock);
		return NULL;
	}

#ifdef NOTDEF
	/*
	 * If reopening something that was open before on a real file,
	 * try to maintain the descriptor.  Various routines (e.g.,
	 * perror) assume that after `freopen(name, mode, stderr)',
	 * fileno(stderr)==2.
	 */
	if (wantfd >= 0 && f != wantfd) {
		if (_dup2(f, wantfd) >= 0) {
			(void) _close(f);
			f = wantfd;
		}
	}
#endif /* NOTDEF */

	stream->_flags = flags;
	stream->_file = f;
	stream->_cookie = stream;
	stream->_read = __sread;
	stream->_write = __swrite;
	stream->_seek = __sseek;
	stream->_close = __sclose;
	EXCL_END(&stream->_file_lock);
	return stream;
}
예제 #16
0
파일: freopen64.c 프로젝트: mlyle/newlib
FILE *
_freopen64_r (struct _reent *ptr,
	const char *file,
	const char *mode,
	register FILE *fp)
{
  register int f;
  int flags, oflags, oflags2;
  int e = 0;


  CHECK_INIT (ptr, fp);

  /* We can't use the _newlib_flockfile_XXX macros here due to the
     interlocked locking with the sfp_lock. */
#ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
  int __oldcancel;
  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &__oldcancel);
#endif
  oflags2 = fp->_flags2;
  if (!(oflags2 & __SNLK))
    _flockfile (fp);

  if ((flags = __sflags (ptr, mode, &oflags)) == 0)
    {
      if (!(oflags2 & __SNLK))
	_funlockfile (fp);
#ifdef _STDIO_WITH_THREAD_CANCELLATION_SUPPORT
      pthread_setcancelstate (__oldcancel, &__oldcancel);
#endif
      _fclose_r (ptr, fp);
      return NULL;
    }

  /*
   * 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,
   * so that, e.g., freopen("/dev/stdin", "r", stdin) works.
   * This is unnecessary if it was not a Unix file.
   */

  if (fp->_flags == 0)
    fp->_flags = __SEOF;	/* hold on to it */
  else
    {
      if (fp->_flags & __SWR)
	_fflush_r (ptr, fp);
      /*
       * If close is NULL, closing is a no-op, hence pointless.
       * If file is NULL, the file should not be closed.
       */
      if (fp->_close != NULL && file != NULL)
	fp->_close (ptr, fp->_cookie);
    }

  /*
   * Now get a new descriptor to refer to the new file, or reuse the
   * existing file descriptor if file is NULL.
   */

  if (file != NULL)
    {
      f = _open64_r (ptr, (char *) file, oflags, 0666);
      e = __errno_r(ptr);
    }
  else
    {
#ifdef HAVE_FCNTL
      int oldflags;
      /*
       * Reuse the file descriptor, but only if the new access mode is
       * equal or less permissive than the old.  F_SETFL correctly
       * ignores creation flags.
       */
      f = fp->_file;
      if ((oldflags = _fcntl_r (ptr, f, F_GETFL, 0)) == -1
	  || ! ((oldflags & O_ACCMODE) == O_RDWR
		|| ((oldflags ^ oflags) & O_ACCMODE) == 0)
	  || _fcntl_r (ptr, f, F_SETFL, oflags) == -1)
	f = -1;
#else
      /* We cannot modify without fcntl support.  */
      f = -1;
#endif

#ifdef __SCLE
      /*
       * F_SETFL doesn't change textmode.  Don't mess with modes of ttys.
       */
      if (0 <= f && ! isatty (f)
	  && setmode (f, oflags & (O_BINARY | O_TEXT)) == -1)
	f = -1;
#endif

      if (f < 0)
	{
	  e = EBADF;
	  if (fp->_close != NULL)
	    fp->_close (ptr, fp->_cookie);
	}
    }

  /*
   * 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 (fp->_flags & __SMBF)
    _free_r (ptr, (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 (ptr, fp);
  fp->_ub._size = 0;
  if (HASLB (fp))
    FREELB (ptr, fp);
  fp->_lb._size = 0;
  fp->_flags &= ~__SORD;
  fp->_flags2 &= ~__SWID;
  memset (&fp->_mbstate, 0, sizeof (_mbstate_t));

  if (f < 0)
    {				/* did not get it after all */
      __sfp_lock_acquire ();
      fp->_flags = 0;		/* set it free */
      __errno_r(ptr) = e;		/* restore in case _close clobbered */
      if (!(oflags2 & __SNLK))
	_funlockfile (fp);
#ifndef __SINGLE_THREAD__
      __lock_close_recursive (fp->_lock);
#endif
      __sfp_lock_release ();
#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS)
      pthread_setcancelstate (__oldcancel, &__oldcancel);
#endif
      return NULL;
    }

  fp->_flags = flags;
  fp->_file = f;
  fp->_cookie = (void *) fp;
  fp->_read = __sread;
  fp->_write = __swrite64;
  fp->_seek = __sseek;
  fp->_seek64 = __sseek64;
  fp->_close = __sclose;

#ifdef __SCLE
  if (__stextmode(fp->_file))
    fp->_flags |= __SCLE;
#endif

  fp->_flags |= __SL64;

  if (!(oflags2 & __SNLK))
    _funlockfile (fp);
#if !defined (__SINGLE_THREAD__) && defined (_POSIX_THREADS)
  pthread_setcancelstate (__oldcancel, &__oldcancel);
#endif
  return fp;
}
예제 #17
0
int
__srefill (register FILE * fp)
{
  /* make sure stdio is set up */

  CHECK_INIT (fp);

  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)
	return EOF;
      /* switch to reading */
      if (fp->_flags & __SWR)
	{
	  if (fflush (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))
    (void) _fwalk (fp->_data, lflush);
  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;
}
예제 #18
0
파일: fseek.c 프로젝트: Ninals-GitHub/TRON
/*
 * 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);
}
예제 #19
0
/*
 * 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);
}