コード例 #1
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;
}
コード例 #2
0
EXPORT_C
void funlockfile(FILE *fp)
{
	_funlockfile(fp);
}