1498 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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
 | |
| 
 |