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); }
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); }
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; }
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; }
/* * 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); }
/* * 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); }