os/ossrv/genericopenlibs/openenvcore/libc/src/wfreopen.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*-
sl@0
     2
 * Copyright (c) 1990, 1993
sl@0
     3
 *	The Regents of the University of California.  All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This code is derived from software contributed to Berkeley by
sl@0
     6
 * Chris Torek.
sl@0
     7
 *
sl@0
     8
 * Redistribution and use in source and binary forms, with or without
sl@0
     9
 * modification, are permitted provided that the following conditions
sl@0
    10
 * are met:
sl@0
    11
 * 1. Redistributions of source code must retain the above copyright
sl@0
    12
 *    notice, this list of conditions and the following disclaimer.
sl@0
    13
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    14
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    15
 *    documentation and/or other materials provided with the distribution.
sl@0
    16
 * 4. Neither the name of the University nor the names of its contributors
sl@0
    17
 *    may be used to endorse or promote products derived from this software
sl@0
    18
 *    without specific prior written permission.
sl@0
    19
 *
sl@0
    20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
sl@0
    21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
sl@0
    24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    30
 * SUCH DAMAGE.
sl@0
    31
 * © Portions copyright (c) 2005 - 2006 Nokia Corporation.  All rights reserved.
sl@0
    32
 */
sl@0
    33
sl@0
    34
#if defined(LIBC_SCCS) && !defined(lint)
sl@0
    35
static char sccsid[] = "@(#)freopen.c	8.1 (Berkeley) 6/4/93";
sl@0
    36
#endif /* LIBC_SCCS and not lint */
sl@0
    37
#include <sys/cdefs.h>
sl@0
    38
#ifndef __SYMBIAN32__
sl@0
    39
__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.13 2004/05/22 15:19:41 tjr Exp $");
sl@0
    40
#endif
sl@0
    41
#include "namespace.h"
sl@0
    42
#include <sys/types.h>
sl@0
    43
#include <sys/stat.h>
sl@0
    44
#include <wchar.h>
sl@0
    45
#ifndef DEFFILEMODE
sl@0
    46
#define	DEFFILEMODE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
sl@0
    47
#endif
sl@0
    48
#include <errno.h>
sl@0
    49
#include <stdio.h>
sl@0
    50
#include <stdlib.h>
sl@0
    51
#include "un-namespace.h"
sl@0
    52
#include <fcntl.h>
sl@0
    53
#include <unistd.h>
sl@0
    54
#include "libc_private.h"
sl@0
    55
#include "local.h"
sl@0
    56
#include "common_def.h"
sl@0
    57
#if (defined(__SYMBIAN32__) && (defined(__WINSCW__) || defined(__WINS__)))
sl@0
    58
#include "libc_wsd_defs.h"
sl@0
    59
#endif
sl@0
    60
sl@0
    61
#ifdef EMULATOR
sl@0
    62
int *GET_WSD_VAR_NAME(__sdidinit, g)();
sl@0
    63
#define __sdidinit (*GET_WSD_VAR_NAME(__sdidinit, g)())
sl@0
    64
#endif //EMULATOR
sl@0
    65
/*
sl@0
    66
  Re-direct an existing, open (probably) file to some other file.
sl@0
    67
  ANSI is written such that the original file gets closed if at
sl@0
    68
  all possible, no matter what.
sl@0
    69
 */
sl@0
    70
sl@0
    71
