/* d4create.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */ #include "d4all.h" #ifdef __TURBOC__ #pragma hdrstop #endif /* __TUROBC__ */ #ifndef S4OFF_WRITE DATA4 *S4FUNCTION d4createTemp( CODE4 *c4, const FIELD4INFO *fieldData, const TAG4INFO *tagInfo ) { int oldTemp ; DATA4 *data ; #ifdef S4VBASIC if ( c4parm_check( c4, 1, E91401 ) ) return 0 ; #endif /* S4VBASIC */ #ifdef E4PARM_HIGH if ( c4 == 0 || fieldData == 0 ) { error4( c4, e4parm_null, E91401 ) ; return 0 ; } #endif oldTemp = c4->createTemp ; c4->createTemp = 1 ; data = d4create( c4, (char *)0, fieldData, tagInfo ) ; c4->createTemp = oldTemp ; if ( data == 0 ) { #ifdef E4STACK error4stack( c4, e4data, E91401 ) ; #endif return 0 ; } return data ; } #ifndef S4CLIENT #ifdef P4ARGS_USED #pragma argsused #endif static void d4createClose( CODE4 *c4, DATA4 *d4 ) { #ifndef S4OFF_TRAN int oldStatus ; #endif if ( d4 == 0 ) return ; #ifdef S4OFF_TRAN d4close( d4 ) ; #else oldStatus = code4tranStatus( c4 ) ; code4tranStatusSet( c4, r4off ) ; d4close( d4 ) ; code4tranStatusSet( c4, oldStatus ) ; #endif } #endif DATA4 *S4FUNCTION d4create( CODE4 *c4, const char *name, const FIELD4INFO *fieldData, const TAG4INFO *tagInfo ) { #ifdef S4CLIENT SOCKET4 *socket ; CONNECTION4 *connection ; CONNECTION4CREATE_INFO_IN dataIn ; CONNECTION4FIELD_INFO finfo ; CONNECTION4TAG_INFO tinfo ; CONNECTION4UNIQUE_INFO_IN uniqueInfoIn ; CONNECTION4UNIQUE_TAG_INFO uniqueTagInfo ; unsigned int len, len2, len3, offset, j ; int oldAccessMode ; #else int oldReadOnly ; #ifndef S4OFF_TRAN int saveStatus ; #endif #endif char nameBuf[258] ; int rc, i, oldAutoOpen ; DATA4FILE *d4 ; DATA4 *data ; TAG4 *tag ; #ifdef S4VBASIC if ( c4parm_check( c4, 1, E91401 ) ) return 0 ; #endif /* S4VBASIC */ #ifdef E4PARM_HIGH if ( c4 == 0 || fieldData == 0 ) { error4( c4, e4parm_null, E91401 ) ; return 0 ; } if ( name == 0 && c4->createTemp != 1 ) { error4( c4, e4parm_null, E91401 ) ; return 0 ; } #endif if ( error4code( c4 ) < 0 ) return 0 ; #ifdef E4ANALYZE if ( c4->debugInt != 0x5281 ) { error4( c4, e4info, E81301 ) ; return 0 ; } #endif #ifdef S4STAND_ALONE #ifndef S4OFF_TRAN if ( c4->logOpen ) /* open now so that can turn off during create */ { rc = code4logOpen( c4, 0, 0 ) ; if ( rc < 0 ) return 0 ; else error4set( c4, 0 ) ; /* remove r4open if it already existed */ } #endif #endif if ( c4->createTemp == 1 ) { #ifndef S4OFF_CATALOG if ( cat4avail( c4->catalog ) == 1 ) c4->catalog->valid = 0 ; #endif } else { #ifdef S4CLIENT d4 = dfile4data( c4, name ) ; #else u4nameCurrent( nameBuf, sizeof( nameBuf ), name ) ; u4nameExt( nameBuf, sizeof( nameBuf ), "dbf", 0 ) ; #ifndef S4CASE_SEN c4upper(nameBuf); #endif d4 = dfile4data( c4, nameBuf ) ; #endif if ( d4 != 0 ) { error4describe( c4, e4create, E81304, name, (char *)0, (char *)0 ) ; return 0 ; } } #ifdef S4CLIENT if ( c4->defaultServer == 0 ) { rc = code4connect( c4, 0, DEF4PROCESS_ID, 0, 0, 0 ) ; if ( rc == 0 ) { if ( c4->defaultServer == 0 ) { error4( c4, e4connection, E84302 ) ; return 0 ; } rc = code4dateFormatSet( c4, code4dateFormat( c4 ) ) ; } if ( rc != 0 ) { if ( c4->defaultServer != 0 ) { socket4initUndo( c4->defaultServer ) ; socket4free( c4->defaultServer ) ; c4->defaultServer = 0 ; } return 0 ; } } socket = c4->defaultServer ; if ( socket == 0 ) { error4( c4, e4connection, E81303 ) ; return 0 ; } connection = socket->connect ; #ifdef E4ANALYZE if ( connection == 0 ) { error4( c4, e4connection, E91401 ) ; return 0 ; } #endif connection4assign( connection, CON4CREATE, 0, 0 ) ; memset( &dataIn, 0, sizeof( dataIn ) ) ; /* avoids requiring memsets for name and zero assigns */ if ( c4->createTemp == 1 ) { dataIn.createTemp = 1 ; dataIn.log = LOG4TRANS ; } else dataIn.log = c4->log ; dataIn.safety = c4->safety ; dataIn.readOnly = c4->readOnly ; /* catalog purposes */ dataIn.compatibility = c4->compatibility ; if ( name != 0 ) { #ifdef E4MISC if ( strlen( name ) > LEN4PATH ) error4describe( c4, e4create, E84301, name, (char *)0, (char *)0 ) ; #endif strncpy( dataIn.name, name, LEN4PATH ) ; } if ( tagInfo == 0 ) i = 0 ; else for( i = 0 ; tagInfo[i].name != 0; i++ ) ; dataIn.numTags = i ; for( i = 0 ; fieldData[i].name != 0; i++ ) ; dataIn.numFields = i ; len = 0 ; for ( j = 0 ; j != dataIn.numFields ; j++ ) { len += sizeof( CONNECTION4FIELD_INFO ) ; len += strlen( fieldData[j].name ) + 1 ; } dataIn.fieldInfoLen = len ; connection4addData( connection, &dataIn, sizeof(CONNECTION4CREATE_INFO_IN), 0 ) ; offset = sizeof( CONNECTION4CREATE_INFO_IN ) ; for ( j = 0 ; j != dataIn.numFields ; j++ ) { len = strlen( fieldData[j].name ) + 1 ; finfo.name.offset = offset + sizeof(CONNECTION4FIELD_INFO) ; finfo.type = fieldData[j].type ; finfo.len = fieldData[j].len ; finfo.dec = fieldData[j].dec ; finfo.nulls = fieldData[j].nulls ; connection4addData( connection, &finfo, sizeof(CONNECTION4FIELD_INFO), 1 ) ; connection4addData( connection, fieldData[j].name, len, 0 ) ; offset += ( len + sizeof( CONNECTION4FIELD_INFO ) ) ; } for ( j = 0 ; j != dataIn.numTags ; j++ ) { len = strlen( tagInfo[j].name ) + 1 ; offset += sizeof( CONNECTION4TAG_INFO ) ; tinfo.name.offset = offset ; len2 = strlen( tagInfo[j].expression ) + 1 ; offset += len ; tinfo.expression.offset = offset ; offset += len2 ; if ( tagInfo[j].filter == 0 ) { len3 = 0 ; tinfo.filter.offset = 0 ; } else { len3 = strlen( tagInfo[j].filter ) + 1 ; tinfo.filter.offset = offset ; } offset += len3 ; tinfo.unique = tagInfo[j].unique ; tinfo.descending = tagInfo[j].descending ; connection4addData( connection, &tinfo, sizeof(CONNECTION4TAG_INFO), 1 ) ; connection4addData( connection, tagInfo[j].name, len, 0 ) ; connection4addData( connection, tagInfo[j].expression, len2, 0 ) ; if ( len3 != 0 ) connection4addData( connection, tagInfo[j].filter, len3, 0 ) ; } connection4send( connection ) ; rc = connection4receive( connection ) ; if ( rc < 0 ) { #ifdef E4STACK error4stack( c4, rc, E91401 ) ; #endif return 0 ; } if ( connection4type( connection ) != CON4CREATE ) { #ifdef E4STACK error4stack( c4, e4connection, E91401 ) ; #endif return 0 ; } rc = connection4status( connection ) ; if ( rc != 0 ) { if ( c4->errCreate == 0 ) error4set( c4, r4noCreate ) ; else connection4errorDescribe( connection, c4, rc, E91401, name, 0, 0 ) ; return 0 ; } oldAutoOpen = c4->autoOpen ; if ( tagInfo == 0 ) c4->autoOpen = 0 ; else { if ( tagInfo[0].name == 0 ) c4->autoOpen = 0 ; else c4->autoOpen = 1 ; } if ( c4->createTemp == 0 ) { if ( connection4len( connection ) != 0 ) { c4->autoOpen = oldAutoOpen ; #ifdef E4STACK error4stack( c4, e4packetLen, E91401 ) ; #endif return 0 ; } if ( dataIn.numTags == 0 ) c4->openForCreate = 2 ; else c4->openForCreate = 1 ; data = d4open( c4, name ) ; c4->openForCreate = 0 ; } else { oldAccessMode = c4->accessMode ; c4->accessMode = OPEN4DENY_RW ; if ( name == 0 ) { if ( connection4len( connection ) > sizeof( nameBuf ) + 1 ) { c4->accessMode = oldAccessMode ; c4->autoOpen = oldAutoOpen ; error4( c4, e4packetLen, E91401 ) ; return 0 ; } memcpy( nameBuf, connection4data( connection ), (unsigned int)connection4len( connection ) ) ; nameBuf[connection4len( connection )] = 0 ; if ( dataIn.numTags == 0 ) c4->openForCreate = 2 ; else c4->openForCreate = 1 ; data = d4open( c4, nameBuf ) ; c4->openForCreate = 0 ; } else { if ( dataIn.numTags == 0 ) c4->openForCreate = 2 ; else c4->openForCreate = 1 ; data = d4open( c4, name ) ; c4->openForCreate = 0 ; } c4->accessMode = oldAccessMode ; } c4->autoOpen = oldAutoOpen ; if ( data == 0 ) return 0 ; /* set the unique settings... */ code4indexFormat( c4 ) ; /* need to call this to avoid corruption in d4tag() call below which asks this question calling the server destroying com struct */ uniqueInfoIn.numTags = dataIn.numTags ; connection4assign( connection, CON4UNIQUE_SET, data4clientId( data ), data4serverId( data ) ) ; connection4addData( connection, &uniqueInfoIn, sizeof(CONNECTION4UNIQUE_INFO_IN), 0 ) ; for ( j = 0 ; j != dataIn.numTags ; j++ ) { if ( tagInfo[j].unique == c4->errDefaultUnique ) uniqueInfoIn.numTags-- ; else { tag = d4tag( data, tagInfo[j].name ) ; if ( tag == 0 ) { rc = error4describe( data->codeBase, e4name, E81406, d4alias( data ), tagInfo[j].name, 0 ) ; break ; } uniqueTagInfo.unique = tagInfo[j].unique ; tag->errUnique = tagInfo[j].unique ; memcpy( uniqueTagInfo.alias, tag->tagFile->alias, LEN4TAG_ALIAS ) ; connection4addData( connection, &uniqueTagInfo, sizeof(CONNECTION4UNIQUE_TAG_INFO), 1 ) ; } } connection4send( connection ) ; rc = connection4receive( connection ) ; if ( rc == 0 ) { rc = connection4status( connection ) ; if ( rc < 0 ) connection4error( connection, c4, rc, E91401 ) ; } if ( rc < 0 ) { d4close( data ) ; return 0 ; } return data ; #else if ( c4->createTemp == 1 ) { data = 0 ; rc = dfile4create( c4, name, fieldData, tagInfo, &data ) ; if ( rc < 0 ) { d4createClose( c4, data ) ; return 0 ; } } else { #ifndef S4OFF_TRAN saveStatus = code4tranStatus( c4 ) ; code4tranStatusSet( c4, r4off ) ; #endif oldReadOnly = c4->readOnly ; c4->readOnly = 0 ; rc = dfile4create( c4, name, fieldData, tagInfo, 0 ) ; c4->readOnly = oldReadOnly ; #ifndef S4OFF_TRAN if ( saveStatus != 0 ) /* which may have resulted in transaction enabling when file created, so leave */ code4tranStatusSet( c4, saveStatus ) ; #endif if ( rc < 0 ) { #ifdef E4STACK error4stack( c4, (short)rc, E91401 ) ; #endif return 0 ; } if ( rc != 0 ) return 0 ; oldAutoOpen = c4->autoOpen ; if ( tagInfo == 0 ) c4->autoOpen = 0 ; else { if ( tagInfo[0].name == 0 ) c4->autoOpen = 0 ; else /* make sure on */ c4->autoOpen = 1 ; } data = d4open( c4, name ) ; c4->autoOpen = oldAutoOpen ; if ( data == 0 ) return 0 ; } /* set the unique settings... */ if ( tagInfo != 0 ) for ( i = 0 ; tagInfo[i].name != 0 ; i++ ) { tag = d4tag( data, tagInfo[i].name ) ; if ( tag == 0 ) { error4describe( data->codeBase, e4name, E81406, d4alias( data ), tagInfo[i].name, 0 ) ; return data ; } tag->errUnique = tagInfo[i].unique ; } return data ; #endif } #ifndef S4CLIENT #ifndef S4OFF_MEMO #ifndef CREATE4MEMO_EXT #ifdef S4MFOX #define CREATE4MEMO_EXT "fpt" #else #define CREATE4MEMO_EXT "mdx" #endif #endif #endif int dfile4create( CODE4 *c4, const char *name, const FIELD4INFO *fieldData, const TAG4INFO *tagInfo, DATA4 **temp ) { unsigned int nFlds ; int i, rc, oldAutoOpen, tempFreeSet, oldCT2 ; #ifndef S4OFF_MULTI int oldAccessMode ; #endif #ifndef S4OFF_MEMO int hasMemo ; #endif long calcRecordLen, lheaderLen ; char buf[258], buffer[0x800] ; FILE4SEQ_WRITE seqWrite ; DATA4 *data ; DATA4HEADER_FULL createHeader ; DATA4FILE *dfile ; FIELD4IMAGE createFieldImage ; FILE4 file ; char *tempName ; unsigned int len ; #ifdef S4CLIPPER #ifndef S4OFF_INDEX char nameBuf[258] ; #endif #endif #ifdef E4MISC int dec ; #endif #ifndef S4OFF_MEMO int isMemo, oldCreateTemp ; MEMO4FILE m4file ; #endif #ifdef S4SERVER int oldKeepOpen ; #endif #ifndef S4OFF_TRAN int oldStatus = 0 ; #endif #ifdef S4FOX int hasNulls = 0 ; #endif #ifdef S4VBASIC if ( c4parm_check( c4, 1, E91102 ) ) return -1 ; #endif /* S4VBASIC */ #ifdef E4PARM_LOW if ( c4 == 0 || fieldData == 0 ) return error4( c4, e4parm_null, E91102 ) ; if ( name == 0 && c4->createTemp != 1 ) return error4( c4, e4parm_null, E91102 ) ; #endif if ( error4code( c4 ) < 0 ) return e4codeBase ; if ( name != 0 ) { u4nameCurrent( buf, sizeof( buf ), name ) ; u4nameExt( buf, sizeof(buf), "dbf", 0 ) ; /* an unused dfile may be removed to allow re-create */ #ifndef S4CASE_SEN c4upper( buf ) ; #endif dfile = dfile4data( c4, buf ) ; if ( dfile != 0 ) { rc = dfile4closeLow( dfile ) ; if ( rc < 0 ) return error4stack( c4, (short)rc, E91102 ) ; dfile = dfile4data( c4, buf ) ; if ( dfile != 0 ) /* datafile already open -- can't create */ return error4describe( c4, e4create, E81304, buf, (char *)0, (char *)0 ) ; } } #ifndef S4OFF_MEMO isMemo = 0 ; #endif calcRecordLen = 1L ; nFlds = 0 ; for ( ; fieldData[nFlds].name ; nFlds++ ) { #ifdef S4FOX if ( c4->compatibility == 30 ) if ( fieldData[nFlds].nulls == r4null ) hasNulls++ ; #endif #ifndef S4OFF_MEMO if ( fieldData[nFlds].type == r4memo || fieldData[nFlds].type == r4gen #ifndef S4FOX || fieldData[nFlds].type == r4bin #endif ) isMemo = 1 ; #endif switch( fieldData[nFlds].type ) { case r4num: case r4float: case r4str: #ifndef S4FOX case r4bin: #endif calcRecordLen += fieldData[nFlds].len ; break ; case r4memo: case r4gen: #ifdef S4OFF_MEMO #ifdef E4MISC return error4( c4, e4notMemo, E91102 ) ; #endif #else #ifdef S4FOX if ( c4->compatibility == 30 ) calcRecordLen += 4 ; else #endif calcRecordLen += 10 ; break ; #endif case r4date: calcRecordLen += 8 ; break ; case r4log: calcRecordLen += 1 ; break ; #ifdef S4FOX case r4memoBin: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; calcRecordLen += 4 ; break ; case r4charBin: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; calcRecordLen += fieldData[nFlds].len ; break ; case r4currency: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; calcRecordLen += 8 ; break ; case r4dateTime: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; calcRecordLen += 8 ; break ; case r4double: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; calcRecordLen += 8 ; break ; case r4int: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; calcRecordLen += 4 ; break ; #endif default: return error4( c4, e4data, E81404 ) ; } } if ( calcRecordLen >= USHRT_MAX ) /* Increment for deletion flag. */ { if ( name == 0 ) return error4( c4, e4recordLen, E81407 ) ; else return error4describe( c4, e4recordLen, E91102, name, 0, 0 ) ; } lheaderLen = (long)nFlds * 32 + 34 ; #ifdef S4FOX if ( c4->compatibility == 30 ) if ( hasNulls > 0 ) /* extra field for null settings */ { lheaderLen += 32 ; calcRecordLen += (hasNulls+7)/8 ; } #endif if ( lheaderLen >= USHRT_MAX ) { if ( name == 0 ) return error4( c4, e4recordLen, E81408 ) ; else return error4describe( c4, e4create, E81405, name, 0, 0 ) ; } tempFreeSet = 0 ; tempName = 0 ; if ( name != 0 ) { #ifdef S4SERVER #ifndef S4OFF_CATALOG if ( c4->createTemp != 1 && cat4avail( c4->catalog ) ) { u4ncpy( buf, cat4pathName( c4->catalog ), (unsigned int)cat4pathNameLen( c4->catalog ) ) ; for ( i = 0 ; i < cat4pathNameLen( c4->catalog ) ; i++ ) if ( buf[i] == ' ' ) { buf[i] = 0 ; break ; } } #endif /* S4OFF_CATALOG */ #endif /* S4SERVER */ if ( c4->createTemp == 1 ) /* take care of setting as temp later */ { c4->createTemp = 0 ; rc = file4create( &file, c4, buf, 1 ) ; c4->createTemp = 1 ; } else rc = file4create( &file, c4, buf, 1 ) ; } else { oldCT2 = c4->createTemp ; c4->createTemp = 0 ; rc = file4tempLow( &file, c4, 0 ) ; /* need to set as non-remove to get name input */ c4->createTemp = oldCT2 ; if ( rc == 0 ) { file.isTemp = 1 ; if ( file.name != 0 ) { len = strlen( file.name ) ; if ( len > sizeof( buf ) + 1 ) len = sizeof( buf ) - 1 ; memcpy( buf, file.name, len ) ; buf[len] = 0 ; tempName = file.nameBuf ; } #ifdef E4DEBUG else { file4close( &file ) ; error4( c4, e4info, E91102 ) ; } #endif tempFreeSet = 1 ; } } if ( rc < 0 ) return error4stack( c4, (short)rc, E91102 ) ; if ( rc != 0 ) /* maybe r4create */ return rc ; rc = file4seqWriteInit( &seqWrite, &file, 0L, buffer, sizeof(buffer) ) ; if ( rc < 0 ) { file4close( &file ) ; return error4stack( c4, (short)rc, E91102 ) ; } /* Write the header */ memset( (void *)&createHeader, 0, sizeof(createHeader) ) ; #ifdef S4FOX if ( c4->compatibility == 30 ) /* 3.0 file */ { createHeader.version = 0x30 ; #ifndef S4OFF_MEMO if ( isMemo ) createHeader.hasMdxMemo |= 0x02 ; #endif } else { #ifndef S4OFF_MEMO if ( isMemo ) createHeader.version = (char)0xF5 ; else #endif createHeader.version = (char)0x03 ; } #else #ifndef S4OFF_MEMO if ( isMemo ) #ifdef S4MNDX createHeader.version = (char)0x83 ; #endif /* S4MNDX */ #ifdef S4MMDX createHeader.version = (char)0x8B ; #endif /* S4MMDX */ else #endif /* S4OFF_MEMO */ createHeader.version = (char)0x03 ; #endif /* S4FOX */ u4yymmdd( &createHeader.yy ) ; createHeader.headerLen = (unsigned short)(32*(nFlds+1) + 1) ; #ifdef S4FOX if ( c4->compatibility == 30 ) /* 3.0 file */ { if ( hasNulls > 0 ) /* extra field for null settings */ createHeader.headerLen += 32 ; createHeader.headerLen += 263 ; /* visual fox reserves an extra 263 bytes */ } #endif createHeader.recordLen = (unsigned short)calcRecordLen ; #ifdef S4FOX createHeader.codePage = (char)c4->codePage ; /* write codepage stamp */ #endif #ifdef S4BYTE_SWAP createHeader.numRecs = x4reverseLong( (void *)&createHeader.numRecs ) ; createHeader.headerLen = x4reverseShort( (void *)&createHeader.headerLen ) ; createHeader.recordLen = x4reverseShort( (void *)&createHeader.recordLen ) ; #endif /* S4BYTE_SWAP */ rc = file4seqWrite( &seqWrite, (char *) &createHeader, sizeof(createHeader) ) ; if ( rc < 0 ) { file4seqWriteFlush( &seqWrite ) ; file4close( &file ) ; return error4stack( c4, (short)rc, E91102 ) ; } #ifdef S4FOX calcRecordLen = 1L ; #endif for ( i = 0; i < (int)nFlds; i++ ) { memset( (void *)&createFieldImage, 0, sizeof(createFieldImage) ) ; u4ncpy( createFieldImage.name, fieldData[i].name, sizeof(createFieldImage.name)); c4trimN( createFieldImage.name, sizeof(createFieldImage.name) ) ; c4upper( createFieldImage.name ) ; createFieldImage.type = (char)fieldData[i].type ; c4upper( &createFieldImage.type ) ; #ifdef S4FOX createFieldImage.offset = (short)calcRecordLen ; calcRecordLen += fieldData[i].len ; if ( fieldData[i].nulls == r4null ) createFieldImage.nullBinary |= 0x02 ; #endif switch( createFieldImage.type ) { case r4str: createFieldImage.len = (unsigned char)(fieldData[i].len & 0xFF) ; createFieldImage.dec = (unsigned char)(fieldData[i].len>>8) ; break ; #ifndef S4OFF_MEMO case r4memo: case r4gen: #ifndef S4FOX case r4bin: #endif #ifdef S4FOX if ( c4->compatibility == 30 ) /* 3.0 file */ createFieldImage.len = 4 ; else createFieldImage.len = 10 ; #else createFieldImage.len = 10 ; #endif createFieldImage.dec = 0 ; break ; #endif case r4date: createFieldImage.len = 8 ; createFieldImage.dec = 0 ; break ; case r4log: createFieldImage.len = 1 ; createFieldImage.dec = 0 ; break ; case r4num: case r4float: createFieldImage.len = (unsigned char)fieldData[i].len ; createFieldImage.dec = (unsigned char)fieldData[i].dec ; #ifdef E4MISC len = fieldData[i].len ; dec = fieldData[i].dec ; if ( ( len > F4MAX_NUMERIC || len < 1 || len <= 2 && dec != 0 || dec < 0 ) || ( (unsigned int)dec > len - F4DECIMAL_OFFSET && dec > 0 ) || ( dec > F4MAX_DECIMAL ) ) return error4( c4, e4data, E81404 ) ; #endif break ; #ifdef S4FOX case r4charBin: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; createFieldImage.type = r4str ; createFieldImage.len = (unsigned char)(fieldData[i].len & 0xFF) ; createFieldImage.dec = (unsigned char)(fieldData[i].len>>8) ; createFieldImage.nullBinary |= 0x04 ; break ; case r4memoBin: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; createFieldImage.type = r4memo ; createFieldImage.dec = 0 ; createFieldImage.len = 4 ; createFieldImage.nullBinary |= 0x04 ; break ; case r4currency: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; createFieldImage.len = 8 ; createFieldImage.dec = 4 ; createFieldImage.nullBinary |= 0x04 ; break ; case r4dateTime: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; createFieldImage.len = 8 ; createFieldImage.dec = 0 ; createFieldImage.nullBinary |= 0x04 ; break ; case r4int: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; createFieldImage.len = 4 ; createFieldImage.dec = 0 ; createFieldImage.nullBinary |= 0x04 ; break ; case r4double: if ( c4->compatibility != 30 ) return error4( c4, e4data, E81404 ) ; createFieldImage.len = 8 ; createFieldImage.dec = (unsigned char)fieldData[i].dec ; createFieldImage.nullBinary |= 0x04 ; break ; #endif default: return error4( c4, e4data, E81404 ) ; } rc = file4seqWrite( &seqWrite, &createFieldImage, sizeof(createFieldImage) ) ; if ( rc < 0 ) break ; } #ifdef S4FOX if ( rc == 0 ) if ( hasNulls > 0 ) /* need to add the special field */ { memset( (void *)&createFieldImage, 0, sizeof(createFieldImage) ) ; u4ncpy( createFieldImage.name, "_NullFlags", sizeof(createFieldImage.name)); c4trimN( createFieldImage.name, sizeof(createFieldImage.name) ) ; createFieldImage.offset = (short)calcRecordLen ; createFieldImage.type = r4system ; createFieldImage.nullBinary = 0x05 ; createFieldImage.len = (hasNulls+7)/8 ; /* 1 byte for every 8 nulls */ createFieldImage.dec = 0 ; rc = file4seqWrite( &seqWrite, &createFieldImage, sizeof(createFieldImage) ) ; } #endif if ( rc == 0 ) { #ifdef S4FOX if ( c4->compatibility == 30 ) /* 3.0 file */ { rc = file4seqWriteRepeat( &seqWrite, 1, '\015' ) ; if ( rc == 0 ) rc = file4seqWriteRepeat( &seqWrite, 263, '\0' ) ; } else rc = file4seqWrite( &seqWrite, "\015\032", 2 ) ; #else rc = file4seqWrite( &seqWrite, "\015\032", 2 ) ; #endif } file4seqWriteFlush( &seqWrite ) ; if ( rc == 0 && tempFreeSet == 1 ) { file.doAllocFree = 0 ; file.isTemp = 0 ; } file4close( &file ) ; if ( rc < 0 ) return error4stack( c4, (short)rc, E91102 ) ; #ifndef S4OFF_MEMO hasMemo = 0 ; #ifdef S4FOX if ( c4->compatibility == 30 ) { if ( createHeader.hasMdxMemo & 0x02 ) hasMemo = 1 ; } else if ( createHeader.version & 0x80 ) hasMemo = 1 ; #else if ( createHeader.version & 0x80 ) hasMemo = 1 ; #endif if ( hasMemo ) { oldCreateTemp = c4->createTemp ; c4->createTemp = 0 ; if ( name == 0 ) rc = memo4fileCreate( &m4file, c4, 0, tempName ) ; else { u4nameExt( buf, sizeof(buf), CREATE4MEMO_EXT, 1 ) ; rc = memo4fileCreate( &m4file, c4, 0, buf ) ; } c4->createTemp = oldCreateTemp ; if ( rc == 0 ) file4close( &m4file.file ) ; } #endif if ( rc < 0 ) { if ( tempFreeSet == 1 && tempName != 0 ) u4free( tempName ) ; return error4stack( c4, (short)rc, E91102 ) ; } oldAutoOpen = c4->autoOpen ; #ifndef S4OFF_MULTI oldAccessMode = c4->accessMode ; c4->accessMode = OPEN4DENY_RW ; #endif if ( tagInfo == 0 ) c4->autoOpen = 0 ; else { if ( tagInfo[0].name == 0 ) c4->autoOpen = 0 ; } #ifdef S4CLIPPER c4->autoOpen = 0 ; #endif #ifndef S4OFF_TRAN if ( name == 0 || c4->createTemp == 1 ) { oldStatus = code4tranStatus( c4 ) ; code4tranStatusSet( c4, r4off ) ; } #endif if ( name == 0 ) data = d4open( c4, tempName ) ; else data = d4open( c4, name ) ; if ( tempFreeSet == 1 && tempName != 0 ) u4free( tempName ) ; if ( name == 0 || c4->createTemp == 1 ) { #ifndef S4OFF_TRAN code4tranStatusSet( c4, oldStatus ) ; #endif if ( data != 0 ) { if ( tempFreeSet == 1 ) if ( data->dataFile->file.name != 0 ) data->dataFile->file.doAllocFree = 1 ; data->dataFile->file.isTemp = 1 ; #ifndef S4OFF_TRAN data->logVal = LOG4TRANS ; #endif #ifndef S4OFF_MEMO if ( createHeader.version & 0x80 ) if ( c4->createTemp == 1 ) { #ifdef E4ANALYZE if ( data->dataFile->memoFile.file.hand <= 0 ) error4( 0, e4struct, E91102 ) ; #endif data->dataFile->memoFile.file.isTemp = 1 ; } #endif } } c4->autoOpen = oldAutoOpen ; if ( data == 0 ) error4( c4, e4open, E91102 ) ; else { #ifdef S4SERVER data->accessMode = OPEN4DENY_RW ; #endif #ifdef S4OFF_INDEX #ifdef E4MISC if ( tagInfo ) error4( c4, e4notIndex, E91102 ) ; #endif #else if ( tagInfo ) #ifdef S4CLIPPER if ( name == 0 ) { if ( i4create( data, 0, tagInfo ) == 0 ) if ( c4->errorCode >= 0 ) error4( c4, e4create, E91102 ) ; } else { /* 03/06/96 AS --> fix #25 changes.60 */ u4namePiece( nameBuf, sizeof( nameBuf ), name, 1, 0 ) ; if ( i4create( data, nameBuf, tagInfo ) == 0 ) if ( c4->errorCode >= 0 ) error4( c4, e4create, E91102 ) ; } #else if ( i4create( data, 0, tagInfo ) == 0 ) if ( c4->errorCode >= 0 ) error4( c4, e4create, E91102 ) ; #endif #endif } #ifndef S4OFF_MULTI c4->accessMode = oldAccessMode ; #endif rc = error4code( c4 ) ; if ( rc < 0 || data == 0 ) d4createClose( c4, data ) ; else { if ( c4->createTemp != 1 ) { dfile = data->dataFile ; #ifdef S4SERVER oldKeepOpen = c4->server->keepOpen ; c4->server->keepOpen = 1 ; #endif d4createClose( c4, data ) ; #ifdef S4SERVER c4->server->keepOpen = oldKeepOpen ; /* the server case requires an explict low close as well */ dfile4closeLow( dfile ) ; #endif } else *temp = data ; } return error4code( c4 ) ; } #endif /* not S4CLIENT */ #endif /* S4OFF_WRITE */ #ifdef S4VB_DOS DATA4 *d4create_v ( CODE4 *c4 , char *name, FIELD4INFO *f4, TAG4INFO *t4 ) { return d4create( c4, c4str(name), f4, t4 ) ; } DATA4 *d4createData ( CODE4 *c4, char *name, FIELD4INFO *f4 ) { return d4create( c4, c4str(name), f4, 0 ) ; } #endif