1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/openenvcore/libc/src/wfreopen.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,264 @@
1.4 +/*-
1.5 + * Copyright (c) 1990, 1993
1.6 + * The Regents of the University of California. All rights reserved.
1.7 + *
1.8 + * This code is derived from software contributed to Berkeley by
1.9 + * Chris Torek.
1.10 + *
1.11 + * Redistribution and use in source and binary forms, with or without
1.12 + * modification, are permitted provided that the following conditions
1.13 + * are met:
1.14 + * 1. Redistributions of source code must retain the above copyright
1.15 + * notice, this list of conditions and the following disclaimer.
1.16 + * 2. Redistributions in binary form must reproduce the above copyright
1.17 + * notice, this list of conditions and the following disclaimer in the
1.18 + * documentation and/or other materials provided with the distribution.
1.19 + * 4. Neither the name of the University nor the names of its contributors
1.20 + * may be used to endorse or promote products derived from this software
1.21 + * without specific prior written permission.
1.22 + *
1.23 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1.24 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.25 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.26 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1.27 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.28 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.29 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.30 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.31 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.32 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.33 + * SUCH DAMAGE.
1.34 + * © Portions copyright (c) 2005 - 2006 Nokia Corporation. All rights reserved.
1.35 + */
1.36 +
1.37 +#if defined(LIBC_SCCS) && !defined(lint)
1.38 +static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93";
1.39 +#endif /* LIBC_SCCS and not lint */
1.40 +#include <sys/cdefs.h>
1.41 +#ifndef __SYMBIAN32__
1.42 +__FBSDID("$FreeBSD: src/lib/libc/stdio/freopen.c,v 1.13 2004/05/22 15:19:41 tjr Exp $");
1.43 +#endif
1.44 +#include "namespace.h"
1.45 +#include <sys/types.h>
1.46 +#include <sys/stat.h>
1.47 +#include <wchar.h>
1.48 +#ifndef DEFFILEMODE
1.49 +#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
1.50 +#endif
1.51 +#include <errno.h>
1.52 +#include <stdio.h>
1.53 +#include <stdlib.h>
1.54 +#include "un-namespace.h"
1.55 +#include <fcntl.h>
1.56 +#include <unistd.h>
1.57 +#include "libc_private.h"
1.58 +#include "local.h"
1.59 +#include "common_def.h"
1.60 +#if (defined(__SYMBIAN32__) && (defined(__WINSCW__) || defined(__WINS__)))
1.61 +#include "libc_wsd_defs.h"
1.62 +#endif
1.63 +
1.64 +#ifdef EMULATOR
1.65 +int *GET_WSD_VAR_NAME(__sdidinit, g)();
1.66 +#define __sdidinit (*GET_WSD_VAR_NAME(__sdidinit, g)())
1.67 +#endif //EMULATOR
1.68 +/*
1.69 + Re-direct an existing, open (probably) file to some other file.
1.70 + ANSI is written such that the original file gets closed if at
1.71 + all possible, no matter what.
1.72 + */
1.73 +
1.74 +EXPORT_C FILE * wfreopen(const wchar_t * file, const wchar_t * mode, FILE *fp)
1.75 +{
1.76 + int f;
1.77 + int dflags, flags, isopen, oflags, sverrno, wantfd;
1.78 + char destmode[4];
1.79 + size_t siz;
1.80 +
1.81 + destmode[0] = '\0';
1.82 + if(mode==NULL)
1.83 + {
1.84 + errno = EINVAL;
1.85 + (void) fclose(fp);
1.86 + return (NULL);
1.87 + }
1.88 + siz = wcstombs(destmode, mode, 4);
1.89 +
1.90 +
1.91 + if ((flags = __sflags(destmode, &oflags)) == 0) {
1.92 + (void) fclose(fp);
1.93 + return (NULL);
1.94 + }
1.95 +
1.96 + FLOCKFILE(fp);
1.97 +
1.98 + if (!__sdidinit)
1.99 + __sinit();
1.100 +
1.101 + /*
1.102 + * If the filename is a NULL pointer, the caller is asking us to
1.103 + * re-open the same file with a different mode. We allow this only
1.104 + * if the modes are compatible.
1.105 + */
1.106 + if (file == NULL) {
1.107 + /* See comment below regarding freopen() of closed files. */
1.108 + if (fp->_flags == 0) {
1.109 + FUNLOCKFILE(fp);
1.110 + errno = EINVAL;
1.111 + return (NULL);
1.112 + }
1.113 + if ((dflags = _fcntl(fp->_file, F_GETFL)) < 0) {
1.114 + sverrno = errno;
1.115 + fclose(fp);
1.116 + FUNLOCKFILE(fp);
1.117 + errno = sverrno;
1.118 + return (NULL);
1.119 + }
1.120 + if ((dflags & O_ACCMODE) != O_RDWR && (dflags & O_ACCMODE) !=
1.121 + (oflags & O_ACCMODE)) {
1.122 + fclose(fp);
1.123 + FUNLOCKFILE(fp);
1.124 + errno = EINVAL;
1.125 + return (NULL);
1.126 + }
1.127 + if ((oflags ^ dflags) & O_APPEND) {
1.128 + dflags &= ~O_APPEND;
1.129 + dflags |= oflags & O_APPEND;
1.130 + if (_fcntl(fp->_file, F_SETFL, dflags) < 0) {
1.131 + sverrno = errno;
1.132 + fclose(fp);
1.133 + FUNLOCKFILE(fp);
1.134 + errno = sverrno;
1.135 + return (NULL);
1.136 + }
1.137 + }
1.138 + if (oflags & O_TRUNC)
1.139 + ftruncate(fp->_file, 0);
1.140 + if (_fseeko(fp, 0, oflags & O_APPEND ? SEEK_END : SEEK_SET,
1.141 + 0) < 0 && errno != ESPIPE) {
1.142 + sverrno = errno;
1.143 + fclose(fp);
1.144 + FUNLOCKFILE(fp);
1.145 + errno = sverrno;
1.146 + return (NULL);
1.147 + }
1.148 + f = fp->_file;
1.149 + isopen = 0;
1.150 + wantfd = -1;
1.151 +
1.152 + }
1.153 + else
1.154 + {
1.155 + /*
1.156 + * There are actually programs that depend on being able to "freopen"
1.157 + * descriptors that weren't originally open. Keep this from breaking.
1.158 + * Remember whether the stream was open to begin with, and which file
1.159 + * descriptor (if any) was associated with it. If it was attached to
1.160 + * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
1.161 + * should work. This is unnecessary if it was not a Unix file.
1.162 + */
1.163 + if (fp->_flags == 0) {
1.164 + fp->_flags = __SEOF; /* hold on to it */
1.165 + isopen = 0;
1.166 + wantfd = -1;
1.167 + }
1.168 + else {
1.169 + /* flush the stream; ANSI doesn't require this. */
1.170 + if (fp->_flags & __SWR)
1.171 + (void) __sflush(fp);
1.172 + /* if close is NULL, closing is a no-op, hence pointless */
1.173 + isopen = fp->_close != NULL;
1.174 + if ((wantfd = fp->_file) < 0 && isopen) {
1.175 + (void) (*fp->_close)(fp->_cookie);
1.176 + isopen = 0;
1.177 + }
1.178 + }
1.179 + /* Get a new descriptor to refer to the new file. */
1.180 + f = wopen(file, oflags, DEFFILEMODE);
1.181 + if (f < 0 && isopen) {
1.182 + /* If out of fd's close the old one and try again. */
1.183 + if (errno == ENFILE || errno == EMFILE) {
1.184 + (void) (*fp->_close)(fp->_cookie);
1.185 + isopen = 0;
1.186 + f = wopen(file, oflags, DEFFILEMODE);
1.187 + }
1.188 + }
1.189 + sverrno = errno;
1.190 + }
1.191 +
1.192 + /*
1.193 + * Finish closing fp. Even if the open succeeded above, we cannot
1.194 + * keep fp->_base: it may be the wrong size. This loses the effect
1.195 + * of any setbuffer calls, but stdio has always done this before.
1.196 + */
1.197 + if (isopen)
1.198 + (void) (*fp->_close)(fp->_cookie);
1.199 + if (fp->_flags & __SMBF)
1.200 + {
1.201 +#ifdef __SYMBIAN32__
1.202 + BackendFree((char *)fp->_bf._base);
1.203 +#else
1.204 + free((char *)fp->_bf._base);
1.205 +#endif//__SYMBIAN32__
1.206 + }
1.207 +
1.208 + fp->_w = 0;
1.209 + fp->_r = 0;
1.210 + fp->_p = NULL;
1.211 + fp->_bf._base = NULL;
1.212 + fp->_bf._size = 0;
1.213 + fp->_lbfsize = 0;
1.214 + if (HASUB(fp))
1.215 + FREEUB(fp);
1.216 + fp->_ub._size = 0;
1.217 + if (HASLB(fp))
1.218 + FREELB(fp);
1.219 + fp->_lb._size = 0;
1.220 + fp->_extra->orientation = 0;
1.221 + memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t));
1.222 +
1.223 + if (f < 0) { /* did not get it after all */
1.224 + fp->_flags = 0; /* set it free */
1.225 + errno = sverrno; /* restore in case _close clobbered */
1.226 + FUNLOCKFILE(fp);
1.227 + return (NULL);
1.228 + }
1.229 +#ifndef __SYMBIAN32__
1.230 + /*
1.231 + * If reopening something that was open before on a real file, try
1.232 + * to maintain the descriptor. Various C library routines (perror)
1.233 + * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
1.234 + */
1.235 + if (wantfd >= 0 && f != wantfd) {
1.236 + if (dup2(f, wantfd) >= 0) {
1.237 + (void)_close(f);
1.238 + f = wantfd;
1.239 + }
1.240 + }
1.241 +#else
1.242 + if (wantfd >= 0 && f > wantfd){
1.243 + if (dup2(f, wantfd) >= 0) {
1.244 + (void)_close(f);
1.245 + f = wantfd;
1.246 + }
1.247 + }
1.248 +#endif
1.249 +
1.250 + fp->_flags = flags;
1.251 + fp->_file = f;
1.252 + fp->_cookie = fp;
1.253 + fp->_read = __sread;
1.254 + fp->_write = __swrite;
1.255 + fp->_seek = __sseek;
1.256 + fp->_close = __sclose;
1.257 +#ifdef __SYMBIAN32__
1.258 + if (oflags & O_TEXT) {
1.259 + fp->_extra->fmode = 't';
1.260 + }
1.261 + else {
1.262 + fp->_extra->fmode = 'b';
1.263 + }
1.264 +#endif
1.265 + FUNLOCKFILE(fp);
1.266 + return (fp);
1.267 +}