campo-sirio/cb/source/f4open.c
alex af15e0698b Codebase
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-06-16 13:01:08 +00:00

589 lines
14 KiB
C
Executable File

/* f4open.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif
#ifdef S4TEMP
#include "t4test.h"
#endif
#ifdef S4WINTEL
#ifndef S4IBMOS2
#ifndef __TURBOC__
#include <sys\locking.h>
#define S4LOCKING
#endif
#ifdef __ZTC__
extern int errno ;
#endif
#ifdef _MSC_VER
#include <sys\locking.h>
#endif
#endif
#include <share.h>
#endif /* S4WINTEL */
#include <fcntl.h>
#include <errno.h>
#ifdef S4TRACK_FILES
extern unsigned int numFiles ;
extern int f4print ;
#endif
#ifdef S4ERRNO
extern int errno ;
#endif
/*
** file4openLow() generic outline:
**
** - clear any postive error values
** - if CODE4 is requesting read-only open, then:
** (a) mark file as read only in FILE4 structure
** (b) set the physical file open flag to read only
** - check file physically to see if file has a physical read-only attribute
** (note that this is different than only allowed to have read-only access
** for example on a network drive) --> in some configurations it is not
** possible to make this check. But if it is true:
** (a) mark file as read only in FILE4 structure
** (b) set the physical file open flag to read only
** (c) mark the FILE4 as exclusive open (since nobody can write to it, can
** treat it as such
** - set the shared flag based on CODE4::accessMode
** 3 possible settings: OPEN4DENY_NONE, OPEN4DENY_WRITE, OPEN4DENY_RW.
** return failure if no the setting is invalid.
** - physically attempt the file open
** - if the file open failed, try to determine the cause of failure and return
** the appropriate error message. e4open is returned if the specific
** failure cannot be determined.
**
** Returns: 0 = success, e4... = failure (appropriate error condition)
**
** Notes:
** This routine shouldn't generate a CodeBase error
*/
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
#ifdef S4UNIX
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
{
int rc = 0 ;
int oflag ;
#ifdef S4NO_FLOCK
struct flock lck;
lck.l_whence = SEEK_SET ;
lck.l_start = 0 ;
lck.l_len = 1000000000 ;
#endif
error4set( c4, 0 ) ; /* clear positive error values */
if ( c4->readOnly == 1 )
{
file->isReadOnly = 1 ;
oflag = (int)O_RDONLY ;
}
else
oflag = (int)O_RDWR ;
file->hand = open( name, oflag ) ;
switch ( c4->accessMode )
{
case OPEN4DENY_NONE:
case OPEN4DENY_WRITE:
#ifndef S4NO_FLOCK
rc = flock (file->hand, LOCK_SH|LOCK_NB) ;
#else
lck.l_type = F_RDLCK ;
rc = fcntl (file->hand, F_SETLK, &lck ) ;
#endif
break;
case OPEN4DENY_RW:
#ifndef S4NO_FLOCK
rc = flock (file->hand, LOCK_EX|LOCK_NB) ;
#else
lck.l_type = F_WRLCK ;
rc = fcntl (file->hand, F_SETLK, &lck ) ;
#endif
break;
default:
close(file->hand);
file->hand = -1;
return e4open;
}
if (rc!=0)
return e4open;
if ( file->hand < 0 )
{
/* note: getting error classification is required to allow for
occasional recovery from exceeded file handle problems */
switch( errno ) /* try to get some clarification on the error */
{
case EACCES:
return e4permiss ;
case EMFILE: /* allow try closing excess files and retrying */
return e4numFiles ;
case ENOENT:
return e4fileFind ;
default:
return e4open ;
}
}
return 0 ;
}
#endif /* S4UNIX */
#ifdef S4WIN32
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
{
DWORD fdwAccess, fdwShareMode, fAttributes ;
error4set( c4, 0 ) ; /* clear positive error values */
fAttributes = GetFileAttributes( name ) ;
if ( fAttributes != 0xFFFFFFFF && fAttributes & FILE_ATTRIBUTE_READONLY )
{
file->isReadOnly = 1 ;
fdwAccess = GENERIC_READ ;
#ifndef S4OFF_MULTI
file->lowAccessMode = OPEN4DENY_RW ; /* for a file read-only can treat as exclusive */
#endif
}
else
{
if ( c4->readOnly == 1 )
{
file->isReadOnly = 1 ;
fdwAccess = GENERIC_READ ;
}
else
fdwAccess = GENERIC_WRITE | GENERIC_READ ;
}
#ifdef S4OFF_MULTI
#ifdef E4DEBUG
/* open in shared mode for debugging to allow other programs to examine */
fdwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ ;
#else
/* otherwise, if single-user, file should be opened exclusively */
fdwShareMode = 0 ;
#endif
#else
switch( c4->accessMode )
{
case OPEN4DENY_NONE:
fdwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ ;
break ;
case OPEN4DENY_WRITE:
fdwShareMode = FILE_SHARE_READ ;
break ;
case OPEN4DENY_RW:
fdwShareMode = 0 ;
break ;
default:
file->hand = -1 ;
return e4open ;
}
#endif /* S4OFF_MULTI */
file->hand = (int) CreateFile( name, fdwAccess, fdwShareMode, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ;
if ( file->hand == (int)INVALID_HANDLE_VALUE )
{
/* note: getting error classification is required to allow for
occasional recovery from exceeded file handle problems */
switch( errno ) /* try to get some clarification on the error */
{
case EACCES:
return e4permiss ;
#ifdef __TURBOC__
case EINVACC:
return e4access ;
#endif
case EMFILE: /* allow try closing excess files and retrying */
return e4numFiles ;
case ENOENT:
return e4fileFind ;
default:
return e4open ;
}
}
#ifdef S4MULTI_THREAD
InitializeCriticalSection( &file->critical4file ) ;
#endif
#ifdef S4ADVANCE_READ
file->advanceReadBufStatus = AR4EMPTY ;
#endif
return 0 ;
}
#endif /* S4WIN32 */
#ifdef S4WIN16
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
{
int oflag, sMode ;
error4set( c4, 0 ) ; /* clear positive error values */
/* check the file's dos read only attrib -- which improves performance */
if ( c4->readOnly == 1 )
{
file->isReadOnly = 1 ;
oflag = (int)OF_READ ;
}
else
oflag = (int)OF_READWRITE ;
#ifdef S4OFF_MULTI
#ifdef E4DEBUG
/* open in shared mode for debugging to allow other programs to examine */
sMode = (int)OF_SHARE_DENY_NONE ;
#else
/* otherwise, if single-user, file should be opened exclusively */
sMode = (int)OF_SHARE_EXCLUSIVE ;
#endif
#else
switch( c4->accessMode )
{
case OPEN4DENY_NONE:
sMode = (int)OF_SHARE_DENY_NONE ;
break ;
case OPEN4DENY_WRITE:
sMode = (int)OF_SHARE_DENY_WRITE ;
break ;
case OPEN4DENY_RW:
sMode = (int)OF_SHARE_EXCLUSIVE ;
break ;
default:
file->hand = -1 ;
return e4open ;
}
#endif
file->hand = _lopen( name, oflag | sMode ) ;
if ( file->hand < 0 )
{
/* note: getting error classification is required to allow for
occasional recovery from exceeded file handle problems */
switch( errno ) /* try to get some clarification on the error */
{
case EACCES:
return e4permiss ;
#ifdef __TURBOC__
case EINVACC:
return e4access ;
#endif
case EMFILE: /* allow try closing excess files and retrying */
return e4numFiles ;
case ENOENT:
return e4fileFind ;
default:
return e4open ;
}
}
return 0 ;
}
#endif /* S4WIN16 */
#ifdef S4WINTEL
#ifndef S4WIN16
#ifndef S4WIN32
#ifndef S4OS2
#ifdef __TURBOC__
#define S4USE_CHMOD
#endif
#ifdef _MSC_VER
#define S4USE_CHMOD
#endif
#endif
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
{
#ifdef _MSC_VER
#ifdef S4USE_CHMOD
unsigned attribute ;
#endif
#endif
int oflag, shflag ;
error4set( c4, 0 ) ; /* clear positive error values */
/* check the file's dos read only attrib -- which improves performance */
#ifdef S4USE_CHMOD
errno = 0 ;
#ifdef __TURBOC__
if ( _A_RDONLY & _chmod( name, 0 ) )
#endif
#ifdef _MSC_VER
_dos_getfileattr( name, &attribute ) ;
if (_A_RDONLY & attribute )
#endif
{
if ( errno == ENOENT ) /* file doesn't exist */
{
file->hand = -1 ;
if ( c4->errOpen )
return e4open ;
}
file->isReadOnly = 1 ;
#ifndef S4OFF_MULTI
file->lowAccessMode = OPEN4DENY_RW ; /* for a file read-only can treat as exclusive */
#endif
oflag = (int)(O_BINARY | O_RDONLY) ;
}
else
{
#endif
if ( c4->readOnly == 1 )
{
file->isReadOnly = 1 ;
oflag = (int)(O_BINARY | O_RDONLY) ;
}
else
{
oflag = (int)(O_BINARY | O_RDWR) ;
}
#ifdef S4USE_CHMOD
}
#endif
#ifdef S4OFF_MULTI
shflag = SH_DENYRW ;
#else
switch ( c4->accessMode )
{
case OPEN4DENY_NONE:
shflag = SH_DENYNO ;
break ;
case OPEN4DENY_WRITE:
shflag = SH_DENYWR ;
break ;
case OPEN4DENY_RW:
shflag = SH_DENYRW ;
break ;
default:
file->hand = -1 ;
return e4open ;
}
#endif
file->hand = sopen( name, oflag, shflag, 0 ) ;
if ( file->hand < 0 )
{
/* note: getting error classification is required to allow for
occasional recovery from exceeded file handle problems */
switch( errno ) /* try to get some clarification on the error */
{
case EACCES:
return e4permiss ;
#ifdef __TURBOC__
case EINVACC:
return e4access ;
#endif
case EMFILE: /* allow try closing excess files and retrying */
return e4numFiles ;
case ENOENT:
return e4fileFind ;
default:
return e4open ;
}
}
return 0 ;
}
#ifdef S4USE_CHMOD
#undef S4USE_CHMOD
#endif
#endif /* S4WIN32 */
#endif /* S4WIN16 */
#endif /* S4WINTEL */
int S4FUNCTION file4open( FILE4 *file, CODE4 *c4, S4CONST char *name, const int doAlloc )
{
int rc, len ;
#ifdef E4PARM_HIGH
if ( file == 0 || c4 == 0 || name == 0 )
return error4( c4, e4parm, E90615 ) ;
#endif
if ( error4code( c4 ) < 0 )
return e4codeBase ;
#ifndef S4OPTIMIZE_OFF
code4memStartMaxSet( c4, c4->memMaxPercent ) ; /* start optimization if not enabled and not suspended */
#endif
memset( (void *)file, 0, sizeof( FILE4 ) ) ;
file->codeBase = c4 ;
file->hand = -1 ;
rc = file4openLow( file, c4, name ) ;
#ifdef S4SERVER
if ( rc != 0 )
{
if ( rc != 0 && rc != e4fileFind && rc != e4permiss && rc != e4access )
{
error4set( c4, 0 ) ;
rc = code4dataFileCloseAll( c4 ) ;
if ( rc < 0 )
return rc ;
rc = file4openLow( file, c4, name ) ;
}
if ( c4->readOnly == 0 && c4->readOnlyRequest == 1 ) /* try opening in read-only mode */
{
error4set( c4, 0 ) ;
c4->readOnly = 1 ;
rc = file4openLow( file, c4, name ) ;
c4->readOnly = 0 ;
}
}
#endif
if ( rc != 0 )
{
if ( c4->errOpen )
return error4describe( c4, rc, E90615, name, (char *) 0, (char *) 0 ) ;
else
{
error4set( c4, r4noOpen ) ;
return r4noOpen ;
}
}
if ( doAlloc )
{
len = strlen( name ) + 1 ;
file->nameBuf = (char *)u4allocFree( c4, (long)len ) ;
if ( file->nameBuf == 0 )
{
file4close( file ) ;
return error4( c4, e4memory, E90615 ) ;
}
file->doAllocFree = 1 ;
u4ncpy( file->nameBuf, name, (unsigned int)len ) ;
file->name = file->nameBuf ;
}
else
file->name = name ;
#ifndef S4OFF_MULTI
file->lowAccessMode = c4->accessMode ;
#endif
#ifndef S4OPTIMIZE_OFF
file->fileCreated = 1 ;
#endif
#ifdef S4TRACK_FILES
numFiles++ ;
if ( f4print != -1 )
{
#ifdef S4WINDOWS
#ifdef S4TESTING
if ( mem4displayPtr == 0 )
error4( 0, e4info, E50101 ) ;
d4display_str( mem4displayPtr, "\r\nfile opened: ", 1 ) ;
d4display_str( mem4displayPtr, f4print, file->name ) ;
#else
u4writeErr( "file opened: ", 1 ) ;
u4writeErr( file->name, 0 ) ;
#endif
#else
if ( f4print )
fprintf( stdprn, "\r\nfile opened: %s", file->name ) ;
else
printf( "\r\nfile opened: %s", file->name ) ;
#endif
}
#endif
return rc ;
}
int S4FUNCTION file4openTest( FILE4 *f4 )
{
return f4->hand >= 0 ;
}