360 lines
10 KiB
C
360 lines
10 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* Open Watcom Project
|
||
|
*
|
||
|
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||
|
*
|
||
|
* ========================================================================
|
||
|
*
|
||
|
* This file contains Original Code and/or Modifications of Original
|
||
|
* Code as defined in and that are subject to the Sybase Open Watcom
|
||
|
* Public License version 1.0 (the 'License'). You may not use this file
|
||
|
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||
|
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||
|
* provided with the Original Code and Modifications, and is also
|
||
|
* available at www.sybase.com/developer/opensource.
|
||
|
*
|
||
|
* The Original Code and all software distributed under the License are
|
||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||
|
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||
|
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||
|
* NON-INFRINGEMENT. Please see the License for the specific language
|
||
|
* governing rights and limitations under the License.
|
||
|
*
|
||
|
* ========================================================================
|
||
|
*
|
||
|
* Description: Platform independent fopen() implementation.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
|
||
|
#include "variety.h"
|
||
|
#include "widechar.h"
|
||
|
#include <stdio.h>
|
||
|
#include <ctype.h>
|
||
|
#ifdef __WIDECHAR__
|
||
|
#include <wctype.h>
|
||
|
#endif
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include "fileacc.h"
|
||
|
#include "fmode.h"
|
||
|
#include "openmode.h"
|
||
|
#include "rtdata.h"
|
||
|
#include "seterrno.h"
|
||
|
//#include "defwin.h"
|
||
|
#include "streamio.h"
|
||
|
|
||
|
#ifdef __UNIX__
|
||
|
#define PMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||
|
#else
|
||
|
#define PMODE (S_IREAD | S_IWRITE)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
int __F_NAME(__open_flags,__wopen_flags)( const CHAR_TYPE *modestr, int *extflags )
|
||
|
{
|
||
|
int flags;
|
||
|
int alive = 1;
|
||
|
int gotplus = 0;
|
||
|
int gottextbin = 0;
|
||
|
#ifndef __NETWARE__
|
||
|
int gotcommit = 0;
|
||
|
#endif
|
||
|
|
||
|
flags = 0;
|
||
|
if( extflags != NULL ) {
|
||
|
#ifdef __NETWARE__
|
||
|
*extflags = 0;
|
||
|
#else
|
||
|
if( _commode == _COMMIT ) {
|
||
|
*extflags = _COMMIT;
|
||
|
} else {
|
||
|
*extflags = 0;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* The first character in modestr must be 'r', 'w', or 'a'.
|
||
|
*/
|
||
|
switch( *modestr ) {
|
||
|
case 'r':
|
||
|
flags |= _READ;
|
||
|
break;
|
||
|
case 'w':
|
||
|
flags |= _WRITE;
|
||
|
break;
|
||
|
case 'a':
|
||
|
flags |= _WRITE | _APPEND;
|
||
|
break;
|
||
|
default:
|
||
|
__set_errno( EINVAL );
|
||
|
return( 0 );
|
||
|
}
|
||
|
modestr++;
|
||
|
|
||
|
/*
|
||
|
* Next we might have, in any order, some additional mode modifier
|
||
|
* characters:
|
||
|
* 1. A '+' character.
|
||
|
* 2. Either a 't' or a 'b'.
|
||
|
* 3. Either a 'c' or a 'n'. (Not available for Netware.)
|
||
|
* For MS compatability, scanning stops when any of the three groups
|
||
|
* is encountered twice; e.g., "wct+b$&!" is valid and will result in
|
||
|
* a text, not binary, stream. Also for MS compatability, scanning
|
||
|
* stops at any unrecognized character, without causing failure.
|
||
|
*/
|
||
|
while( (*modestr != NULLCHAR) && alive ) {
|
||
|
switch( *modestr ) {
|
||
|
case '+':
|
||
|
if( gotplus ) {
|
||
|
alive = 0;
|
||
|
} else {
|
||
|
flags |= _READ | _WRITE;
|
||
|
gotplus = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 't':
|
||
|
if( gottextbin ) {
|
||
|
alive = 0;
|
||
|
} else {
|
||
|
gottextbin = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 'b':
|
||
|
if( gottextbin ) {
|
||
|
alive = 0;
|
||
|
} else {
|
||
|
#ifndef __UNIX__
|
||
|
flags |= _BINARY;
|
||
|
#endif
|
||
|
gottextbin = 1;
|
||
|
}
|
||
|
break;
|
||
|
#ifndef __NETWARE__
|
||
|
case 'c':
|
||
|
if( gotcommit ) {
|
||
|
alive = 0;
|
||
|
} else {
|
||
|
*extflags |= _COMMIT;
|
||
|
gotcommit = 1;
|
||
|
}
|
||
|
break;
|
||
|
case 'n':
|
||
|
if( gotcommit ) {
|
||
|
alive = 0;
|
||
|
} else {
|
||
|
*extflags &= ~_COMMIT;
|
||
|
gotcommit = 1;
|
||
|
}
|
||
|
break;
|
||
|
#endif
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
modestr++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Handle defaults for any unspecified options.
|
||
|
*/
|
||
|
#ifndef __UNIX__
|
||
|
if( !gottextbin ) {
|
||
|
if( _RWD_fmode == O_BINARY ) flags |= _BINARY;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return( flags );
|
||
|
}
|
||
|
|
||
|
|
||
|
static FILE *__F_NAME(__doopen,__wdoopen)( const CHAR_TYPE *name,
|
||
|
CHAR_TYPE mode,
|
||
|
int file_flags,
|
||
|
int extflags,
|
||
|
int shflag, /* sharing flag */
|
||
|
FILE * fp )
|
||
|
{
|
||
|
int open_mode;
|
||
|
int p_mode;
|
||
|
|
||
|
SetupTGCSandNCS( RETURN_ARG( FILE *, 0 ) ); /* for NW386 */
|
||
|
fp->_flag &= ~(_READ | _WRITE);
|
||
|
fp->_flag |= file_flags;
|
||
|
|
||
|
/* we need the mode character to indicate if the original */
|
||
|
/* intention is to open for read or for write */
|
||
|
mode = __F_NAME(tolower,towlower)( mode );
|
||
|
if( mode == 'r' ) {
|
||
|
open_mode = O_RDONLY;
|
||
|
if( file_flags & _WRITE ) { /* if "r+" mode */
|
||
|
open_mode = O_RDWR;
|
||
|
}
|
||
|
#if defined( __NETWARE__ )
|
||
|
open_mode |= O_BINARY;
|
||
|
#elif defined( __UNIX__ )
|
||
|
#else
|
||
|
if( file_flags & _BINARY ) {
|
||
|
open_mode |= O_BINARY;
|
||
|
} else {
|
||
|
open_mode |= O_TEXT;
|
||
|
}
|
||
|
#endif
|
||
|
p_mode = 0;
|
||
|
} else { /* mode == 'w' || mode == 'a' */
|
||
|
if( file_flags & _READ ) { /* if "a+" or "w+" mode */
|
||
|
open_mode = O_RDWR | O_CREAT;
|
||
|
} else {
|
||
|
open_mode = O_WRONLY | O_CREAT;
|
||
|
}
|
||
|
if( file_flags & _APPEND ) {
|
||
|
open_mode |= O_APPEND;
|
||
|
} else { /* mode == 'w' */
|
||
|
open_mode |= O_TRUNC;
|
||
|
}
|
||
|
#if defined( __NETWARE__ )
|
||
|
open_mode |= O_BINARY;
|
||
|
#elif defined( __UNIX__ )
|
||
|
#else
|
||
|
if( file_flags & _BINARY ) {
|
||
|
open_mode |= O_BINARY;
|
||
|
} else {
|
||
|
open_mode |= O_TEXT;
|
||
|
}
|
||
|
#endif
|
||
|
p_mode = PMODE;
|
||
|
}
|
||
|
fp->_handle = __F_NAME(sopen,_wsopen)( name, open_mode, shflag, p_mode );
|
||
|
if( fp->_handle == -1 ) {
|
||
|
// since we couldn't open the file, release the FILE struct
|
||
|
__freefp( fp );
|
||
|
return( NULL );
|
||
|
}
|
||
|
fp->_cnt = 0;
|
||
|
fp->_bufsize = 0; /* was BUFSIZ JBS 31-may-91 */
|
||
|
#ifndef __NETWARE__
|
||
|
_FP_ORIENTATION(fp) = _NOT_ORIENTED; /* initial orientation */
|
||
|
_FP_EXTFLAGS(fp) = extflags;
|
||
|
#endif
|
||
|
#if defined( __NT__ ) || defined( __OS2__ )
|
||
|
_FP_PIPEDATA(fp).isPipe = 0; /* not a pipe */
|
||
|
#endif
|
||
|
_FP_BASE(fp) = NULL;
|
||
|
if( file_flags & _APPEND ) {
|
||
|
fseek( fp, 0L, SEEK_END );
|
||
|
}
|
||
|
__chktty( fp ); /* JBS 28-aug-90 */
|
||
|
return( fp );
|
||
|
}
|
||
|
|
||
|
|
||
|
_WCRTLINK FILE *__F_NAME(_fsopen,_wfsopen)( const CHAR_TYPE *name,
|
||
|
const CHAR_TYPE *access_mode, int shflag )
|
||
|
{
|
||
|
FILE * fp;
|
||
|
int file_flags;
|
||
|
int extflags;
|
||
|
|
||
|
/* validate access_mode */
|
||
|
file_flags = __F_NAME(__open_flags,__wopen_flags)( access_mode, &extflags );
|
||
|
if( file_flags == 0 ) {
|
||
|
return( NULL );
|
||
|
}
|
||
|
|
||
|
/* specify dummy handle 0 */
|
||
|
fp = __allocfp( 0 ); /* JBS 30-aug-91 */
|
||
|
if( fp != NULL ) {
|
||
|
fp = __F_NAME(__doopen,__wdoopen)( name, *access_mode,
|
||
|
file_flags, extflags,
|
||
|
shflag, fp );
|
||
|
}
|
||
|
return( fp );
|
||
|
}
|
||
|
|
||
|
|
||
|
_WCRTLINK FILE *__F_NAME(fopen,_wfopen)( const CHAR_TYPE *name, const CHAR_TYPE *access_mode )
|
||
|
{
|
||
|
return( __F_NAME(_fsopen,_wfsopen)( name, access_mode, OPENMODE_DENY_COMPAT ) );
|
||
|
}
|
||
|
|
||
|
static FILE *close_file( FILE *fp )
|
||
|
{
|
||
|
__stream_link * link;
|
||
|
__stream_link **owner;
|
||
|
|
||
|
_AccessIOB();
|
||
|
/* See if the file pointer is a currently open file. */
|
||
|
link = _RWD_ostream;
|
||
|
for( ;; ) {
|
||
|
if( link == NULL ) break;
|
||
|
if( link->stream == fp ) {
|
||
|
if( fp->_flag & (_READ|_WRITE) ) {
|
||
|
__doclose( fp, 1 );
|
||
|
}
|
||
|
_ReleaseIOB();
|
||
|
return( fp );
|
||
|
}
|
||
|
link = link->next;
|
||
|
}
|
||
|
/*
|
||
|
It's not on the list of open files, so check the list of
|
||
|
recently closed ones.
|
||
|
*/
|
||
|
owner = &_RWD_cstream;
|
||
|
for( ;; ) {
|
||
|
link = *owner;
|
||
|
if( link == NULL ) break;
|
||
|
if( link->stream == fp ) {
|
||
|
/* remove from closed list and put on open */
|
||
|
*owner = link->next;
|
||
|
link->next = _RWD_ostream;
|
||
|
_RWD_ostream = link;
|
||
|
_ReleaseIOB();
|
||
|
return( fp );
|
||
|
}
|
||
|
owner = &link->next;
|
||
|
}
|
||
|
/* We ain't seen that file pointer ever. Leave things be. */
|
||
|
__set_errno( EBADF );
|
||
|
_ReleaseIOB();
|
||
|
return( NULL );
|
||
|
}
|
||
|
|
||
|
|
||
|
_WCRTLINK FILE *__F_NAME(freopen,_wfreopen)( const CHAR_TYPE *name,
|
||
|
const CHAR_TYPE *access_mode, FILE *fp )
|
||
|
{
|
||
|
int hdl;
|
||
|
int file_flags;
|
||
|
int extflags;
|
||
|
|
||
|
_ValidFile( fp, 0 );
|
||
|
|
||
|
/* validate access_mode */
|
||
|
file_flags = __F_NAME(__open_flags,__wopen_flags)( access_mode, &extflags );
|
||
|
if( file_flags == 0 ) {
|
||
|
return( NULL );
|
||
|
}
|
||
|
|
||
|
hdl = fileno( fp );
|
||
|
_AccessFileH( hdl );
|
||
|
|
||
|
#ifdef DEFAULT_WINDOWING
|
||
|
if( _WindowsRemoveWindowedHandle != 0 ) {
|
||
|
_WindowsRemoveWindowedHandle( hdl );
|
||
|
}
|
||
|
#endif
|
||
|
fp = close_file( fp );
|
||
|
if( fp != NULL ) {
|
||
|
fp->_flag &= _DYNAMIC; /* 24-jul-92 */
|
||
|
fp = __F_NAME(__doopen,__wdoopen)( name, *access_mode,
|
||
|
file_flags, extflags,
|
||
|
0, fp );
|
||
|
}
|
||
|
_ReleaseFileH( hdl );
|
||
|
return( fp );
|
||
|
}
|