kolibrios/programs/develop/open watcom/trunk/clib/streamio/fopen.c
Sergey Semyonov (Serge) 3be3768ce0 update CLib
git-svn-id: svn://kolibrios.org@614 a494cfbc-eb01-0410-851d-a64ba20cac60
2007-08-28 10:31:46 +00:00

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 );
}