campo-sirio/cb/source/d4open.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

1498 lines
43 KiB
C
Executable File

/* d4open.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif
#ifdef S4OFF_MEMO
extern char f4memoNullChar ;
#endif
/* */
#ifdef S4UNIX
#include <sys/stat.h>
#else
#include "sys\stat.h"
#endif
/* */
static DATA4FILE *data4reopen( DATA4FILE *, char ** ) ;
static DATA4 *d4openInit( CODE4 *c4 )
{
DATA4 *d4 ;
#ifdef S4STAND_ALONE
#ifndef S4OFF_TRAN
int rc;
#endif
#endif
#ifdef S4VBASIC
if ( c4parm_check( c4, 1, E94301 ) )
return 0 ;
#endif
if ( error4code( c4 ) < 0 )
return 0 ;
#ifdef E4ANALYZE
if ( c4->debugInt != 0x5281 )
{
error4( 0, e4result, E81301 ) ;
return 0 ;
}
#endif
#ifdef S4STAND_ALONE
#ifndef S4OFF_TRAN
if ( c4->logOpen )
{
rc = code4logOpen( c4, 0, 0 ) ;
if ( rc < 0 )
return 0 ;
else
error4set( c4, 0 ) ; /* remove r4open if it already existed */
}
#endif
#endif
#ifndef S4CLIENT
#ifdef E4ANALYZE
#ifndef S4STAND_ALONE
if ( c4->currentClient == 0 )
{
error4( c4, e4struct, E94301 ) ;
return 0 ;
}
if ( c4->currentClient->trans.c4trans == 0 )
{
error4( c4, e4struct, E94301 ) ;
return 0 ;
}
#endif
#endif
#endif
if ( c4->dataMemory == 0 )
{
c4->dataMemory = mem4create( c4, c4->memStartData, sizeof(DATA4), c4->memExpandData, 0 ) ;
if ( c4->dataMemory == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E94301 ) ;
#endif
return 0 ;
}
}
d4 = (DATA4 *)mem4alloc( c4->dataMemory ) ;
if ( d4 == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E94301 ) ;
#endif
return 0 ;
}
#ifdef S4VBASIC
d4->debugInt = E4DEBUG_INT ;
#endif
d4->codeBase = c4 ;
#ifdef S4SERVER
d4->clientId = 1L ; /* should get overridden at a later point, unless this is a server-only data file */
d4->serverId = c4->server->serverDataCount ;
c4->server->serverDataCount++ ;
d4->trans = &c4->currentClient->trans ;
l4add( tran4dataList( d4->trans ), d4 ) ;
#else
d4->trans = &c4->c4trans.trans ;
l4add( tran4dataList( (&(c4->c4trans.trans)) ), d4 ) ;
#endif
return d4 ;
}
static int d4openConclude( DATA4 *d4, const char *name, char *info )
{
CODE4 *c4 ;
int iFields, fieldType ;
unsigned int recOffset ;
long recWidth ;
#ifdef S4CLIENT_OR_FOX
int nullCount ;
#endif
char fieldBuf[2] ;
FIELD4IMAGE *image ;
#ifndef S4CLIENT
#ifdef S4CLIPPER
#ifndef S4OFF_INDEX
char nameBuf[258] ;
#else
#ifndef S4OFF_TRAN
#ifndef S4OFF_WRITE
char nameBuf[258] ;
#endif
#endif
#endif
#else
#ifndef S4OFF_TRAN
#ifndef S4OFF_WRITE
char nameBuf[258] ;
#endif
#endif
#endif
#ifndef S4OFF_WRITE
#ifndef S4OFF_TRAN
TRAN4 *trans ;
int tranCode ;
/* */
struct stat bufStat ;
/* */
/* */
/* */
/* */
long connectionId, rcl ;
short rc ;
#endif
#endif
#ifndef S4OFF_INDEX
INDEX4 *i4 ;
#ifndef S4SERVER
#ifndef S4CLIPPER
int oldSingleOpen ;
#endif
#endif
#endif
#else
#ifndef S4OFF_INDEX
char nameBuf[258] ;
#endif
#endif
#ifndef S4OFF_MEMO
int i_memo ;
#endif
c4 = d4->codeBase ;
#ifdef E4ANALYZE
if ( d4->dataFile->nFields == 0 )
return error4describe( c4, e4struct, E94301, name, 0, 0 ) ;
#endif
u4namePiece( d4->alias, sizeof( d4->alias ), name, 0, 0 ) ;
d4->alias[ sizeof( d4->alias ) - 1 ] = 0 ;
recWidth = dfile4recWidth( d4->dataFile ) ;
if ( ( ( recWidth + 50L + 1L ) * 2L + (long)sizeof( FIELD4 ) * (long)d4->dataFile->nFields ) > (long)UINT_MAX ) /* try allocating records and fields together, 50 bytes for overhead */
{
d4->groupRecordAlloc = (char *)u4allocFree( c4, (recWidth + 1L) * 2L + (long)sizeof( FIELD4 ) * (long)d4->dataFile->nFields ) ;
if ( d4->groupRecordAlloc != 0 )
{
d4->record = d4->groupRecordAlloc ;
d4->recordOld = d4->groupRecordAlloc + recWidth + 1 ;
d4->fields = (FIELD4 *)(d4->groupRecordAlloc + 2 * ( recWidth + 1 ) ) ;
}
}
if ( d4->groupRecordAlloc == 0 )
{
d4->record = (char *)u4allocFree( c4, recWidth + 1 ) ;
d4->recordOld = (char *)u4allocFree( c4, recWidth + 1 ) ;
d4->fields = (FIELD4 *)u4allocFree( c4, sizeof( FIELD4 ) * (long)d4->dataFile->nFields ) ;
}
if ( d4->record == 0 || d4->recordOld == 0 || d4->fields == 0 )
return error4stack( c4, e4memory, E94301 ) ;
recOffset = 1 ;
#ifdef S4CLIENT_OR_FOX
nullCount = 0 ;
#endif
if ( !( error4code( c4 ) < 0 ) )
for ( iFields = 0 ; iFields < d4->dataFile->nFields ; iFields++ )
{
image = (FIELD4IMAGE *)( info + iFields * 32 ) ;
u4ncpy( d4->fields[iFields].name, image->name, sizeof( d4->fields->name ) ) ;
u4ncpy( fieldBuf, &image->type, 2 ) ;
c4upper( fieldBuf ) ;
d4->fields[iFields].type = *fieldBuf ;
fieldType = d4->fields[iFields].type ;
#ifdef S4CLIENT_OR_FOX
if ( d4version( d4 ) == 0x30 ) /* FOX 3.0 */
{
d4->fields[iFields].null = ( image->nullBinary & 0x02 ) ? 1 : 0 ;
if ( d4->fields[iFields].null == 1 )
{
d4->fields[iFields].nullBit = nullCount ;
nullCount++ ;
}
if ( image->nullBinary & 0x04 )
d4->fields[iFields].binary = 1 ;
else
{
if ( fieldType == r4memo || fieldType == r4gen ) /* memo fields are also stored binary */
d4->fields[iFields].binary = 2 ;
else
d4->fields[iFields].binary = 0 ;
}
}
#endif
switch( fieldType )
{
#ifdef S4CLIENT_OR_FOX
case r4int:
#endif
case r4log:
case r4date:
d4->fields[iFields].len = image->len ;
break ;
case r4double: /* same as r4bin */
if ( d4version( d4 ) == 0x30 ) /* double */
{
d4->fields[iFields].len = image->len ;
d4->fields[iFields].dec = image->dec ;
}
else /* binary */
d4->fields[iFields].len = image->len ;
break ;
case r4num:
case r4float:
#ifdef S4CLIENT_OR_FOX
case r4currency:
case r4dateTime:
#endif
d4->fields[iFields].len = image->len ;
d4->fields[iFields].dec = image->dec ;
break ;
case r4memo:
case r4gen:
/* #ifdef S4OFF_MEMO */
/* d4->fields[iFields].memo = (F4MEMO *)&f4memoNullChar ; */
/* #endif */
d4->fields[iFields].len = image->len ;
break ;
default:
d4->fields[iFields].len = image->len + ( image->dec << 8 ) ;
break ;
}
#ifdef S4VBASIC
d4->fields[iFields].debugInt = E4DEBUG_INT ;
#endif
d4->fields[iFields].offset = recOffset ;
recOffset += d4->fields[iFields].len ;
d4->fields[iFields].data = d4 ;
}
#ifndef S4OFF_MEMO
if ( d4->dataFile->nFieldsMemo > 0 && !( error4code( c4 ) < 0 ) )
{
i_memo = 0 ;
d4->fieldsMemo = (F4MEMO *)u4allocFree( c4, (long)sizeof(F4MEMO) * d4->dataFile->nFieldsMemo ) ;
#ifdef E4STACK
if ( d4->fieldsMemo == 0 )
error4stack( c4, e4memory, E94301 ) ;
#endif
if ( d4->fieldsMemo != 0 )
for ( iFields = 0 ; iFields < d4->dataFile->nFields ; iFields++ )
{
fieldType = d4->fields[iFields].type ;
if ( fieldType == r4memo || fieldType == r4gen || ( fieldType == r4bin && d4version( d4 ) != 0x30 ) )
{
d4->fields[iFields].memo = d4->fieldsMemo+i_memo ;
d4->fieldsMemo[i_memo].status = 1 ;
d4->fieldsMemo[i_memo].field = d4->fields+iFields ;
i_memo++ ;
}
}
}
#endif
if ( error4code( c4 ) < 0 )
return -1 ;
d4->recNum = d4->recNumOld = -1 ;
d4blank( d4 ) ;
memcpy( d4->recordOld, d4->record, (unsigned)recWidth ) ;
d4->recordChanged = 0 ;
d4->record[recWidth] = 0 ;
d4->recordOld[recWidth] = 0 ;
#ifndef S4OFF_INDEX
#ifdef S4CLIENT
/* client will get all the index tags if autoOpen set to 1, else
will get none -- this is an undocumented side-effect */
if ( d4->dataFile->indexes.nLink > 0 && c4->autoOpen == 1 )
{
u4namePiece( nameBuf, sizeof( nameBuf ), name, 0, 0 ) ;
if ( i4setup( c4, d4, nameBuf, 1, 0 ) < 0 )
return -1 ;
}
#else
#ifdef S4CLIPPER
if ( c4->autoOpen )
{
if ( d4->dataFile->userCount > 1 ) /* already open, just set up tags */
{
u4namePiece( nameBuf, sizeof( nameBuf ), name, 0, 0 ) ;
if ( i4setup( c4, d4, nameBuf, 1 ) < 0 )
return -1 ;
}
else
{
#ifdef S4SERVER
/* if a temp file, tags already available... */
if ( d4->dataFile->file.isTemp == 1 )
{
if ( i4setup( c4, d4, nameBuf, 1 ) < 0 )
return -1 ;
}
#endif
i4 = i4open( d4, 0 ) ;
#ifdef S4SERVER
if ( i4 == 0 ) /* server version, if no .cgp file then don't open index */
error4set( c4, 0 ) ;
#else
if ( i4 == 0 )
return -1 ;
#endif
}
}
#else
#ifdef S4STAND_ALONE
d4->dataFile->openMdx = 0 ;
#endif
if ( ( d4->dataFile->hasMdxMemo & 0x01 ) && c4->autoOpen )
{
#ifndef S4SERVER
oldSingleOpen = c4->singleOpen ;
c4->singleOpen = OPEN4SPECIAL ;
#endif
i4 = i4open( d4, 0 ) ;
#ifndef S4SERVER
c4->singleOpen = oldSingleOpen ;
#endif
if ( i4 == 0 )
return -1 ;
#ifdef S4MDX
if ( !i4->indexFile->header.isProduction )
i4close( i4 ) ;
#endif
#ifdef S4STAND_ALONE
d4->dataFile->openMdx = 1 ;
#endif
}
#endif
#endif /* S4CLIENT */
#endif /* S4OFF_INDEX */
#ifndef S4SERVER
c4->clientDataCount++ ;
d4->clientId = c4->clientDataCount ;
#endif
#ifndef S4OFF_WRITE
#ifndef S4OFF_TRAN
#ifndef S4CLIENT
if ( code4transEnabled( c4 ) )
{
trans = code4trans( c4 ) ;
#ifdef S4STAND_ALONE
connectionId = 0L ;
#else
connectionId = connection4id( c4->currentClient->connection ) ;
#endif
rc = u4nameCurrent( nameBuf, sizeof( nameBuf ), dfile4name( d4->dataFile ) ) ;
if ( rc < 0 )
return error4stack( c4, rc, E94301 ) ;
#ifdef S4CASE_SEN
rc = u4nameExt( nameBuf, sizeof( nameBuf ), "dbf", 0 ) ;
#else
rc = u4nameExt( nameBuf, sizeof( nameBuf ), "DBF", 0 ) ;
#endif
if ( rc < 0 )
return error4stack( c4, rc, E94301 ) ;
rc = strlen(nameBuf) ;
if (c4->createTemp == 1)
tranCode = TRAN4OPEN_TEMP ;
else
tranCode = TRAN4OPEN ;
if ( tran4set( trans, trans->currentTranStatus, -1L, connectionId, tranCode,
(unsigned)rc + 19, data4clientId( d4 ), data4serverId( d4 ) ) == 0 )
{
tran4putData( trans, &rc, 2 ) ;
tran4putData( trans, nameBuf, (unsigned)rc ) ;
rcl = recWidth ;
tran4putData( trans, &rcl, 4 ) ;
rc = d4numFields( d4 ) ;
tran4putData( trans, &rc, 2 ) ;
rcl = d4recCount( d4 ) ;
tran4putData( trans, &rcl, 4 ) ;
/* */
if ( stat( nameBuf, &bufStat ) != 0 )
return -1 ;
tran4putData( trans, &bufStat.st_atime, 4 ) ;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
tran4putData( trans, &d4->dataFile->yy, 3 ) ;
tran4lowAppend( trans, 0 ) ;
}
else
return -1 ;
}
#endif /* S4CLIENT */
#endif /* S4OFF_TRAN */
#endif /* S4OFF_WRITE */
#ifdef S4SERVER
d4->accessMode = c4->singleClient ;
if ( d4->accessMode == OPEN4DENY_RW )
d4->dataFile->exclusiveOpen = d4 ;
#endif
#ifndef S4CLIENT
d4->readOnly = c4->readOnly ;
#endif
#ifndef S4OFF_TRAN
#ifndef S4CLIENT
if ( code4transEnabled( d4->codeBase ) == 1 )
d4->logVal = c4->log ;
#endif
#endif
return 0 ;
}
DATA4 *S4FUNCTION d4open( CODE4 *c4, const char *name )
{
int rc ;
char *info ;
DATA4 *d4 ;
#ifdef E4PARM_HIGH
if ( c4 == 0 || name == 0 )
{
error4( 0, e4parm_null, E94301 ) ;
return 0 ;
}
#endif
d4 = d4openInit( c4 ) ;
if ( d4 != 0 )
{
d4->dataFile = dfile4open( c4, d4, name, &info ) ;
if ( d4->dataFile == 0 )
{
d4close( d4 ) ;
return 0 ;
}
rc = d4openConclude( d4, name, info ) ;
if ( rc < 0 )
{
d4close( d4 ) ;
return 0 ;
}
}
return d4 ;
}
DATA4 *S4FUNCTION d4openClone( DATA4 *dataOld )
{
DATA4 *d4 ;
int rc ;
char *info ;
#ifndef S4SERVER
int oldSingleOpen ;
#endif
#ifdef E4PARM_HIGH
if ( dataOld == 0 )
{
error4( 0, e4parm_null, E94301 ) ;
return 0 ;
}
#endif
d4 = d4openInit( dataOld->codeBase ) ;
if ( d4 == 0 )
return 0 ;
#ifndef S4SERVER
oldSingleOpen = dataOld->codeBase->singleOpen ;
dataOld->codeBase->singleOpen = OPEN4DENY_NONE ;
#endif
d4->dataFile = data4reopen( dataOld->dataFile, &info ) ;
if ( d4->dataFile == 0 )
{
#ifndef S4SERVER
dataOld->codeBase->singleOpen = oldSingleOpen ;
#endif
d4close( d4 ) ;
return 0 ;
}
rc = d4openConclude( d4, dfile4name( d4->dataFile ), info ) ;
#ifndef S4SERVER
dataOld->codeBase->singleOpen = oldSingleOpen ;
#endif
if ( rc < 0 )
{
d4close( d4 ) ;
return 0 ;
}
return d4 ;
}
#ifndef S4OFF_INDEX
#ifdef S4CLIENT
int client4indexSetup( CODE4 *c4, DATA4 *d4, DATA4FILE *data, unsigned int numTags, const char *info, unsigned int iLen, const char *indexAlias, INDEX4 *i4ndx )
{
unsigned int i ;
TAG4FILE *tag, *first ;
INDEX4FILE *i4file ;
long infoLen ;
DATA4FILE *oldDataFile ;
int doTags ;
#ifdef E4PARM_LOW
if ( c4 == 0 || d4 == 0 || data == 0 || info == 0 )
return error4( c4, e4parm_null, E94302 ) ;
#endif
infoLen = iLen ;
if ( numTags == 0 )
return 0 ;
if ( c4->index4fileMemory == 0 )
{
c4->index4fileMemory = mem4create( c4, c4->memStartIndexFile, sizeof(INDEX4FILE), c4->memExpandIndexFile, 0 ) ;
if ( c4->index4fileMemory == 0 )
return e4memory ;
}
if ( c4->tagFileMemory == 0 )
{
c4->tagFileMemory = mem4create( c4, c4->memStartTagFile, sizeof(TAG4FILE), c4->memExpandTagFile, 0 ) ;
if ( c4->tagFileMemory == 0 )
return e4memory ;
}
oldDataFile = d4->dataFile ; ;
d4->dataFile = data ;
/* passing non-null into index4open will ensure that an actual open
does not occur, but simply a check will occur ... */
if ( i4ndx != 0 )
i4file = i4ndx->indexFile ;
else
i4file = index4open( d4, indexAlias, (INDEX4 *)1 ) ;
if ( i4file == 0 )
{
i4file = (INDEX4FILE *)mem4alloc( c4->index4fileMemory ) ;
if ( i4file == 0 )
{
d4->dataFile = oldDataFile ;
return error4stack( c4, e4memory, E94302 ) ;
}
i4file->codeBase = c4 ;
i4file->autoOpened = 1 ;
i4file->dataFile = data ;
i4file->clientId = data4clientId( d4 ) ;
i4file->serverId = data4serverId( d4 ) ;
d4->dataFile = oldDataFile ;
#ifdef E4MISC
if ( strlen( indexAlias ) > sizeof( i4file->accessName ) )
return error4describe( c4, e4name, E91102, indexAlias, 0, 0 ) ;
#endif
strcpy( i4file->accessName, indexAlias ) ;
c4upper( i4file->accessName ) ;
l4add( &data->indexes, i4file ) ;
doTags = 1 ;
}
else
doTags = 0 ;
/* only execute next if i4file was not blank and i4ndx was blank */
if ( i4ndx != 0 || doTags == 1 ) /* new index file, or add to existing */
{
for ( i = 0 ; i < numTags ; i++ )
{
tag = (TAG4FILE *)mem4alloc( c4->tagFileMemory ) ;
if ( tag == 0 )
return e4memory ;
infoLen -= LEN4TAG_ALIAS ;
if ( infoLen < 0 )
return e4connection ;
memcpy( tag->alias, info, LEN4TAG_ALIAS ) ;
tag->indexFile = i4file ;
info += LEN4TAG_ALIAS ;
tag->errUniqueHold = *(int *)info ;
info += sizeof( short int ) ;
first = (TAG4FILE *)l4first( &i4file->tags ) ;
if ( first == 0 )
l4add( &i4file->tags, tag ) ;
else
l4addBefore( &i4file->tags, first, tag ) ;
}
}
else
d4->dataFile = oldDataFile ;
return 0 ;
}
#endif /* S4CLIENT */
#endif /* not S4OFF_INDEX */
#ifdef S4SERVER
/* what is the maximal read and access setting on the data file */
/* does not report results for current client */
static void dfile4accesses( DATA4FILE *d4, int *readMode, int *accessMode, int *otherUsers )
{
SERVER4CLIENT *client ;
DATA4 *data ;
*readMode = 1 ;
*accessMode = OPEN4DENY_NONE ;
*otherUsers = 0 ;
for ( client = 0 ;; )
{
client = (SERVER4CLIENT *)l4next( &d4->c4->server->clients, client ) ;
if ( client == 0 )
break ;
if ( client == d4->c4->currentClient )
continue ;
for ( data = 0 ;; )
{
data = (DATA4 *)l4next( tran4dataList( &client->trans ), data ) ;
if ( data == 0 )
break ;
if ( data->dataFile == d4 )
{
*otherUsers = 1 ;
if ( data->readOnly == 0 )
*readMode = 0 ;
if ( *accessMode != OPEN4DENY_RW)
if ( data->accessMode != *accessMode )
if ( data->accessMode != OPEN4DENY_NONE )
*accessMode = data->accessMode ;
if ( *readMode == 0 && *accessMode == OPEN4DENY_RW ) /* maximal already */
return ;
}
}
}
return ;
}
/* returns 1 if file can be accessed in desired mode */
static int dfile4checkAccess( DATA4FILE *d4, int accessRequested, int readOnly )
{
int maxAccess, maxRead, otherUsers ;
if ( d4->userCount == 0 )
return 1 ;
/* first get maximal access and read modes of other users */
dfile4accesses( d4, &maxRead, &maxAccess, &otherUsers ) ;
if ( otherUsers == 0 ) /* no other users, so any requests are ok */
return 1 ;
if ( accessRequested == OPEN4DENY_RW ) /* others users accessing, so no */
return 0 ;
if ( maxAccess == OPEN4DENY_RW ) /* other user is disallowing our access */
return 0 ;
if ( readOnly == 0 ) /* need write access */
{
if ( maxAccess != OPEN4DENY_NONE )
return 0 ;
/* maxAccess is DENY_NONE, so continue */
switch( accessRequested )
{
case OPEN4DENY_NONE:
return 1 ;
case OPEN4DENY_WRITE:
if ( maxRead == 1 ) /* others only reading, so ok */
return 1 ;
/* fall through, and any other case, access denied */
default:
return 0 ;
}
}
/* is readOnly, so deny_write allowable by others */
switch( maxAccess )
{
case OPEN4DENY_RW:
return 0 ;
case OPEN4DENY_WRITE:
switch ( accessRequested )
{
case OPEN4DENY_NONE:
return 1 ;
case OPEN4DENY_WRITE:
if ( maxRead == 1 )
return 1 ;
/* fall through or default, no access */
default:
return 0 ;
}
default:
break ;
}
return 1 ;
}
#endif /* S4SERVER */
static DATA4FILE *data4reopen( DATA4FILE *d4, char **info )
{
#ifndef S4CLIENT
#ifndef S4OFF_MULTI
int rc ;
#ifndef S4OFF_INDEX
#ifdef S4CLIPPER
TAG4FILE *t4file ;
#else
INDEX4FILE *i4file ;
#ifdef E4ANALYZE
#ifndef S4CLIPPER
unsigned short int nCheck ;
#endif
#endif
#endif
#endif
#endif
#endif
#ifndef S4SERVER
#ifndef S4OFF_TRAN
DATA4 *data4 ;
LIST4 *list ;
#endif
#endif
CODE4 *c4 ;
if ( d4 == 0 )
return 0 ;
c4 = d4->c4 ;
#ifndef S4CLIENT
if ( d4->userCount == 0 )
{
#ifndef S4OFF_MULTI
if ( d4->file.lowAccessMode != c4->accessMode ) /* need to open in updated mode */
{
rc = dfile4closeLow( d4 ) ;
if ( rc != 0 )
return 0 ;
#ifndef S4OFF_INDEX
#ifdef S4CLIPPER
for ( t4file = 0 ;; )
{
t4file = (TAG4FILE *)l4next( &d4->tagfiles, t4file ) ;
if ( t4file == 0 )
break ;
rc = tfile4close( t4file, d4 ) ;
if ( rc < 0 )
return 0 ;
}
#else
if ( d4->indexes.nLink != ((unsigned int)d4->hasMdxMemo & 0x01 ) )
{
for ( i4file = 0 ;; )
{
i4file = (INDEX4FILE *)l4next( &d4->indexes, i4file ) ;
if ( i4file == 0 )
break ;
if ( index4isProduction( i4file ) == 1 )
continue ;
#ifdef E4ANALYZE
nCheck = d4->indexes.nLink ;
#endif
rc = index4close( i4file ) ;
#ifdef E4ANALYZE
if ( nCheck != d4->indexes.nLink + 1 )
{
error4describe( c4, e4result, E91102, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
#endif
if ( rc < 0 )
return 0 ;
}
}
#endif /* S4CLIPPER */
#endif /* S4OFF_INDEX */
d4 = 0 ;
}
#endif /* S4OFF_MULTI */
}
else
{
#endif /* S4CLIENT */
#ifndef S4SERVER
if ( c4->singleOpen != OPEN4DENY_NONE ) /* only one instance allowed... */
{
#ifndef S4SERVER
#ifndef S4OFF_TRAN
/* verify that data4 not on the closed data list if within a
transaction (which is allowed) */
if ( code4tranStatus( c4 ) == r4active )
{
list = tran4dataList( code4trans( c4 ) ) ;
for ( data4 = 0 ;; )
{
data4 = (DATA4 *)l4next( list, data4 ) ;
if ( data4 == 0 )
break ;
if ( data4->dataFile == d4 )
{
error4describe( c4, e4instance, E91102, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
}
#ifdef E4ANALYZE
/* ensure that the datafile exists somewhere! */
list = &( code4trans( c4 )->closedDataFiles ) ;
for ( data4 = 0 ;; )
{
data4 = (DATA4 *)l4next( list, data4 ) ;
if ( data4 == 0 )
{
error4describe( c4, e4struct, E91102, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
if ( data4->dataFile == d4 )
break ;
}
#endif
}
else
#endif /* S4OFF_TRAN */
#endif /* S4STAND_ALONE */
{
error4describe( c4, e4instance, E91102, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
}
#endif
#ifdef E4ANALYZE
if ( d4->info == 0 )
{
error4describe( c4, e4struct, E91102, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
#endif
/* verify that the desired access level is available in terms of the actual physical open */
#ifndef S4OFF_MULTI
switch( c4->accessMode )
{
case OPEN4DENY_NONE:
break ;
case OPEN4DENY_RW:
#ifdef S4CLIENT
if ( d4->accessMode != OPEN4DENY_RW )
#else
if ( d4->file.lowAccessMode != OPEN4DENY_RW )
#endif
{
error4describe( c4, e4access, E84307, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
break ;
case OPEN4DENY_WRITE:
#ifdef S4CLIENT
if ( d4->accessMode == OPEN4DENY_NONE )
#else
if ( d4->file.lowAccessMode == OPEN4DENY_NONE )
#endif
{
error4describe( c4, e4access, E84307, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
break ;
default:
{
error4describe( c4, e4access, E82502, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
}
#endif /* S4OFF_MULTI */
#ifdef S4SERVER
/* singleClient is the client's requested access mode */
if ( d4 != 0 )
if ( dfile4checkAccess( d4, c4->singleClient, c4->readOnly ) == 0 ) /* access denied */
{
error4describe( c4, e4access, E91102, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
#endif
#ifndef S4CLIENT
}
#endif
if ( d4 != 0 )
{
d4->userCount++ ;
*info = d4->info ;
#ifdef E4ANALYZE
if ( d4->nFields == 0 )
{
error4describe( c4, e4struct, E91102, dfile4name( d4 ), 0, 0 ) ;
return 0 ;
}
#endif
return d4 ;
}
return 0 ;
}
#ifdef P4ARGS_USED
#pragma argsused
#endif
DATA4FILE *dfile4open( CODE4 *c4, DATA4 *data, const char *name, char **info )
{
int rc ;
DATA4FILE *d4 ;
unsigned int count ;
int iFields ;
FIELD4IMAGE *image ;
#ifdef S4CLIENT
SOCKET4 *socket ;
CONNECTION4 *connection ;
int len2, len3 ;
CONNECTION4OPEN_INFO_IN dataIn ;
CONNECTION4OPEN_INFO_OUT *dataInfo ;
#ifndef S4OFF_INDEX
char indexName[258] ;
#endif
#else
char nameBuf[258] ;
DATA4HEADER_FULL fullHeader ;
unsigned fieldDataLen ;
#ifndef S4OFF_MEMO
int hasMemo ;
#endif
#ifndef S4OFF_CATALOG
int i ;
#endif
#endif
#ifdef S4VBASIC
if ( c4parm_check( c4, 1, E91102 ) )
return 0 ;
#endif
#ifdef E4PARM_LOW
if ( c4 == 0 || name == 0 )
{
error4( c4, e4parm_null, E91102 ) ;
return 0 ;
}
#ifdef S4CLIENT
if ( data == 0 )
{
error4( c4, e4parm_null, E91102 ) ;
return 0 ;
}
#endif
#endif
if ( error4code( c4 ) < 0 )
return 0 ;
#ifdef E4ANALYZE
if ( c4->debugInt != 0x5281 )
{
error4( 0, e4result, E81301 ) ;
return 0 ;
}
#endif
#ifdef S4CLIENT
d4 = dfile4data( c4, name ) ;
#else
u4nameCurrent( nameBuf, sizeof( nameBuf ), name ) ;
u4nameExt( nameBuf, sizeof(nameBuf), "dbf", 0 ) ;
#ifndef S4CASE_SEN /* preserve the case sensitivity for unix */
c4upper( nameBuf ) ;
#endif
d4 = dfile4data( c4, nameBuf ) ;
#endif
if ( d4 != 0 )
{
d4 = data4reopen( d4, info ) ;
if ( error4code( c4 ) < 0 )
return 0 ;
if ( d4 != 0 )
return d4 ;
}
#ifdef S4CLIENT
#ifdef E4MISC
if ( strlen( name ) > LEN4PATH )
{
error4describe( c4, e4name, E84301, name, 0, 0 ) ;
return 0 ;
}
#endif
if ( c4->defaultServer == 0 )
{
rc = code4connect( c4, 0, DEF4PROCESS_ID, 0, 0, 0 ) ;
if ( rc == 0 )
{
if ( c4->defaultServer == 0 )
{
error4describe( c4, e4connection, E84302, DEF4SERVER_ID, DEF4PROCESS_ID, 0 ) ;
return 0 ;
}
rc = code4dateFormatSet( c4, code4dateFormat( c4 ) ) ;
}
if ( rc != 0 )
{
if ( c4->defaultServer != 0 )
{
socket4initUndo( c4->defaultServer ) ;
socket4free( c4->defaultServer ) ;
c4->defaultServer = 0 ;
}
error4describe( c4, e4connection, E81001, DEF4SERVER_ID, DEF4PROCESS_ID, 0 ) ;
return 0 ;
}
}
socket = c4->defaultServer ;
memset( &dataIn, 0, sizeof( CONNECTION4OPEN_INFO_IN ) ) ;
if ( socket == 0 )
{
error4( c4, e4connection, E84303 ) ;
return 0 ;
}
connection = socket->connect ;
if ( connection == 0 )
{
error4( c4, e4connection, E84303 ) ;
return 0 ;
}
connection4assign( connection, CON4OPEN, data->trans->dataIdCount,0 ) ;
data->trans->dataIdCount++ ;
len3 = strlen( name ) + 1 ;
if ( len3 > LEN4PATH )
len3 = LEN4PATH ;
memcpy( dataIn.name, name, len3 ) ;
dataIn.name[LEN4PATH] = 0 ;
#ifdef S4OFF_MULTI
dataIn.exclusiveClient = 1 ;
#else
dataIn.accessMode = c4->accessMode ;
#endif
dataIn.readOnly = c4->readOnly ;
dataIn.safety = c4->safety ; /* for catalog */
dataIn.errDefaultUnique = c4->errDefaultUnique ;
dataIn.openForCreate = c4->openForCreate ;
dataIn.singleOpen = c4->singleOpen ;
dataIn.log = c4->log ;
connection4addData( connection, &dataIn, sizeof( CONNECTION4OPEN_INFO_IN ), 0 ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
{
error4( c4, rc, E91102 ) ;
return 0 ;
}
if ( connection4type( connection ) != CON4OPEN )
{
error4( c4, e4connection, E84304 ) ;
return 0 ;
}
rc = connection4status( connection ) ;
if ( rc < 0 )
{
if ( c4->errOpen == 0 )
error4set( c4, r4noOpen ) ;
else
connection4errorDescribe( connection, c4, rc, E91102, name, 0, 0 ) ;
return 0 ;
}
if ( connection4len( connection ) < sizeof( CONNECTION4OPEN_INFO_OUT ) )
{
error4( c4, e4connection, E84305 ) ;
return 0 ;
}
dataInfo = (CONNECTION4OPEN_INFO_OUT *)connection4data( connection ) ;
#endif /* S4CLIENT */
if ( c4->data4fileMemory == 0 )
{
c4->data4fileMemory = mem4create( c4, c4->memStartDataFile, sizeof(DATA4FILE), c4->memExpandDataFile, 0 ) ;
if ( c4->data4fileMemory == 0 )
{
error4( c4, e4memory, E91102 ) ;
return 0 ;
}
}
d4 = (DATA4FILE *)mem4alloc( c4->data4fileMemory ) ;
if ( d4 == 0 )
{
error4( c4, e4memory, E91102 ) ;
return 0 ;
}
d4->c4 = c4 ;
d4->userCount = 1 ;
#ifndef S4CLIENT
#ifndef S4OFF_MEMO
d4->memoFile.file.hand = -1 ;
#endif
#ifdef S4SERVER
#ifndef S4OFF_CATALOG
if ( cat4avail( c4->catalog ) )
{
u4ncpy( nameBuf, cat4pathName( c4->catalog ), (unsigned int)cat4pathNameLen( c4->catalog ) ) ;
for ( i = 0 ; i < cat4pathNameLen( c4->catalog ) ; i++ )
if ( nameBuf[i] == ' ' )
{
nameBuf[i] = 0 ;
break ;
}
}
#endif /* S4OFF_CATALOG */
#endif /* S4SERVER */
rc = file4open( &d4->file, c4, nameBuf, 1 ) ;
if ( rc )
{
dfile4close( d4 ) ;
return 0 ;
}
#endif
l4add( &c4->dataFileList, &d4->link ) ;
#ifdef S4CLIENT
#ifdef E4MISC
if ( strlen( name ) > sizeof( d4->accessName ) )
{
error4describe( c4, e4name, E91102, name, 0, 0 ) ;
dfile4close( d4 ) ;
return 0 ;
}
#endif
strcpy( d4->accessName, name ) ;
c4upper( d4->accessName ) ;
d4->connection = connection ;
d4->recWidth = dataInfo->recWidth ;
d4->headerLen = dataInfo->headerLen ;
d4->version = dataInfo->version ;
d4->serverId = dataInfo->serverId ;
data->readOnly = dataInfo->readOnly ;
d4->info = (char *)u4allocFree( c4, dataInfo->infoLen ) ;
if ( d4->info == 0 )
{
dfile4close( d4 ) ;
return 0 ;
}
len2 = sizeof( CONNECTION4OPEN_INFO_OUT ) ;
memcpy( d4->info, connection4data( connection ) + len2, dataInfo->infoLen ) ;
d4->infoLen = dataInfo->infoLen ;
len2 += dataInfo->infoLen ;
#ifndef S4OFF_INDEX
/* index file information... */
if ( c4->autoOpen == 1 && dataInfo->numTags > 0 )
{
u4namePiece( indexName, sizeof(indexName), name, 1, 0 ) ;
rc = client4indexSetup( c4, data, d4, dataInfo->numTags, connection4data( connection ) + len2, (unsigned int)connection4len( connection ) - len2, indexName, 0 ) ;
if ( rc < 0 )
{
dfile4close( d4 ) ;
return 0 ;
}
}
#endif
#else
if ( file4readAll( &d4->file, 0L, &fullHeader, sizeof( fullHeader ) ) < 0 )
{
dfile4close( d4 ) ;
return 0 ;
}
#ifdef S4BYTE_SWAP
fullHeader.numRecs = x4reverseLong( (void *)&fullHeader.numRecs ) ;
fullHeader.headerLen = x4reverseShort( (void *)&fullHeader.headerLen ) ;
fullHeader.recordLen = x4reverseShort( (void *)&fullHeader.recordLen ) ;
#endif
#ifdef S4DEMO
if ( fullHeader.numRecs > 200L)
{
error4( c4, e4demo, 0 ) ;
dfile4close( d4 ) ;
return 0 ;
}
#endif
if ( fullHeader.recordLen == 0 ) /* divide by zero */
{
error4describe( c4, e4data, E83805, nameBuf, dfile4name( d4 ), (char *)0 ) ;
dfile4close( d4 ) ;
return 0 ;
}
#ifndef S4CLIENT
/* if the file is opened deny write/exclusively, and this was the first open, then
verify that the record count matches the file length (i.e. to avoid
data file corruption) */
if ( c4->accessMode == OPEN4DENY_WRITE || c4->accessMode == OPEN4DENY_RW )
if ( fullHeader.numRecs != ( file4len( &d4->file ) - fullHeader.headerLen ) / fullHeader.recordLen )
{
error4describe( c4, e4data, E83805, nameBuf, dfile4name( d4 ), (char *)0 ) ;
dfile4close( d4 ) ;
return 0 ;
}
#endif
if ( fullHeader.numRecs < 0L || fullHeader.numRecs > ( 1 + ( file4len ( &d4->file ) - fullHeader.headerLen ) / fullHeader.recordLen ) )
{
error4describe( c4, e4data, E83805, nameBuf, dfile4name( d4 ), (char *)0 ) ;
dfile4close( d4 ) ;
return 0 ;
}
memcpy( (void *)&d4->version, (void *)&fullHeader.version, (4+(sizeof(S4LONG))+(sizeof(short))) ) ;
#ifdef S4FOX
data->codePage = fullHeader.codePage ;
#endif
d4->hasMdxMemo = fullHeader.hasMdxMemo ;
fieldDataLen = fullHeader.headerLen-sizeof(fullHeader) ;
if ( fullHeader.headerLen <= sizeof(fullHeader) )
{
error4describe( c4, e4data, E83805, nameBuf, dfile4name( d4 ), (char *)0 ) ;
dfile4close( d4 ) ;
return 0 ;
}
d4->info = (char *)u4allocFree( c4, (long)fieldDataLen ) ;
d4->infoLen = fieldDataLen ;
d4->headerLen = fullHeader.headerLen ;
if ( d4->info == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E91102 ) ;
#endif
dfile4close( d4 ) ;
return 0 ;
}
/* 06/18/96 AS --> fullHeader not read in prior place, must be after previous read */
#ifndef S4OFF_OPTIMIZE
file4optimizeLow( &d4->file, c4->optimize, OPT4DBF, fullHeader.recordLen, d4 ) ;
#endif
if ( file4readAll( &d4->file, (long)sizeof(fullHeader), d4->info, fieldDataLen ) < 0 )
{
error4describe( c4, e4data, E84306, name, 0, 0 ) ;
dfile4close( d4 ) ;
return 0 ;
}
if ( error4code( c4 ) < 0 )
{
dfile4close( d4 ) ;
return 0 ;
}
#ifndef S4OFF_MEMO
if ( d4->version == 0x30 ) /* visual FP 3.0 */
hasMemo = fullHeader.hasMdxMemo & 0x02 ;
else
hasMemo = d4->version & 0x80 ;
if ( hasMemo )
{
#ifdef S4MFOX
#ifdef S4CASE_SEN
u4nameExt( nameBuf, sizeof(nameBuf), "fpt", 1 ) ;
#else
u4nameExt( nameBuf, sizeof(nameBuf), "FPT", 1 ) ;
#endif
#else
#ifdef S4CASE_SEN
u4nameExt( nameBuf, sizeof(nameBuf), "dbt", 1 ) ;
#else
u4nameExt( nameBuf, sizeof(nameBuf), "DBT", 1 ) ;
#endif
#endif
if ( memo4fileOpen( &d4->memoFile, d4, nameBuf ) < 0 )
{
dfile4close( d4 ) ;
return 0 ;
}
}
#endif
#endif
d4->numRecs = -1L ;
*info = d4->info ;
/* count the number of fields */
for ( count = 0 ; d4->info[count] != 0xD ; count += 32 ) ;
d4->nFields = (int)( count / 32 ) ;
#ifdef E4ANALYZE
if ( d4->nFields == 0 )
{
error4describe( c4, e4data, E84309, name, dfile4name( d4 ), 0 ) ;
return 0 ;
}
#endif
d4->recWidth = 1 ;
d4->nFieldsMemo = 0 ;
for ( iFields = 0; iFields < d4->nFields; iFields++ )
{
image = (FIELD4IMAGE *)(((char *)*info) + iFields * 32 ) ;
switch( image->type )
{
case r4memo:
case r4gen:
d4->nFieldsMemo++ ;
d4->recWidth += image->len ;
break ;
case r4num:
case r4float:
case r4log:
case r4date:
d4->recWidth += image->len ;
break ;
case r4str:
d4->recWidth += ( image->len + (image->dec << 8) ) ;
break ;
case r4double: /* r4bin and r4double the same */
if ( d4->version == 0x30 )
{
d4->recWidth += image->len ;
if ( d4->version != 0x30 ) /* 2.5 data files disallowed these fields */
{
dfile4close( d4 ) ;
#ifdef S4SERVER
error4describe( c4, e4data, E80501, nameBuf, dfile4name( d4 ), 0 ) ;
#else
error4describe( c4, e4data, E80501, name, dfile4name( d4 ), 0 ) ;
#endif
return 0 ;
}
}
else
{
d4->nFieldsMemo++ ;
d4->recWidth += image->len ;
}
break ;
#ifdef S4CLIENT_OR_FOX
case r4currency:
case r4int:
case r4dateTime:
d4->recWidth += image->len ;
if ( d4->version != 0x30 ) /* 2.5 data files disallowed these fields */
{
dfile4close( d4 ) ;
#ifdef S4SERVER
error4describe( c4, e4data, E80501, nameBuf, dfile4name( d4 ), 0 ) ;
#else
error4describe( c4, e4data, E80501, name, dfile4name( d4 ), 0 ) ;
#endif
return 0 ;
}
break ;
case r4system: /* null-fields/system field */
if ( ( d4->version != 0x30 ) || ( memcmp( image->name, "_NullFlags", 10 ) != 0 ) ) /* not visual FP 3.0 */
{
dfile4close( d4 ) ;
#ifdef S4SERVER
error4describe( c4, e4data, E80501, nameBuf, dfile4name( d4 ), 0 ) ;
#else
error4describe( c4, e4data, E80501, name, dfile4name( d4 ), 0 ) ;
#endif
}
d4->recWidth += image->len ;
break ;
#endif
default:
dfile4close( d4 ) ;
#ifdef S4SERVER
error4describe( c4, e4data, E80501, nameBuf, dfile4name( d4 ), 0 ) ;
#else
error4describe( c4, e4data, E80501, name, dfile4name( d4 ), 0 ) ;
#endif
return 0 ;
}
}
#ifdef S4SERVER
if ( d4->recWidth != fullHeader.recordLen )
{
dfile4close( d4 ) ;
error4describe( c4, e4data, E91102, nameBuf, dfile4name( d4 ), 0 ) ;
return 0 ;
}
#endif
#ifdef S4CLIENT
d4->accessMode = c4->accessMode ;
#else
d4->valid = 1 ; /* valid, so low closes will leave open. */
#endif
return d4 ;
}
#ifdef S4VB_DOS
DATA4 * d4open_v( CODE4 *c4, char *name )
{
return d4open( c4, c4str(name) ) ;
}
#endif