sl@0: /* FREOPEN.C sl@0: * sl@0: * Portions Copyright (c) 1990-1999 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: */ sl@0: sl@0: /* sl@0: * Copyright (c) 1990 The Regents of the University of California. sl@0: * All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms are permitted sl@0: * provided that the above copyright notice and this paragraph are sl@0: * duplicated in all such forms and that any documentation, sl@0: * advertising materials, and other materials related to such sl@0: * distribution and use acknowledge that the software was developed sl@0: * by the University of California, Berkeley. The name of the sl@0: * University may not be used to endorse or promote products derived sl@0: * from this software without specific prior written permission. sl@0: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR sl@0: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED sl@0: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. sl@0: */ sl@0: sl@0: /* sl@0: FUNCTION sl@0: <>---open a file using an existing file descriptor sl@0: sl@0: INDEX sl@0: freopen sl@0: sl@0: ANSI_SYNOPSIS sl@0: #include sl@0: FILE *freopen(const char *<[file]>, const char *<[mode]>, sl@0: FILE *<[fp]>); sl@0: sl@0: TRAD_SYNOPSIS sl@0: #include sl@0: FILE *freopen(<[file]>, <[mode]>, <[fp]>) sl@0: char *<[file]>; sl@0: char *<[mode]>; sl@0: FILE *<[fp]>; sl@0: sl@0: DESCRIPTION sl@0: Use this variant of <> if you wish to specify a particular file sl@0: descriptor <[fp]> (notably <>, <>, or <>) for sl@0: the file. sl@0: sl@0: If <[fp]> was associated with another file or stream, <> sl@0: closes that other file or stream (but ignores any errors while closing sl@0: it). sl@0: sl@0: <[file]> and <[mode]> are used just as in <>. sl@0: sl@0: RETURNS sl@0: If successful, the result is the same as the argument <[fp]>. If the sl@0: file cannot be opened as specified, the result is <>. sl@0: sl@0: PORTABILITY sl@0: ANSI C requires <>. sl@0: sl@0: Supporting OS subroutines required: <>, <>, <>, sl@0: <>, <>, <>, <>, <>. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "LOCAL.H" sl@0: #include sl@0: sl@0: /* sl@0: * Re-direct an existing, open (probably) file to some other file. sl@0: */ sl@0: sl@0: #define MaxFullName 255 sl@0: sl@0: /** sl@0: Reopen a stream with a different file and mode. sl@0: @return If the file has been succesfully reopened the function returns a pointer to the file. sl@0: Otherwise a NULL pointer is returned. sl@0: @param file name of the file to be opened. sl@0: This paramenter must follow operating system's specifications and can include a path sl@0: if the system supports it. sl@0: @param mode type of access requested. sl@0: @param fp pointer to open file that has to be reopened. sl@0: */ sl@0: EXPORT_C FILE * freopen (const char *file, const char *mode, FILE *fp) sl@0: { sl@0: wchar_t _wfile[MaxFullName+1]; sl@0: wchar_t _wmode[MaxFullName+1]; sl@0: struct _reent *ptr; sl@0: sl@0: if ((-1 != mbstowcs(_wfile, file, MaxFullName)) && sl@0: (-1 != mbstowcs(_wmode, mode, MaxFullName))) sl@0: { sl@0: return wfreopen(_wfile, _wmode, fp); sl@0: } sl@0: sl@0: CHECK_INIT (fp); sl@0: ptr = fp->_data; sl@0: ptr->_errno = EILSEQ; sl@0: return NULL; sl@0: } sl@0: sl@0: EXPORT_C FILE * wfreopen (const wchar_t *file, const wchar_t *mode, FILE *fp) sl@0: { sl@0: register int f; sl@0: int isopen, flags, oflags, e; sl@0: struct _reent *ptr; sl@0: sl@0: CHECK_INIT (fp); sl@0: ptr = fp->_data; sl@0: sl@0: if ((flags = __sflags (ptr, mode, &oflags)) == 0) sl@0: { sl@0: (void) fclose (fp); sl@0: return NULL; sl@0: } sl@0: sl@0: /* sl@0: * Remember whether the stream was open to begin with, and sl@0: * which file descriptor (if any) was associated with it. sl@0: * If it was attached to a descriptor, defer closing it, sl@0: * so that, e.g., freopen("/dev/stdin", "r", stdin) works. sl@0: * This is unnecessary if it was not a Unix file. sl@0: */ sl@0: sl@0: if (fp->_flags == 0) sl@0: { sl@0: fp->_flags = __SEOF; /* hold on to it */ sl@0: isopen = 0; sl@0: } sl@0: else sl@0: { sl@0: if (fp->_flags & __SWR) sl@0: (void) fflush (fp); sl@0: /* if close is NULL, closing is a no-op, hence pointless */ sl@0: isopen = fp->_close != NULL; sl@0: if (fp->_file < 0 && isopen) sl@0: { sl@0: (void) (*fp->_close) (fp->_cookie); sl@0: isopen = 0; sl@0: } sl@0: } sl@0: sl@0: /* sl@0: * Now get a new descriptor to refer to the new file. sl@0: */ sl@0: sl@0: f = _wopen_r (ptr, (wchar_t *)file, oflags, 0666); sl@0: if (f < 0 && isopen) sl@0: { sl@0: /* sl@0: * May have used up all descriptors, so close the old sl@0: * and try again. sl@0: */ sl@0: (void) (*fp->_close) (fp->_cookie); sl@0: isopen = 0; sl@0: f = _wopen_r (ptr, (wchar_t *) file, oflags, 0666); sl@0: } sl@0: e = ptr->_errno; sl@0: sl@0: /* sl@0: * Finish closing fp. Even if the open succeeded above, sl@0: * we cannot keep fp->_base: it may be the wrong size. sl@0: * This loses the effect of any setbuffer calls, sl@0: * but stdio has always done this before. sl@0: */ sl@0: sl@0: if (isopen) sl@0: (void) (*fp->_close) (fp->_cookie); sl@0: if (fp->_flags & __SMBF) sl@0: _free_r (ptr, (char *) fp->_bf._base); sl@0: fp->_w = 0; sl@0: fp->_r = 0; sl@0: fp->_p = NULL; sl@0: fp->_bf._base = NULL; sl@0: fp->_bf._size = 0; sl@0: fp->_lbfsize = 0; sl@0: if (HASUB (fp)) sl@0: FREEUB (fp); sl@0: fp->_ub._size = 0; sl@0: if (HASLB (fp)) sl@0: FREELB (fp); sl@0: fp->_lb._size = 0; sl@0: sl@0: if (f < 0) sl@0: { /* did not get it after all */ sl@0: fp->_flags = 0; /* set it free */ sl@0: ptr->_errno = e; /* restore in case _close clobbered */ sl@0: return NULL; sl@0: } sl@0: sl@0: fp->_flags = (short)flags; sl@0: fp->_file = (short)f; sl@0: fp->_cookie = (void*) fp; sl@0: fp->_read = __sread; sl@0: fp->_write = __swrite; sl@0: fp->_seek = __sseek; sl@0: fp->_close = __sclose; sl@0: return fp; sl@0: }