/** A reentrant version of wfopen(). */ EXPORT_C FILE * _wfopen_r(struct _reent *ptr, const wchar_t *file, const wchar_t *mode) { register FILE *fp; register int f; int flags, oflags; if ((flags = __sflags (ptr, mode, &oflags)) == 0) return NULL; if ((fp = __sfp (ptr)) == NULL) return NULL; if ((f = _wopen_r (fp->_data, file, oflags, 0666)) < 0) { fp->_flags = 0; /* release */ return NULL; } fp->_file = (short)f; fp->_flags = (short)flags; fp->_cookie = (void*) fp; fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; if (fp->_flags & __SAPP) fseek (fp, 0, SEEK_END); return fp; }
FILE * fopen(const char *file, const char *mode) { FILE *fp; int f; int flags, oflags; if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); if ((fp = __sfp()) == NULL) return (NULL); if ((f = open(file, oflags, DEFFILEMODE)) < 0) { fp->_flags = 0; /* release */ return (NULL); } fp->_file = f; fp->_flags = flags; 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); }
FILE * fdopen(int fd, const char *mode) { FILE *fp; int flags, oflags, fdflags, tmp; /* * File descriptors are a full int, but _file is only a short. * If we get a valid file descriptor that is greater than * SHRT_MAX, then the fd will get sign-extended into an * invalid file descriptor. Handle this case by failing the * open. */ if (fd > SHRT_MAX) { errno = EMFILE; return (NULL); } if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); /* Make sure the mode the user wants is a subset of the actual mode. */ if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0) return (NULL); /* Work around incorrect O_ACCMODE. */ tmp = fdflags & (O_ACCMODE | O_EXEC); if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { errno = EINVAL; return (NULL); } if ((fp = __sfp()) == NULL) return (NULL); if ((oflags & O_CLOEXEC) && _fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { fp->_flags = 0; return (NULL); } fp->_flags = flags; /* * If opened for appending, but underlying descriptor does not have * O_APPEND bit set, assert __SAPP so that __swrite() caller * will _sseek() to the end before write. */ /* XXX: Reuse __SALC for O_APPEND. */ if (fdflags & O_APPEND) fp->_flags |= __SALC; else if (oflags & O_APPEND) fp->_flags |= __SAPP; fp->_file = fd; fp->_cookie = fp; fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; return (fp); }
FILE * fopen(const char *file, const char *mode) { FILE *fp; int f; int flags, oflags; _DIAGASSERT(file != NULL); if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); if ((fp = __sfp()) == NULL) return (NULL); if ((f = open(file, oflags, DEFFILEMODE)) < 0) goto release; if (oflags & O_NONBLOCK) { struct stat st; if (fstat(f, &st) == -1) { int sverrno = errno; (void)close(f); errno = sverrno; goto release; } if (!S_ISREG(st.st_mode)) { (void)close(f); errno = EFTYPE; goto release; } } fp->_file = (short)f; fp->_flags = (unsigned short)flags; 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); release: fp->_flags = 0; /* release */ return (NULL); }
FILE *_fdopen_r(struct _reent *ptr, int fd, const char *mode) { register FILE *fp; int flags, oflags; #ifdef F_GETFL int fdflags, fdmode; #endif if ((flags = __sflags(ptr, mode, &oflags)) == 0) return 0; /* make sure the mode the user wants is a subset of the actual mode */ #ifdef F_GETFL if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0) return 0; fdmode = fdflags & O_ACCMODE; if (fdmode != O_RDWR && (fdmode != (oflags & O_ACCMODE))) { ptr->_errno = EBADF; return 0; } #endif if ((fp = __sfp(ptr)) == 0) return 0; fp->_flags = flags; /* * If opened for appending, but underlying descriptor * does not have O_APPEND bit set, assert __SAPP so that * __swrite() will lseek to end before each write. */ if ((oflags & O_APPEND) #ifdef F_GETFL && !(fdflags & O_APPEND) #endif ) fp->_flags |= __SAPP; fp->_file = fd; fp->_cookie = (void *)fp; #undef _read #undef _write #undef _seek #undef _close fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; return fp; }
FILE * fdopen(int fd, const char *mode) { FILE *fp; int flags, oflags, fdflags, tmp; /* _file is only a short */ if (fd > SHRT_MAX) { errno = EMFILE; return (NULL); } if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); /* Make sure the mode the user wants is a subset of the actual mode. */ if ((fdflags = fcntl(fd, F_GETFL)) < 0) return (NULL); tmp = fdflags & O_ACCMODE; if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { errno = EINVAL; return (NULL); } if ((fp = __sfp()) == NULL) return (NULL); fp->_flags = flags; /* * If opened for appending, but underlying descriptor does not have * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to * end before each write. */ if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) fp->_flags |= __SAPP; /* * If close-on-exec was requested, then turn it on if not already */ if ((oflags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC)) fcntl(fd, F_SETFD, tmp | FD_CLOEXEC); fp->_file = fd; fp->_cookie = fp; fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; return (fp); }
FILE* fmemopen(void* buf, size_t capacity, const char* mode) { int flags; if (__sflags(mode, &flags) == 0) { errno = EINVAL; return nullptr; } fmemopen_cookie* ck = static_cast<fmemopen_cookie*>(calloc(sizeof(fmemopen_cookie), 1)); if (ck == nullptr) return nullptr; ck->buf = static_cast<char*>(buf); ck->capacity = capacity; if (ck->buf == nullptr) ck->buf = ck->allocation = static_cast<char*>(calloc(capacity, 1)); if (ck->buf == nullptr) { free(ck); return nullptr; } FILE* fp = funopen(ck, (flags & O_WRONLY) ? nullptr : fmemopen_read, (flags & O_RDONLY) ? nullptr : fmemopen_write, fmemopen_seek, fmemopen_close); if (fp == nullptr) { fmemopen_close(ck); return nullptr; } if (mode[0] == 'a') { ck->size = strnlen(ck->buf, ck->capacity); ck->offset = ck->size; ck->append = true; } else if (mode[0] == 'r') { ck->size = capacity; ck->offset = 0; } else if (mode[0] == 'w') { ck->size = 0; ck->offset = 0; if (capacity > 0) { ck->buf[0] = '\0'; } } return fp; }
FILE * fdopen(int fd, const char *mode) { register FILE *fp; static int nofile; int flags, oflags, fdflags, tmp; if (nofile == 0) nofile = getdtablesize(); if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); /* Make sure the mode the user wants is a subset of the actual mode. */ #ifdef __ORCAC__ /* ORCA/C: Provide only required args to variadic functions */ if ((fdflags = fcntl(fd, F_GETFL)) < 0) #else if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0) #endif return (NULL); tmp = fdflags & O_ACCMODE; if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { errno = EINVAL; return (NULL); } if ((fp = __sfp()) == NULL) return (NULL); fp->_flags = flags; /* * If opened for appending, but underlying descriptor does not have * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to * end before each write. */ if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) fp->_flags |= __SAPP; fp->_file = fd; fp->_cookie = fp; fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; return (fp); }
FILE* fdopen( int fd, const char *mode ) { FILE *fp; int flags, oflags; /* Check file descriptor */ if (iosFdValue(fd) == (ARG) 0) { fp = NULL; } else { /* Get flags */ flags = __sflags(mode, &oflags); if (flags == 0) { fp = NULL; } else { /* Create stream object */ fp = stdioFpCreate(); if (fp != NULL) { /* Setup FILE struct */ fp->_flags = flags; if (oflags & O_APPEND) { fp->_flags |= __SAPP; } fp->_file = fd; } } } return fp; }
FILE * fopencookie(void *cookie, const char *mode, cookie_io_functions_t functions) { FILE *fp; fccookie *c; int flags; int dummy; if ((flags = __sflags (mode, &dummy)) == 0) return NULL; if (((flags & (__SRD | __SRW)) && !functions.read) || ((flags & (__SWR | __SRW)) && !functions.write)) { return NULL; } if ((fp = (FILE *) __sfp ()) == NULL) return NULL; if ((c = (fccookie *) malloc (sizeof *c)) == NULL) { fp->_flags = 0; return NULL; } fp->_file = -1; fp->_flags = flags; c->cookie = cookie; c->fp = fp; fp->_cookie = c; c->readfn = functions.read; fp->_read = fcread; c->writefn = functions.write; fp->_write = fcwrite; c->seekfn = functions.seek; fp->_seek = functions.seek ? fcseek : NULL; c->closefn = functions.close; fp->_close = fcclose; return fp; }
FILE *fdopen(int fd, const char *mode) { register FILE *fp; int flags, oflags, fdflags, tmp; if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); /* Make sure the mode the user wants is a subset of the actual mode. */ if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0) return (NULL); tmp = fdflags & O_ACCMODE; if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { errno = EINVAL; return (NULL); } __sinit (); pthread_mutex_lock(&__sfp_mutex); while (__sfp_state) { pthread_cond_wait(&__sfp_cond, &__sfp_mutex); } if (fp = __sfp()) { fp->_flags = flags; /* * If opened for appending, but underlying descriptor does not have * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to * end before each write. */ if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) fp->_flags |= __SAPP; fp->_file = fd; } pthread_mutex_unlock(&__sfp_mutex); return (fp); }
FILE * fopencookie(void *cookie, const char *mode, cookie_io_functions_t io_funcs) { int (*readfn)(void *, char *, int); int (*writefn)(void *, const char *, int); struct fopencookie_thunk *thunk; FILE *fp; int flags, oflags; if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); thunk = malloc(sizeof(*thunk)); if (thunk == NULL) return (NULL); thunk->foc_cookie = cookie; thunk->foc_io = io_funcs; readfn = _fopencookie_read; writefn = _fopencookie_write; if (flags == __SWR) readfn = NULL; else if (flags == __SRD) writefn = NULL; fp = funopen(thunk, readfn, writefn, _fopencookie_seek, _fopencookie_close); if (fp == NULL) { free(thunk); return (NULL); } if ((oflags & O_APPEND) != 0) fp->_flags |= __SAPP; return (fp); }
FILE * fdopen(int fd, const char *mode) { FILE *fp; int flags, oflags, fdflags, tmp; if ((flags = __sflags(mode, &oflags)) == 0) return (NULL); /* Make sure the mode the user wants is a subset of the actual mode. */ if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0) return (NULL); tmp = fdflags & O_ACCMODE; if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) { errno = EINVAL; return (NULL); } if ((fp = __sfp()) == NULL) return (NULL); fp->pub._flags = flags; /* * If opened for appending, but underlying descriptor does not have * O_APPEND bit set, assert __SAPP so that __swrite() caller * will _sseek() to the end before write. */ if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) fp->pub._flags |= __SAPP; fp->pub._fileno = fd; fp->_cookie = fp; fp->_read = __sread; fp->_write = __swrite; fp->_seek = __sseek; fp->_close = __sclose; return (fp); }
FILE * fmemopen(void *buf, size_t size, const char *mode) { struct state *st; FILE *fp; int flags, oflags; if (size == 0) { errno = EINVAL; return (NULL); } if ((flags = __sflags(mode, &oflags)) == 0) { errno = EINVAL; return (NULL); } if (buf == NULL && ((oflags & O_RDWR) == 0)) { errno = EINVAL; return (NULL); } if ((st = malloc(sizeof(*st))) == NULL) return (NULL); if ((fp = __sfp()) == NULL) { free(st); return (NULL); } st->pos = 0; st->len = (oflags & O_WRONLY) ? 0 : size; st->size = size; st->update = oflags & O_RDWR; if (buf == NULL) { if ((st->string = malloc(size)) == NULL) { free(st); fp->_flags = 0; return (NULL); } *st->string = '\0'; } else { st->string = (char *)buf; if (oflags & O_TRUNC) *st->string = '\0'; if (oflags & O_APPEND) { char *p; if ((p = memchr(st->string, '\0', size)) != NULL) st->pos = st->len = (p - st->string); else st->pos = st->len = size; } } fp->_flags = (short)flags; fp->_file = -1; fp->_cookie = (void *)st; fp->_read = (flags & __SWR) ? NULL : fmemopen_read; fp->_write = (flags & __SRD) ? NULL : fmemopen_write; fp->_seek = fmemopen_seek; fp->_close = (buf == NULL) ? fmemopen_close_free : fmemopen_close; return (fp); }
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 * _fdopen64_r (struct _reent *ptr, int fd, const char *mode) { register FILE *fp; int flags, oflags; #ifdef HAVE_FCNTL int fdflags, fdmode; #endif if ((flags = __sflags (ptr, mode, &oflags)) == 0) return 0; /* make sure the mode the user wants is a subset of the actual mode */ #ifdef HAVE_FCNTL if ((fdflags = _fcntl_r (ptr, fd, F_GETFL, 0)) < 0) return 0; fdmode = fdflags & O_ACCMODE; if (fdmode != O_RDWR && (fdmode != (oflags & O_ACCMODE))) { ptr->_errno = EBADF; return 0; } #endif if ((fp = __sfp (ptr)) == 0) return 0; _newlib_flockfile_start(fp); fp->_flags = flags; /* POSIX recommends setting the O_APPEND bit on fd to match append streams. Someone may later clear O_APPEND on fileno(fp), but the stream must still remain in append mode. Rely on __sflags setting __SAPP properly. */ #ifdef HAVE_FCNTL if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) _fcntl_r (ptr, fd, F_SETFL, fdflags | O_APPEND); #endif fp->_file = fd; fp->_cookie = (void *) fp; #undef _read #undef _write #undef _seek #undef _close fp->_read = __sread; fp->_write = __swrite64; fp->_seek = __sseek; fp->_seek64 = __sseek64; fp->_close = __sclose; #ifdef __SCLE /* Explicit given mode results in explicit setting mode on fd */ if (oflags & O_BINARY) setmode(fp->_file, O_BINARY); else if (oflags & O_TEXT) setmode(fp->_file, O_TEXT); if (__stextmode(fp->_file)) fp->_flags |= __SCLE; #endif fp->_flags |= __SL64; _newlib_flockfile_end(fp); 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); }