예제 #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
/*
 * 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);
}
예제 #3
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;
}
예제 #4
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);
}
예제 #5
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);
}
예제 #6
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)
{
  fpos_t (*seekfn)(void *, fpos_t, int);
  fpos_t target, curoff;
  size_t n;
  struct stat st;
  int havepos;

  _DIAGASSERT(fp != NULL);
  if(fp == NULL) {
    errno = EINVAL;
    return -1;
  }

#ifdef __GNUC__
  /* This outrageous construct just to shut up a GCC warning. */
  (void) &curoff;
#endif

  /* make sure stdio is set up */
  if (!__sdidinit)
    __sinit();

//Print(L"%a( %d, %Ld, %d)\n", __func__, fp->_file, offset, whence);
  FLOCKFILE(fp);

  /*
   * Have to be able to seek.
   */
  if ((seekfn = fp->_seek) == NULL) {
    errno = ESPIPE;     /* historic practice */
    FUNLOCKFILE(fp);
//Print(L"%a: %d\n", __func__, __LINE__);
    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 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 == POS_ERR) {
        FUNLOCKFILE(fp);
//Print(L"%a: %d\n", __func__, __LINE__);
        return (-1);
      }
    }
    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;
    FUNLOCKFILE(fp);
//Print(L"%a: %d\n", __func__, __LINE__);
    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->_flags & (__SWR | __SRW | __SNBF | __SNPT))
    goto dumb;
  if ((fp->_flags & __SOPT) == 0) {
    if (seekfn != __sseek ||
        fp->_file < 0 || fstat(fp->_file, &st) ||
        !S_ISREG(st.st_mode)) {
      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 (fstat(fp->_file, &st))
    {
//Print(L"%a: %d\n", __func__, __LINE__);
      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)
      {
//Print(L"%a: %d\n", __func__, __LINE__);
        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 < (fpos_t)(curoff + n)) {
    int o = (int)(target - curoff);

    fp->_p = fp->_bf._base + o;
    fp->_r = (int)(n - o);
    if (HASUB(fp))
      FREEUB(fp);
    WCIO_FREE(fp);    /* Should this really be unconditional??? */
    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)
  {
//Print(L"%a: %d\n", __func__, __LINE__);
    goto dumb;
  }
  fp->_r = 0;
  fp->_p = fp->_bf._base;
  if (HASUB(fp))
    FREEUB(fp);
  WCIO_FREE(fp);    /* Should this really be unconditional??? */
  fp->_flags &= ~__SEOF;
  n = (int)(target - curoff);
  if (n) {
    if (__srefill(fp) || fp->_r < (int)n)
    {
//Print(L"%a: %d\n", __func__, __LINE__);
      goto dumb;
    }
    fp->_p += n;
    fp->_r -= (int)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:
//Print(L"%a: %d\n", __func__, __LINE__);
  if (__sflush(fp) ||
      (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) {
    FUNLOCKFILE(fp);
//Print(L"%a: %d\n", __func__, __LINE__);
    return (-1);
  }
  /* success: clear EOF indicator and discard ungetc() data */
  if (HASUB(fp))
    FREEUB(fp);
  WCIO_FREE(fp);    /* Should this really be unconditional??? */
  fp->_p = fp->_bf._base;
  fp->_r = 0;
  fp->_w = 0;
  fp->_flags &= ~__SEOF;
  FUNLOCKFILE(fp);
//Print(L"%a: %d\n", __func__, __LINE__);
  return (0);
}