EXPORT_C FILE * wfreopen(const wchar_t *  file, const wchar_t *  mode,	FILE *fp)	
sl@0
    72
{
sl@0
    73
	int f;
sl@0
    74
	int dflags, flags, isopen, oflags, sverrno, wantfd;
sl@0
    75
	char destmode[4];
sl@0
    76
	size_t siz;
sl@0
    77
       
sl@0
    78
	destmode[0] = '\0';
sl@0
    79
    if(mode==NULL)
sl@0
    80
    {
sl@0
    81
    	errno = EINVAL;
sl@0
    82
	    (void) fclose(fp);
sl@0
    83
		return (NULL);
sl@0
    84
    }
sl@0
    85
	siz = wcstombs(destmode, mode, 4);	
sl@0
    86
	   
sl@0
    87
      
sl@0
    88
	if ((flags = __sflags(destmode, &oflags)) == 0) {
sl@0
    89
		(void) fclose(fp);
sl@0
    90
		return (NULL);
sl@0
    91
	}
sl@0
    92
sl@0
    93
	FLOCKFILE(fp);
sl@0
    94
sl@0
    95
	if (!__sdidinit)
sl@0
    96
		__sinit();
sl@0
    97
sl@0
    98
	/*
sl@0
    99
	 * If the filename is a NULL pointer, the caller is asking us to
sl@0
   100
	 * re-open the same file with a different mode. We allow this only
sl@0
   101
	 * if the modes are compatible.
sl@0
   102
	 */
sl@0
   103
	if (file == NULL) {
sl@0
   104
		/* See comment below regarding freopen() of closed files. */
sl@0
   105
		if (fp->_flags == 0) {
sl@0
   106
			FUNLOCKFILE(fp);
sl@0
   107
			errno = EINVAL;
sl@0
   108
			return (NULL);
sl@0
   109
		}
sl@0
   110
		if ((dflags = _fcntl(fp->_file, F_GETFL)) < 0) {
sl@0
   111
			sverrno = errno;
sl@0
   112
			fclose(fp);
sl@0
   113
			FUNLOCKFILE(fp);
sl@0
   114
			errno = sverrno;
sl@0
   115
			return (NULL);
sl@0
   116
		}
sl@0
   117
		if ((dflags & O_ACCMODE) != O_RDWR && (dflags & O_ACCMODE) !=
sl@0
   118
		    (oflags & O_ACCMODE)) {
sl@0
   119
			fclose(fp);
sl@0
   120
			FUNLOCKFILE(fp);
sl@0
   121
			errno = EINVAL;
sl@0
   122
			return (NULL);
sl@0
   123
		}
sl@0
   124
		if ((oflags ^ dflags) & O_APPEND) {
sl@0
   125
			dflags &= ~O_APPEND;
sl@0
   126
			dflags |= oflags & O_APPEND;
sl@0
   127
			if (_fcntl(fp->_file, F_SETFL, dflags) < 0) {
sl@0
   128
				sverrno = errno;
sl@0
   129
				fclose(fp);
sl@0
   130
				FUNLOCKFILE(fp);
sl@0
   131
				errno = sverrno;
sl@0
   132
				return (NULL);
sl@0
   133
			}
sl@0
   134
		}
sl@0
   135
		if (oflags & O_TRUNC)
sl@0
   136
			ftruncate(fp->_file, 0);
sl@0
   137
		if (_fseeko(fp, 0, oflags & O_APPEND ? SEEK_END : SEEK_SET,
sl@0
   138
		    0) < 0 && errno != ESPIPE) {
sl@0
   139
			sverrno = errno;
sl@0
   140
			fclose(fp);
sl@0
   141
			FUNLOCKFILE(fp);
sl@0
   142
			errno = sverrno;
sl@0
   143
			return (NULL);
sl@0
   144
		}
sl@0
   145
		f = fp->_file;
sl@0
   146
		isopen = 0;
sl@0
   147
		wantfd = -1;
sl@0
   148
		
sl@0
   149
	}
sl@0
   150
	else
sl@0
   151
	{
sl@0
   152
	/*
sl@0
   153
	 * There are actually programs that depend on being able to "freopen"
sl@0
   154
	 * descriptors that weren't originally open.  Keep this from breaking.
sl@0
   155
	 * Remember whether the stream was open to begin with, and which file
sl@0
   156
	 * descriptor (if any) was associated with it.  If it was attached to
sl@0
   157
	 * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
sl@0
   158
	 * should work.  This is unnecessary if it was not a Unix file.
sl@0
   159
	 */
sl@0
   160
		if (fp->_flags == 0) {
sl@0
   161
		fp->_flags = __SEOF;	/* hold on to it */
sl@0
   162
		isopen = 0;
sl@0
   163
		wantfd = -1;
sl@0
   164
		} 
sl@0
   165
		else {
sl@0
   166
		/* flush the stream; ANSI doesn't require this. */
sl@0
   167
		if (fp->_flags & __SWR)
sl@0
   168
			(void) __sflush(fp);
sl@0
   169
		/* if close is NULL, closing is a no-op, hence pointless */
sl@0
   170
		isopen = fp->_close != NULL;
sl@0
   171
		if ((wantfd = fp->_file) < 0 && isopen) {
sl@0
   172
			(void) (*fp->_close)(fp->_cookie);
sl@0
   173
			isopen = 0;
sl@0
   174
			}
sl@0
   175
		}
sl@0
   176
	/* Get a new descriptor to refer to the new file. */
sl@0
   177
		f = wopen(file, oflags, DEFFILEMODE);
sl@0
   178
		if (f < 0 && isopen) {
sl@0
   179
		/* If out of fd's close the old one and try again. */
sl@0
   180
		if (errno == ENFILE || errno == EMFILE) {
sl@0
   181
			(void) (*fp->_close)(fp->_cookie);
sl@0
   182
			isopen = 0;
sl@0
   183
			f = wopen(file, oflags, DEFFILEMODE);        
sl@0
   184
			}
sl@0
   185
		}
sl@0
   186
		sverrno = errno;
sl@0
   187
	}
sl@0
   188
sl@0
   189
	/*
sl@0
   190
	 * Finish closing fp.  Even if the open succeeded above, we cannot
sl@0
   191
	 * keep fp->_base: it may be the wrong size.  This loses the effect
sl@0
   192
	 * of any setbuffer calls, but stdio has always done this before.
sl@0
   193
	 */
sl@0
   194
	if (isopen)                                      
sl@0
   195
		(void) (*fp->_close)(fp->_cookie);
sl@0
   196
	if (fp->_flags & __SMBF)
sl@0
   197
		{
sl@0
   198
#ifdef __SYMBIAN32__
sl@0
   199
		BackendFree((char *)fp->_bf._base);
sl@0
   200
#else
sl@0
   201
		free((char *)fp->_bf._base);
sl@0
   202
#endif//__SYMBIAN32__
sl@0
   203
		}
sl@0
   204
		
sl@0
   205
	fp->_w = 0;
sl@0
   206
	fp->_r = 0;
sl@0
   207
	fp->_p = NULL;
sl@0
   208
	fp->_bf._base = NULL;
sl@0
   209
	fp->_bf._size = 0;
sl@0
   210
	fp->_lbfsize = 0;
sl@0
   211
	if (HASUB(fp))
sl@0
   212
		FREEUB(fp);
sl@0
   213
	fp->_ub._size = 0;
sl@0
   214
	if (HASLB(fp))
sl@0
   215
		FREELB(fp);
sl@0
   216
	fp->_lb._size = 0;
sl@0
   217
	fp->_extra->orientation = 0;
sl@0
   218
	memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
sl@0
   219
sl@0
   220
	if (f < 0) {			/* did not get it after all */
sl@0
   221
		fp->_flags = 0;		/* set it free */
sl@0
   222
		errno = sverrno;	/* restore in case _close clobbered */
sl@0
   223
		FUNLOCKFILE(fp);
sl@0
   224
		return (NULL);
sl@0
   225
	}
sl@0
   226
#ifndef __SYMBIAN32__	
sl@0
   227
	/*
sl@0
   228
	 * If reopening something that was open before on a real file, try
sl@0
   229
	 * to maintain the descriptor.  Various C library routines (perror)
sl@0
   230
	 * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
sl@0
   231
	 */
sl@0
   232
	if (wantfd >= 0 && f != wantfd) {
sl@0
   233
		if (dup2(f, wantfd) >= 0) {
sl@0
   234
			(void)_close(f);
sl@0
   235
			f = wantfd;
sl@0
   236
		}
sl@0
   237
	}
sl@0
   238
#else
sl@0
   239
		if (wantfd >= 0 && f > wantfd){
sl@0
   240
			if (dup2(f, wantfd) >= 0) {
sl@0
   241
				(void)_close(f);
sl@0
   242
				f = wantfd;		
sl@0
   243
		}
sl@0
   244
	}
sl@0
   245
#endif	
sl@0
   246
sl@0
   247
	fp->_flags = flags;
sl@0
   248
	fp->_file = f;
sl@0
   249
	fp->_cookie = fp;
sl@0
   250
	fp->_read = __sread;
sl@0
   251
	fp->_write = __swrite;
sl@0
   252
	fp->_seek = __sseek;
sl@0
   253
	fp->_close = __sclose;
sl@0
   254
#ifdef __SYMBIAN32__    
sl@0
   255
    if (oflags & O_TEXT) {
sl@0
   256
        fp->_extra->fmode = 't';
sl@0
   257
    }
sl@0
   258
    else {
sl@0
   259
        fp->_extra->fmode = 'b';
sl@0
   260
    }
sl@0
   261
#endif
sl@0
   262
	FUNLOCKFILE(fp);
sl@0
   263
	return (fp);
sl@0
   264
}