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
 | 
						|
 |