2006-04-15 20:20 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/include/Makefile
  + harbour/include/blob.ch
  * harbour/include/dbinfo.ch
  * harbour/include/hbdbferr.h
  * harbour/include/hbrddfpt.h
  * harbour/source/rdd/dbf1.c
  * harbour/source/rdd/workarea.c
  * harbour/source/rdd/dbffpt/dbffpt1.c
    + added all CL5.3 BLOB*() functions support
    + added new RDD DBFBLOB compatible with CL5.3 DBFBLOB
      It operates on memo files only (.dbv) without tables (.dbf)
      To create .DBV file use:
         dbCreate( cFile, {}, "DBFBLOB" )

  * harbour/source/rdd/dbcmd.c
    * do not report error when empty structure table is passed to DBCREATE()
      CL5.3 allow to create even DBF files without any fields and because
      I can imagine some valid code which use it as a feature then I also
      allow it in DBF RDD.
      Authors of RDDs which do not allow to create tables without fields
      should add to their low level RDD code necessary RT error.
This commit is contained in:
Przemyslaw Czerpak
2006-04-15 18:51:38 +00:00
parent 3498a9c55b
commit 8bc1e2f652
10 changed files with 868 additions and 248 deletions

View File

@@ -7,6 +7,30 @@
For example:
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
*/
* fixed bug in ParseOptional
* bin/bld.sh
* fixed typo
* source/pp/ppcore.c
* fixed bug in ParseOptional
<"var"> were not recognized correctly
(This fixes SET RELATION bug reported by David Macias)
2006-04-15 20:20 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/Makefile
+ harbour/include/blob.ch
* harbour/include/dbinfo.ch
* harbour/include/hbdbferr.h
* harbour/include/hbrddfpt.h
* harbour/source/rdd/dbf1.c
* harbour/source/rdd/workarea.c
* harbour/source/rdd/dbffpt/dbffpt1.c
+ added all CL5.3 BLOB*() functions support
+ added new RDD DBFBLOB compatible with CL5.3 DBFBLOB
It operates on memo files only (.dbv) without tables (.dbf)
To create .DBV file use:
dbCreate( cFile, {}, "DBFBLOB" )

View File

@@ -57,6 +57,7 @@ PRG_HEADERS=\
assert.ch \
box.ch \
button.ch \
blob.ch \
color.ch \
common.ch \
dbedit.ch \

83
harbour/include/blob.ch Normal file
View File

@@ -0,0 +1,83 @@
/*
* $Id$
*/
/*
* Harbour Project source code:
* Header file for the RDD API Index OrderInfo and DBInfo support
*
* Copyright 2004 {list of individual authors and e-mail addresses}
* www - http://www.xharbour.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#ifndef HB_BLOB_CH_
#define HB_BLOB_CH_
#ifndef HB_DBINFO_CH
#include "dbinfo.ch"
#endif
#xtranslate BLOBRootLock() => dbInfo( DBI_BLOB_ROOT_LOCK )
#xtranslate BLOBRootUnlock() => dbInfo( DBI_BLOB_ROOT_UNLOCK )
#xtranslate BLOBRootGet() => dbInfo( DBI_BLOB_ROOT_GET )
#xtranslate BLOBRootPut( <xBlob> ) => dbInfo( DBI_BLOB_ROOT_PUT, <xBlob> )
#xtranslate BLOBRootDelete() => BLOBRootPut( "" )
#xtranslate BLOBDirectExport( <nPointer>, <cTargetFile> [, <kMode>] ) => ;
dbInfo( DBI_BLOB_DIRECT_EXPORT, { <nPointer>, <cTargetFile>, ;
iif( <.kMode.>, <kMode>, BLOB_EXPORT_OVERWRITE ) } )
#xtranslate BLOBDirectGet( <nPointer> [, <nStart> [, <nCount> ]] ) => ;
dbInfo( DBI_BLOB_DIRECT_GET, { <nPointer>, <nStart>, <nCount> } )
#xtranslate BLOBDirectImport( <nOldPointer>, <cSourceFile> ) => ;
dbInfo( DBI_BLOB_DIRECT_IMPORT, { <nOldPointer>, <cSourceFile> } )
#xtranslate BLOBDirectPut( [<nOldPointer>], <xBlob> ) => ;
dbInfo( DBI_BLOB_DIRECT_PUT, { <nOldPointer>, <xBlob> } )
#xtranslate BLOBGet( <nFieldNo> [, <nStart> [, <nCount>]] ) => ;
dbFieldInfo( DBS_BLOB_GET, <nFieldNo>, { <nStart>, <nCount> } )
#xtranslate BLOBExport( <nFieldNo>, <cTargetFile>, <nMode> ) => ;
dbFileGet( <nFieldNo>, <cTargetFile>, <nMode> )
#xtranslate BLOBImport( <nFieldNo>, <cSourceFile> ) => ;
dbFilePut( <nFieldNo>, <cSourceFile> )
#endif /* HB_BLOB_CH_ */

View File

@@ -99,7 +99,7 @@
#define RDDI_MEMOGCTYPE 34 /* type of garbage collector used by GC */
#define RDDI_MEMOREADLOCK 35 /* use read lock in memo file access */
#define RDDI_MEMOREUSE 36 /* reuse free space on write */
#define RDDI_BLOB_SUPPORT 37 /* can support BLOB files directly */
/*
Constants for SELF_ORDINFO ()

View File

@@ -56,6 +56,7 @@
HB_EXTERN_BEGIN
/* DBF errors */
#define EDBF_UNSUPPORTED 1000
#define EDBF_OPEN_DBF 1001
#define EDBF_OPEN_MEMO 1002
#define EDBF_OPEN_INDEX 1003

View File

@@ -66,6 +66,7 @@ HB_EXTERN_BEGIN
#define DBT_MEMOEXT ".dbt"
#define FPT_MEMOEXT ".fpt"
#define SMT_MEMOEXT ".smt"
#define DBV_MEMOEXT ".dbv"
#define DBT_DEFBLOCKSIZE 512
#define FPT_DEFBLOCKSIZE 64
#define SMT_DEFBLOCKSIZE 32
@@ -73,6 +74,8 @@ HB_EXTERN_BEGIN
#define FPT_LOCKPOS 0x00000000L
#define FPT_LOCKSIZE 0x00000001L
#define FPT_ROOTBLOCK_OFFSET 0x218 /* Clipper 5.3 ROOT data block offset */
#define SIX_ITEM_BUFSIZE 14
#define FLEX_ITEM_BUFSIZE 8
#define MAX_SIXFREEBLOCKS 82
@@ -177,6 +180,7 @@ HB_EXTERN_BEGIN
#define FPTIT_FLEXAR_LONG2 0x20 /* long[4], len, dec */
#define FPTIT_FLEXAR_ULONG2 0x21 /* ulong[4], len, dec */
/* MEMO file strucutres */
typedef struct _FPTHEADER
{

View File

@@ -1741,7 +1741,17 @@ HB_FUNC( DBCREATE )
fKeepOpen = ISLOG( 4 );
fCurrArea = fKeepOpen && !hb_parl( 4 );
if( !pStruct || hb_arrayLen( pStruct ) == 0 ||
/*
* Clipper allows to use empty struct array for RDDs which does not
* support fields, f.e.: DBFBLOB in CL5.3
* In CL5.3 it's also possible to create DBF file without fields.
* if some RDD wants to block it then they should serve it in lower
* level, [druzus]
*/
if( !pStruct ||
#ifdef HB_C52_STRICT
hb_arrayLen( pStruct ) == 0 ||
#endif
!szFileName || !szFileName[ 0 ] )
{
hb_errRT_DBCMD( EG_ARG, EDBCMD_DBCMDBADPARAMETER, NULL, "DBCREATE" );

View File

@@ -228,8 +228,11 @@ static ULONG hb_dbfCalcRecCount( DBFAREAP pArea )
{
HB_TRACE(HB_TR_DEBUG, ("hb_dbfCalcRecCount(%p)", pArea));
return ( ULONG ) ( ( hb_fsSeekLarge( pArea->hDataFile, 0, FS_END ) -
pArea->uiHeaderLen ) / pArea->uiRecordLen );
if( pArea->hDataFile == FS_ERROR )
return 0;
else
return ( ULONG ) ( ( hb_fsSeekLarge( pArea->hDataFile, 0, FS_END ) -
pArea->uiHeaderLen ) / pArea->uiRecordLen );
}
/*
@@ -1928,8 +1931,11 @@ static ERRCODE hb_dbfSetFieldExtent( DBFAREAP pArea, USHORT uiFieldExtent )
return FAILURE;
/* Alloc field offsets array */
pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT * ) );
memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT * ) );
if( uiFieldExtent )
{
pArea->pFieldOffset = ( USHORT * ) hb_xgrab( uiFieldExtent * sizeof( USHORT * ) );
memset( pArea->pFieldOffset, 0, uiFieldExtent * sizeof( USHORT * ) );
}
return SUCCESS;
}
@@ -2019,9 +2025,9 @@ static ERRCODE hb_dbfClose( DBFAREAP pArea )
*/
static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
{
ERRCODE errCode;
ERRCODE errCode = SUCCESS;
USHORT uiSize, uiCount;
BOOL fRetry, fError;
BOOL fRetry, fError, fRawBlob;
DBFFIELD * pBuffer, *pThisField;
PHB_FNAME pFileName;
PHB_ITEM pItem = NULL, pError;
@@ -2036,8 +2042,6 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
SELF_INFO( ( AREAP ) pArea, DBI_TABLEEXT, pItem );
pFileName->szExtension = hb_itemGetCPtr( pItem );
hb_fsFNameMerge( ( char * ) szFileName, pFileName );
hb_itemRelease( pItem );
pItem = NULL;
}
else
{
@@ -2045,48 +2049,52 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
}
hb_xfree( pFileName );
pError = NULL;
/* Try create */
do
pItem = hb_itemPutL( pItem, FALSE );
fRawBlob = SELF_RDDINFO( SELF_RDDNODE( pArea ), RDDI_BLOB_SUPPORT, 0, pItem ) == SUCCESS &&
hb_itemGetL( pItem );
if( !fRawBlob )
{
pArea->hDataFile = hb_fsExtOpen( szFileName, NULL,
FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE |
FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
NULL, pError );
pError = NULL;
/* Try create */
do
{
pArea->hDataFile = hb_fsExtOpen( szFileName, NULL,
FO_READWRITE | FO_EXCLUSIVE | FXO_TRUNCATE |
FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
NULL, pError );
if( pArea->hDataFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CREATE );
hb_errPutSubCode( pError, EDBF_CREATE_DBF );
hb_errPutOsCode( pError, hb_fsError() );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) );
hb_errPutFileName( pError, ( char * ) szFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
}
fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
fRetry = FALSE;
} while( fRetry );
if( pError )
{
hb_itemRelease( pError );
}
if( pArea->hDataFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CREATE );
hb_errPutSubCode( pError, EDBF_CREATE_DBF );
hb_errPutOsCode( pError, hb_fsError() );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CREATE ) );
hb_errPutFileName( pError, ( char * ) szFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
}
fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
if( pItem )
hb_itemRelease( pItem );
return FAILURE;
}
else
fRetry = FALSE;
} while( fRetry );
if( pError )
{
hb_itemRelease( pError );
}
if( pArea->hDataFile == FS_ERROR )
{
return FAILURE;
}
pArea->szDataFileName = hb_strdup( ( char * ) szFileName );
uiSize = pArea->uiFieldCount * sizeof( DBFFIELD );
pBuffer = ( DBFFIELD * ) hb_xgrab( uiSize );
memset( pBuffer, 0, uiSize );
pThisField = pBuffer;
/* Size for deleted flag */
pArea->uiRecordLen = 1;
@@ -2117,7 +2125,7 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
}
}
if( pArea->bTableType == DB_DBF_VFP )
if( pArea->bTableType == DB_DBF_VFP && !fRawBlob )
{
pArea->bMemoType = DB_MEMO_FPT;
}
@@ -2140,6 +2148,18 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
hb_itemRelease( pItem );
}
uiSize = pArea->uiFieldCount * sizeof( DBFFIELD );
if( pArea->uiFieldCount )
{
pBuffer = ( DBFFIELD * ) hb_xgrab( uiSize );
memset( pBuffer, 0, uiSize );
}
else
{
pBuffer = NULL;
}
pThisField = pBuffer;
pArea->fHasMemo = fError = FALSE;
for( uiCount = 0; uiCount < pArea->uiFieldCount; uiCount++ )
@@ -2253,7 +2273,6 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
hb_errPutFileName( pError, ( char * ) pCreateInfo->abName );
SELF_ERROR( ( AREAP ) pArea, pError );
hb_itemRelease( pError );
return FAILURE;
}
pThisField++ ;
@@ -2263,6 +2282,10 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
pArea->ulRecCount = 0;
pArea->uiHeaderLen = sizeof( DBFHEADER ) + uiSize +
( pArea->bTableType == DB_DBF_VFP ? 1 : 2 );
if( fRawBlob )
{
pArea->fHasMemo = TRUE;
}
if( !pArea->fHasMemo )
{
pArea->bMemoType = DB_MEMO_NONE;
@@ -2280,31 +2303,37 @@ static ERRCODE hb_dbfCreate( DBFAREAP pArea, LPDBOPENINFO pCreateInfo )
pArea->cdPage = hb_cdp_page;
#endif
/* Force write new header */
pArea->fUpdateHeader = TRUE;
/* Write header */
errCode = SELF_WRITEDBHEADER( ( AREAP ) pArea );
if( errCode != SUCCESS )
if( !fRawBlob )
{
hb_xfree( pBuffer );
SELF_CLOSE( ( AREAP ) pArea );
return errCode;
}
/* Force write new header */
pArea->fUpdateHeader = TRUE;
/* Write header */
errCode = SELF_WRITEDBHEADER( ( AREAP ) pArea );
if( errCode != SUCCESS )
{
if( pBuffer )
hb_xfree( pBuffer );
SELF_CLOSE( ( AREAP ) pArea );
return errCode;
}
/* Write fields and eof mark */
if( hb_fsWrite( pArea->hDataFile, ( BYTE * ) pBuffer, uiSize ) != uiSize ||
( pArea->bTableType == DB_DBF_VFP ?
hb_fsWrite( pArea->hDataFile, ( BYTE * ) "\r\032", 2 ) != 2 :
hb_fsWrite( pArea->hDataFile, ( BYTE * ) "\r\0\032", 3 ) != 3 ) )
{
/* TODO: add RT error */
hb_xfree( pBuffer );
SELF_CLOSE( ( AREAP ) pArea );
return FAILURE;
}
/* Write fields and eof mark */
if( hb_fsWrite( pArea->hDataFile, ( BYTE * ) pBuffer, uiSize ) != uiSize ||
( pArea->bTableType == DB_DBF_VFP ?
hb_fsWrite( pArea->hDataFile, ( BYTE * ) "\r\032", 2 ) != 2 :
hb_fsWrite( pArea->hDataFile, ( BYTE * ) "\r\0\032", 3 ) != 3 ) )
{
/* TODO: add RT error */
if( pBuffer )
hb_xfree( pBuffer );
SELF_CLOSE( ( AREAP ) pArea );
return FAILURE;
}
pArea->fDataFlush = TRUE;
hb_xfree( pBuffer );
pArea->fDataFlush = TRUE;
if( pBuffer )
hb_xfree( pBuffer );
}
/* Create memo file */
if( pArea->fHasMemo )
@@ -2375,10 +2404,6 @@ static ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
pArea->dbfHeader.bDay );
break;
case DBI_GETDELIMITER:
case DBI_SETDELIMITER:
break;
case DBI_GETRECSIZE:
hb_itemPutNL( pItem, pArea->uiRecordLen );
break;
@@ -2413,7 +2438,7 @@ static ERRCODE hb_dbfInfo( DBFAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
break;
case DBI_MEMOHANDLE:
hb_itemPutNL( pItem, (LONG)pArea->hMemoFile );
hb_itemPutNL( pItem, ( LONG ) pArea->hMemoFile );
break;
case DBI_SHARED:
@@ -2727,8 +2752,8 @@ static ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo )
{
ERRCODE errCode;
USHORT uiFlags, uiFields, uiSize, uiCount;
BOOL fRetry;
PHB_ITEM pError, pFileExt;
BOOL fRetry, fRawBlob;
PHB_ITEM pError, pFileExt, pItem;
PHB_FNAME pFileName;
BYTE * pBuffer;
LPDBFFIELD pField;
@@ -2798,126 +2823,143 @@ static ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo )
}
hb_xfree( pFileName );
/* Try open */
do
pItem = hb_itemPutL( NULL, FALSE );
fRawBlob = SELF_RDDINFO( SELF_RDDNODE( pArea ), RDDI_BLOB_SUPPORT, 0, pItem ) == SUCCESS &&
hb_itemGetL( pItem );
hb_itemRelease( pItem );
if( fRawBlob )
{
pArea->hDataFile = hb_fsExtOpen( szFileName, NULL, uiFlags |
FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
NULL, pError );
uiFields = 0;
pBuffer = NULL;
pArea->fHasMemo = TRUE;
}
else
{
/* Try open */
do
{
pArea->hDataFile = hb_fsExtOpen( szFileName, NULL, uiFlags |
FXO_DEFAULTS | FXO_SHARELOCK | FXO_COPYNAME,
NULL, pError );
if( pArea->hDataFile == FS_ERROR )
{
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_OPEN );
hb_errPutSubCode( pError, EDBF_OPEN_DBF );
hb_errPutOsCode( pError, hb_fsError() );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) );
hb_errPutFileName( pError, ( char * ) szFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
}
fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
fRetry = FALSE;
} while( fRetry );
if( pError )
{
hb_itemRelease( pError );
pError = NULL;
}
/* Exit if error */
if( pArea->hDataFile == FS_ERROR )
{
if( !pError )
SELF_CLOSE( ( AREAP ) pArea );
return FAILURE;
}
/* Allocate only after succesfully open file */
pArea->szDataFileName = hb_strdup( ( char * ) szFileName );
/* Read file header and exit if error */
errCode = SELF_READDBHEADER( ( AREAP ) pArea );
if( errCode != SUCCESS )
{
SELF_CLOSE( ( AREAP ) pArea );
return errCode;
}
/* Add fields */
uiFields = ( pArea->uiHeaderLen - sizeof( DBFHEADER ) ) / sizeof( DBFFIELD );
uiSize = uiFields * sizeof( DBFFIELD );
pBuffer = uiFields ? ( BYTE * ) hb_xgrab( uiSize ) : NULL;
/* Read fields and exit if error */
do
{
hb_fsSeek( pArea->hDataFile, sizeof( DBFHEADER ), FS_SET );
if( hb_fsRead( pArea->hDataFile, pBuffer, uiSize ) != uiSize )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_OPEN );
hb_errPutSubCode( pError, EDBF_OPEN_DBF );
hb_errPutOsCode( pError, hb_fsError() );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_OPEN ) );
hb_errPutFileName( pError, ( char * ) szFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
errCode = FAILURE;
if( !pError )
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CORRUPTION );
hb_errPutSubCode( pError, EDBF_CORRUPT );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CORRUPTION ) );
hb_errPutFileName( pError, pArea->szDataFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
}
fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
fRetry = FALSE;
} while( fRetry );
if( pError )
{
hb_itemRelease( pError );
pError = NULL;
}
/* Exit if error */
if( pArea->hDataFile == FS_ERROR )
{
SELF_CLOSE( ( AREAP ) pArea );
return FAILURE;
}
/* Allocate only after succesfully open file */
pArea->szDataFileName = hb_strdup( ( char * ) szFileName );
/* Read file header and exit if error */
errCode = SELF_READDBHEADER( ( AREAP ) pArea );
if( errCode != SUCCESS )
{
SELF_CLOSE( ( AREAP ) pArea );
return errCode;
}
/* Add fields */
uiFields = ( pArea->uiHeaderLen - sizeof( DBFHEADER ) ) / sizeof( DBFFIELD );
uiSize = uiFields * sizeof( DBFFIELD );
pBuffer = ( BYTE * ) hb_xgrab( uiSize );
/* Read fields and exit if error */
do
{
hb_fsSeek( pArea->hDataFile, sizeof( DBFHEADER ), FS_SET );
if( hb_fsRead( pArea->hDataFile, pBuffer, uiSize ) != uiSize )
{
errCode = FAILURE;
if( !pError )
else
{
pError = hb_errNew();
hb_errPutGenCode( pError, EG_CORRUPTION );
hb_errPutSubCode( pError, EDBF_CORRUPT );
hb_errPutDescription( pError, hb_langDGetErrorDesc( EG_CORRUPTION ) );
hb_errPutFileName( pError, pArea->szDataFileName );
hb_errPutFlags( pError, EF_CANRETRY | EF_CANDEFAULT );
errCode = SUCCESS;
break;
}
fRetry = ( SELF_ERROR( ( AREAP ) pArea, pError ) == E_RETRY );
}
else
{
errCode = SUCCESS;
break;
}
} while( fRetry );
} while( fRetry );
if( pError )
{
hb_itemRelease( pError );
}
/* Exit if error */
if( errCode != SUCCESS )
{
hb_xfree( pBuffer );
SELF_CLOSE( ( AREAP ) pArea );
return errCode;
}
/* some RDDs use the additional space in the header after field arrray
for private data we should check for 0x0D marker to not use this
data as fields description */
for( uiCount = 0; uiCount < uiFields; uiCount++ )
{
if( pBuffer[ uiCount * sizeof( DBFFIELD ) ] == 0x0d )
{
uiFields = uiCount;
break;
}
/* Peter added it for FVP DBFs but in wrong place,
anyhow I cannot see why it's necessary, FVP private data
in header should be after 0x0d - I disabled this code, [druzus] */
/*
if( pArea->bTableType == DB_DBF_VFP &&
pBuffer[ uiCount * sizeof( DBFFIELD ) ] == 0x00 )
{
uiFields = uiCount;
break;
}
*/
if( pError )
{
hb_itemRelease( pError );
}
/* Exit if error */
if( errCode != SUCCESS )
{
if( pBuffer )
hb_xfree( pBuffer );
SELF_CLOSE( ( AREAP ) pArea );
return errCode;
}
/* some RDDs use the additional space in the header after field arrray
for private data we should check for 0x0D marker to not use this
data as fields description */
for( uiCount = 0; uiCount < uiFields; uiCount++ )
{
if( pBuffer[ uiCount * sizeof( DBFFIELD ) ] == 0x0d )
{
uiFields = uiCount;
break;
}
/* Peter added it for FVP DBFs but in wrong place,
anyhow I cannot see why it's necessary, FVP private data
in header should be after 0x0d - I disabled this code, [druzus] */
/*
if( pArea->bTableType == DB_DBF_VFP &&
pBuffer[ uiCount * sizeof( DBFFIELD ) ] == 0x00 )
{
uiFields = uiCount;
break;
}
*/
}
}
/* CL5.3 allow to create and open DBFs without fields */
#ifdef HB_C52_STRICT
if( uiFields == 0 )
{
errCode = FAILURE;
}
else
#endif
{
errCode = SELF_SETFIELDEXTENT( ( AREAP ) pArea, uiFields );
if( errCode != SUCCESS )
@@ -3030,7 +3072,8 @@ static ERRCODE hb_dbfOpen( DBFAREAP pArea, LPDBOPENINFO pOpenInfo )
if( errCode != SUCCESS )
break;
}
hb_xfree( pBuffer );
if( pBuffer )
hb_xfree( pBuffer );
/* Exit if error */
if( errCode != SUCCESS )

View File

@@ -77,6 +77,9 @@
# include "hbapicdp.h"
#endif
static USHORT s_uiRddIdBLOB = ( USHORT ) -1;
static USHORT s_uiRddIdFPT = ( USHORT ) -1;
static RDDFUNCS fptSuper;
static RDDFUNCS fptTable =
{
@@ -258,8 +261,11 @@ static ERRCODE hb_memoErrorRT( FPTAREAP pArea, USHORT uiGenCode, USHORT uiSubCod
}
static char * hb_memoDefaultFileExt( int iType )
static char * hb_memoDefaultFileExt( int iType, USHORT uiRdd )
{
if( uiRdd == s_uiRddIdBLOB )
return DBV_MEMOEXT;
switch( iType )
{
case DB_MEMO_DBT:
@@ -326,6 +332,82 @@ static BOOL hb_fptFileUnLock( FPTAREAP pArea )
return !pArea->fShared || hb_fsLock( pArea->hMemoFile, FPT_LOCKPOS, FPT_LOCKSIZE, FL_UNLOCK );
}
/*
* Check if MEMO file has direct access to data
*/
static BOOL hb_fptHasDirectAccess( FPTAREAP pArea )
{
return pArea->bMemoType == DB_MEMO_FPT &&
( pArea->uiMemoVersion == DB_MEMOVER_FLEX ||
pArea->uiMemoVersion == DB_MEMOVER_CLIP );
}
/*
* Lock root block pointer.
*/
static BOOL hb_fptRootBlockLock( FPTAREAP pArea )
{
BOOL fRet;
if ( !pArea->fShared )
fRet = TRUE;
else
fRet = hb_fsLock( pArea->hMemoFile, FPT_ROOTBLOCK_OFFSET, 4,
FL_LOCK | FLX_EXCLUSIVE );
return fRet;
}
/*
* Unlock root block pointer.
*/
static BOOL hb_fptRootBlockUnLock( FPTAREAP pArea )
{
return !pArea->fShared ||
hb_fsLock( pArea->hMemoFile, FPT_ROOTBLOCK_OFFSET, 4, FL_UNLOCK );
}
/*
* Read root block pointer.
*/
static ERRCODE hb_fptGetRootBlock( FPTAREAP pArea, ULONG * pulBlock )
{
*pulBlock = 0;
if( hb_fptHasDirectAccess( pArea ) )
{
BYTE buffer[ 4 ];
hb_fsSeek( pArea->hMemoFile, FPT_ROOTBLOCK_OFFSET, FS_SET );
if( hb_fsRead( pArea->hMemoFile, buffer, 4 ) == 4 )
{
*pulBlock = HB_GET_LE_UINT32( buffer );
return SUCCESS;
}
else
return EDBF_READ;
}
return EDBF_UNSUPPORTED;
}
/*
* Write root block pointer.
*/
static ERRCODE hb_fptPutRootBlock( FPTAREAP pArea, ULONG ulBlock )
{
if( hb_fptHasDirectAccess( pArea ) )
{
BYTE buffer[ 4 ];
HB_PUT_LE_UINT32( buffer, ulBlock );
hb_fsSeek( pArea->hMemoFile, FPT_ROOTBLOCK_OFFSET, FS_SET );
if( hb_fsWrite( pArea->hMemoFile, buffer, 4 ) == 4 )
return SUCCESS;
else
return EDBF_WRITE;
}
return EDBF_UNSUPPORTED;
}
/*
GARBAGE COLLECTOR:
I don't have any documentation about it. All I know is reverse engineering
@@ -988,7 +1070,7 @@ static ULONG hb_fptGetMemoLen( FPTAREAP pArea, USHORT uiIndex )
HB_TRACE(HB_TR_DEBUG, ("hb_fptGetMemoLen(%p, %hu)", pArea, uiIndex));
if( hb_dbfGetMemoData( ( DBFAREAP ) pArea, uiIndex, &ulBlock, &ulSize,
if( hb_dbfGetMemoData( ( DBFAREAP ) pArea, uiIndex - 1, &ulBlock, &ulSize,
&ulType ) == SUCCESS )
{
if( ulBlock != 0 )
@@ -1034,7 +1116,7 @@ static char * hb_fptGetMemoType( FPTAREAP pArea, USHORT uiIndex )
HB_TRACE(HB_TR_DEBUG, ("hb_fptGetMemoLen(%p, %hu)", pArea, uiIndex));
if( hb_dbfGetMemoData( ( DBFAREAP ) pArea, uiIndex, &ulBlock, &ulSize,
if( hb_dbfGetMemoData( ( DBFAREAP ) pArea, uiIndex - 1, &ulBlock, &ulSize,
&ulType ) == SUCCESS )
{
if( ulBlock != 0 )
@@ -2450,17 +2532,31 @@ ERRCODE hb_fptReadSMTBlock( FPTAREAP pArea, PHB_ITEM pItem, ULONG ulBlock, ULONG
/*
* Read fpt vartype memos.
*/
static ERRCODE hb_fptGetMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem, FHANDLE hFile )
static ERRCODE hb_fptGetMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem,
FHANDLE hFile, ULONG ulBlock, ULONG ulStart,
ULONG ulCount )
{
ERRCODE errCode;
ULONG ulBlock, ulSize, ulBufSize, ulType;
ULONG ulSize, ulType;
BYTE * pBuffer, * bMemoBuf;
FPTBLOCK fptBlock;
HB_TRACE(HB_TR_DEBUG, ("hb_fptGetMemo(%p, %hu, %p, %p)", pArea, uiIndex, pItem));
HB_TRACE(HB_TR_DEBUG, ("hb_fptGetMemo(%p, %hu, %p, %p, %lu, %lu)", pArea, uiIndex, pItem, hFile, ulStart, ulCount));
errCode = hb_dbfGetMemoData( ( DBFAREAP ) pArea, uiIndex,
&ulBlock, &ulSize, &ulType );
if( uiIndex )
{
errCode = hb_dbfGetMemoData( ( DBFAREAP ) pArea, uiIndex - 1,
&ulBlock, &ulSize, &ulType );
}
else if( ! hb_fptHasDirectAccess( pArea ) )
{
errCode = EDBF_UNSUPPORTED;
}
else
{
ulSize = ulType = 0;
errCode = SUCCESS;
}
if( errCode != SUCCESS )
return errCode;
@@ -2478,7 +2574,6 @@ static ERRCODE hb_fptGetMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem, FH
}
ulType = HB_GET_BE_UINT32( fptBlock.type );
ulSize = HB_GET_BE_UINT32( fptBlock.size );
ulBufSize = HB_MAX( ulSize + 1, 8 );
}
else
{
@@ -2489,22 +2584,52 @@ static ERRCODE hb_fptGetMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem, FH
}
hb_fsSeekLarge( pArea->hMemoFile, ( HB_FOFFSET ) ulBlock *
( HB_FOFFSET ) pArea->uiMemoBlockSize, FS_SET );
ulBufSize = ulSize + 1;
}
if( ulStart || ulCount )
{
if( pArea->bMemoType == DB_MEMO_FPT )
{
if( ulType != FPTIT_TEXT && ulType != FPTIT_PICT )
ulStart = ulCount = 0;
}
else if( pArea->bMemoType == DB_MEMO_SMT )
{
if( ulType != SMT_IT_CHAR )
ulStart = ulCount = 0;
}
}
if( ulStart >= ulSize )
ulSize = 0;
else
ulSize -= ulStart;
if( ulCount && ulCount < ulSize )
ulSize = ulCount;
if( ulStart && ulSize )
hb_fsSeekLarge( pArea->hMemoFile, ( HB_FOFFSET ) ulStart, FS_RELATIVE );
if( hFile != FS_ERROR )
{
return hb_fptExportToFile( pArea, hFile, ulSize );
}
pBuffer = ( BYTE * ) hb_xalloc( ulBufSize );
if( pArea->bMemoType == DB_MEMO_FPT )
{
pBuffer = ( BYTE * ) hb_xalloc( HB_MAX( ulSize + 1, 8 ) );
if( pBuffer )
memset( pBuffer, '\0', 8 );
}
else
{
pBuffer = ( BYTE * ) hb_xalloc( ulSize + 1 );
}
if( !pBuffer )
{
/* in most cases this means that file is corrupted */
return EDBF_CORRUPT;
}
if( pArea->bMemoType == DB_MEMO_FPT )
memset( pBuffer, '\0', 8 );
if ( ulSize != 0 && hb_fsReadLarge( pArea->hMemoFile, pBuffer, ulSize ) != ulSize )
{
@@ -2764,16 +2889,17 @@ static ERRCODE hb_fptWriteMemo( FPTAREAP pArea, ULONG ulBlock, ULONG ulSize,
/*
* Assign a value to the specified memo field.
*/
static ERRCODE hb_fptPutMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
static ERRCODE hb_fptPutMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem,
ULONG * pulBlock )
{
ULONG ulSize, ulBlock, ulType, ulOldSize, ulOldType, ulArrayCount = 0;
ULONG ulBlock, ulSize, ulType, ulOldSize, ulOldType, ulArrayCount = 0;
BYTE itmBuffer[FLEX_ITEM_BUFSIZE];
BYTE *bBufPtr = NULL, *bBufAlloc = NULL;
ERRCODE errCode;
HB_LONG iVal;
LONG lVal;
HB_TRACE(HB_TR_DEBUG, ("hb_fptPutMemo(%p, %hu, %p)", pArea, uiIndex, pItem));
HB_TRACE(HB_TR_DEBUG, ("hb_fptPutMemo(%p, %hu, %p, %p)", pArea, uiIndex, pItem, pulBlock));
if( HB_IS_STRING( pItem ) )
{
@@ -2905,8 +3031,22 @@ static ERRCODE hb_fptPutMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
return EDBF_DATATYPE;
}
errCode = hb_dbfGetMemoData( (DBFAREAP) pArea, uiIndex,
&ulBlock, &ulOldSize, &ulOldType );
if( uiIndex )
{
errCode = hb_dbfGetMemoData( (DBFAREAP) pArea, uiIndex - 1,
&ulBlock, &ulOldSize, &ulOldType );
}
else if( !pulBlock || ! hb_fptHasDirectAccess( pArea ) )
{
errCode = EDBF_UNSUPPORTED;
}
else
{
ulBlock = *pulBlock;
ulOldSize = ulOldType = 0;
errCode = SUCCESS;
}
if( errCode == SUCCESS )
errCode = hb_fptWriteMemo( pArea, ulBlock, ulOldSize, bBufPtr, FS_ERROR,
ulType, ulSize, &ulBlock );
@@ -2917,8 +3057,12 @@ static ERRCODE hb_fptPutMemo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
}
if( errCode == SUCCESS )
hb_dbfSetMemoData( (DBFAREAP) pArea, uiIndex, ulBlock, ulSize, ulType );
{
if( uiIndex )
hb_dbfSetMemoData( (DBFAREAP) pArea, uiIndex - 1, ulBlock, ulSize, ulType );
else
*pulBlock = ulBlock;
}
return errCode;
}
@@ -3172,7 +3316,7 @@ static ERRCODE hb_fptGetVarField( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem
if( uiError != SUCCESS )
return uiError;
uiError = hb_fptGetMemo( pArea, uiIndex - 1, pItem, hFile );
uiError = hb_fptGetMemo( pArea, uiIndex, pItem, hFile, 0, 0, 0 );
}
else if( hFile == FS_ERROR )
{
@@ -3189,6 +3333,92 @@ static ERRCODE hb_fptGetVarField( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem
return uiError;
}
static ERRCODE hb_fptGetVarFile( FPTAREAP pArea, ULONG ulBlock, BYTE * szFile, USHORT uiMode )
{
USHORT uiError;
FHANDLE hFile;
HB_TRACE(HB_TR_DEBUG, ("hb_fptGetVarFile(%p, %lu, %s, %hu)", pArea, ulBlock, szFile, uiMode));
hFile = hb_fsExtOpen( szFile, NULL, FO_WRITE | FO_EXCLUSIVE |
FXO_DEFAULTS | FXO_SHARELOCK |
( uiMode == FILEGET_APPEND ?
FXO_APPEND : FXO_TRUNCATE ),
NULL, NULL );
if( hFile == FS_ERROR )
{
uiError = uiMode != FILEGET_APPEND ? EDBF_CREATE : EDBF_OPEN_DBF;
}
else
{
hb_fsSeekLarge( hFile, 0, FS_END );
uiError = hb_fptGetMemo( pArea, 0, NULL, hFile, ulBlock, 0, 0 );
hb_fsClose( hFile );
}
/* Exit if any error */
if( uiError != SUCCESS )
{
if( uiError != FAILURE )
{
hb_memoErrorRT( pArea, 0, uiError,
uiError == EDBF_OPEN_DBF || uiError == EDBF_CREATE ||
uiError == EDBF_WRITE ? ( char * ) szFile :
pArea->szMemoFileName, 0, 0 );
}
return FAILURE;
}
return SUCCESS;
}
static ULONG hb_fptPutVarFile( FPTAREAP pArea, ULONG ulBlock, BYTE * szFile )
{
USHORT uiError;
FHANDLE hFile;
HB_TRACE(HB_TR_DEBUG, ("hb_fptPutVarFile(%p, %lu, %s)", pArea, ulBlock, szFile));
hFile = hb_fsExtOpen( szFile, NULL, FO_READ | FO_DENYNONE |
FXO_DEFAULTS | FXO_SHARELOCK, NULL, NULL );
if( hFile == FS_ERROR )
{
uiError = EDBF_OPEN_DBF;
}
else
{
ULONG ulSize;
HB_FOFFSET size = hb_fsSeekLarge( hFile, 0, FS_END );
hb_fsSeekLarge( hFile, 0, FS_SET );
if( ( HB_FOFFSET ) ( size & 0xFFFFFFFFUL ) == size )
ulSize = HB_MIN( ( ULONG ) size, 0xFFFFFFFFUL - sizeof( FPTBLOCK ) );
else
ulSize = HB_MIN( size, ( HB_FOFFSET ) ( 0xFFFFFFFFUL - sizeof( FPTBLOCK ) ) );
if( hb_fptFileLockEx( pArea, TRUE ) )
{
uiError = hb_fptWriteMemo( pArea, ulBlock, 0, NULL, hFile,
0, ulSize, &ulBlock );
hb_fptFileUnLock( pArea );
}
else
{
uiError = EDBF_LOCK;
}
hb_fsClose( hFile );
}
if( uiError != SUCCESS )
{
hb_memoErrorRT( pArea, 0, uiError,
uiError == EDBF_OPEN_DBF || uiError == EDBF_READ ?
( char * ) szFile : pArea->szMemoFileName, 0, 0 );
ulBlock = 0;
}
return ulBlock;
}
static ERRCODE hb_fptPutVarField( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
{
LPFIELD pField;
@@ -3223,7 +3453,7 @@ static ERRCODE hb_fptPutVarField( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem
{
if( !hb_fptFileLockEx( pArea, TRUE ) )
return EDBF_LOCK;
uiError = hb_fptPutMemo( pArea, uiIndex -1, pItem );
uiError = hb_fptPutMemo( pArea, uiIndex, pItem, NULL );
#if defined( HB_MEMO_SAFELOCK )
if( uiError == SUCCESS )
{
@@ -3462,7 +3692,7 @@ static ERRCODE hb_fptGetVarLen( FPTAREAP pArea, USHORT uiIndex, ULONG * pLength
uiError = hb_fptLockForRead( pArea, uiIndex, &fUnLock );
if( uiError == SUCCESS )
*pLength = hb_fptGetMemoLen( pArea, uiIndex - 1 );
*pLength = hb_fptGetMemoLen( pArea, uiIndex );
else
*pLength = 0;
@@ -3644,6 +3874,10 @@ static ERRCODE hb_fptCreateMemFile( FPTAREAP pArea, LPDBOPENINFO pCreateInfo )
{
strcpy( ( char *) fptHeader.signature2, "FlexFile3\003" );
ulSize = sizeof( FPTHEADER );
if( pArea->rddID == s_uiRddIdBLOB )
{
HB_PUT_LE_UINT16( fptHeader.flexSize, pArea->uiMemoBlockSize );
}
}
}
ulNextBlock = ( ulSize + pArea->uiMemoBlockSize - 1 ) / pArea->uiMemoBlockSize;
@@ -3740,9 +3974,14 @@ static ERRCODE hb_fptOpenMemFile( FPTAREAP pArea, LPDBOPENINFO pOpenInfo )
HB_TRACE(HB_TR_DEBUG, ("hb_fptOpenMemFile(%p, %p)", pArea, pOpenInfo));
if( pArea->bMemoType != DB_MEMO_DBT &&
pArea->bMemoType != DB_MEMO_FPT &&
pArea->bMemoType != DB_MEMO_SMT )
if( pArea->rddID == s_uiRddIdBLOB )
{
pArea->bMemoType = DB_MEMO_FPT;
pArea->uiMemoVersion = DB_MEMOVER_FLEX;
}
else if( pArea->bMemoType != DB_MEMO_DBT &&
pArea->bMemoType != DB_MEMO_FPT &&
pArea->bMemoType != DB_MEMO_SMT )
{
hb_memoErrorRT( pArea, EG_OPEN, EDBF_MEMOTYPE,
( char * ) pOpenInfo->abName, 0, 0 );
@@ -3815,9 +4054,13 @@ static ERRCODE hb_fptOpenMemFile( FPTAREAP pArea, LPDBOPENINFO pOpenInfo )
if( pArea->uiMemoVersion != DB_MEMOVER_SIX &&
memcmp( fptHeader.signature2, "FlexFile3\003", 10) == 0 )
{
USHORT usSize = HB_GET_LE_UINT16( fptHeader.flexSize );
pArea->uiMemoVersion = DB_MEMOVER_FLEX;
if ( pArea->uiMemoBlockSize == 0 )
pArea->uiMemoBlockSize = HB_GET_LE_UINT16( fptHeader.flexSize );
if( usSize != 0 && ( pArea->uiMemoBlockSize == 0 ||
pArea->rddID == s_uiRddIdBLOB ) )
{
pArea->uiMemoBlockSize = usSize;
}
}
}
hb_fptFileUnLock( pArea );
@@ -3840,14 +4083,18 @@ static ERRCODE hb_fptOpenMemFile( FPTAREAP pArea, LPDBOPENINFO pOpenInfo )
*/
static ERRCODE hb_fptPutValueFile( FPTAREAP pArea, USHORT uiIndex, BYTE * szFile, USHORT uiMode )
{
LPFIELD pField;
HB_TRACE(HB_TR_DEBUG, ("hb_fptPutValueFile(%p, %hu, %s, %hu)", pArea, uiIndex, szFile, uiMode));
if( !uiIndex || uiIndex > pArea->uiFieldCount )
return FAILURE;
/* TODO: add "V" field support */
pField = pArea->lpFields + uiIndex - 1;
if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR &&
pArea->lpFields[ uiIndex - 1 ].uiType == HB_IT_MEMO )
( pField->uiType == HB_IT_MEMO || ( pField->uiType == HB_IT_ANY &&
pField->uiLen >= 6 ) ) )
{
USHORT uiError;
BOOL bDeleted;
@@ -3871,6 +4118,29 @@ static ERRCODE hb_fptPutValueFile( FPTAREAP pArea, USHORT uiIndex, BYTE * szFile
{
uiError = EDBF_OPEN_DBF;
}
else if( pField->uiType == HB_IT_ANY )
{
PHB_ITEM pItem;
BYTE * pAlloc;
ULONG ulSize;
HB_FOFFSET size = hb_fsSeekLarge( hFile, 0, FS_END );
hb_fsSeekLarge( hFile, 0, FS_SET );
ulSize = HB_MIN( size, HB_VF_CHAR );
pAlloc = ( BYTE * ) hb_xgrab( ulSize + 1 );
if( hb_fsRead( hFile, pAlloc, ulSize ) != ulSize )
{
uiError = EDBF_READ;
hb_xfree( pAlloc );
}
else
{
pAlloc[ ulSize ] = '\0';
pItem = hb_itemPutCPtr( NULL, ( char * ) pAlloc, ulSize );
uiError = hb_fptPutVarField( pArea, uiIndex, pItem );
hb_itemRelease( pItem );
}
}
else if( !hb_fptFileLockEx( pArea, TRUE ) )
{
hb_fsClose( hFile );
@@ -3881,13 +4151,14 @@ static ERRCODE hb_fptPutValueFile( FPTAREAP pArea, USHORT uiIndex, BYTE * szFile
ULONG ulSize, ulBlock, ulType, ulOldSize, ulOldType;
HB_FOFFSET size = hb_fsSeekLarge( hFile, 0, FS_END );
if( ( HB_FOFFSET ) ( size & 0xFFFFFFFF ) == size )
hb_fsSeekLarge( hFile, 0, FS_SET );
if( ( HB_FOFFSET ) ( size & 0xFFFFFFFFUL ) == size )
{
ulSize = HB_MIN( ( ULONG ) size, 0xFFFFFFFFUL - sizeof( FPTBLOCK ) );
}
else
{
ulSize = HB_MIN( size, ( HB_FOFFSET ) ( 0xFFFFFFFF - sizeof( FPTBLOCK ) ) );
ulSize = HB_MIN( size, ( HB_FOFFSET ) ( 0xFFFFFFFFUL - sizeof( FPTBLOCK ) ) );
}
if( pArea->bMemoType == DB_MEMO_SMT )
@@ -3895,7 +4166,7 @@ static ERRCODE hb_fptPutValueFile( FPTAREAP pArea, USHORT uiIndex, BYTE * szFile
else
ulType = FPTIT_BINARY;
hb_fsSeekLarge( hFile, 0, FS_SET );
uiError = hb_dbfGetMemoData( (DBFAREAP) pArea, uiIndex - 1,
&ulBlock, &ulOldSize, &ulOldType );
if( uiError == SUCCESS )
@@ -3956,9 +4227,9 @@ static ERRCODE hb_fptInfo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
hb_itemPutC( pItem, hb_set.HB_SET_MFILEEXT );
else
{
char * szExt = hb_memoDefaultFileExt( pArea->bMemoType );
char * szExt = hb_memoDefaultFileExt( pArea->bMemoType, pArea->rddID );
if( !szExt )
szExt = hb_memoDefaultFileExt( pData->bMemoType );
szExt = hb_memoDefaultFileExt( pData->bMemoType, pArea->rddID );
hb_itemPutC( pItem, szExt );
}
}
@@ -4005,21 +4276,141 @@ static ERRCODE hb_fptInfo( FPTAREAP pArea, USHORT uiIndex, PHB_ITEM pItem )
/* case DBI_RDD_VERSION */
case DBI_BLOB_DIRECT_EXPORT: /* BLOBDirectExport() { <nPointer>, <cTargetFile>, <kMOde> */
case DBI_BLOB_DIRECT_GET: /* BLOBDirectGet() { <nPointer>, <nStart>, <nCount> } */
case DBI_BLOB_DIRECT_IMPORT: /* BLOBDirectImport() { <nOldPointer>, <cSourceFile> } */
case DBI_BLOB_DIRECT_PUT: /* BLOBDirectPut() { <nOldPointer>, <xBlob> } */
case DBI_BLOB_DIRECT_EXPORT: /* BLOBDirectExport() { <nPointer>, <cTargetFile>, <kMOde> } */
{
ERRCODE errCode = FAILURE;
case DBI_BLOB_ROOT_GET: /* BLOBRootGet() */
case DBI_BLOB_ROOT_PUT: /* BLOBRootPut( <xBlob> ) */
if( HB_IS_ARRAY( pItem ) )
{
ULONG ulBlock = hb_arrayGetNL( pItem, 1 );
BYTE * szFile = ( BYTE * ) hb_arrayGetCPtr( pItem, 2 );
if( ulBlock && szFile && *szFile )
errCode = hb_fptGetVarFile( pArea, ulBlock, szFile,
hb_arrayGetNI( pItem, 3 ) );
}
hb_itemPutL( pItem, errCode == SUCCESS );
break;
}
case DBI_BLOB_DIRECT_GET: /* BLOBDirectGet() { <nPointer>, <nStart>, <nCount> } */
{
/* pItem := { <nPointer>, <nStart>, <nCount> } */
ULONG ulBlock, ulStart, ulCount;
USHORT errCode;
if( HB_IS_ARRAY( pItem ) )
{
ulBlock = hb_arrayGetNL( pItem, 1 );
ulStart = hb_arrayGetNL( pItem, 2 );
if( ulStart )
--ulStart;
ulCount = hb_arrayGetNL( pItem, 3 );
}
else
{
ulBlock = ulStart = ulCount = 0;
}
errCode = hb_fptGetMemo( pArea, 0, pItem, FS_ERROR, ulBlock, ulStart, ulCount );
if( errCode != SUCCESS )
{
if( errCode != FAILURE )
hb_memoErrorRT( pArea, 0, errCode, pArea->szMemoFileName, 0, 0 );
return FAILURE;
}
break;
}
case DBI_BLOB_DIRECT_IMPORT: /* BLOBDirectImport() { <nOldPointer>, <cSourceFile> } */
if( HB_IS_ARRAY( pItem ) )
hb_itemPutNInt( pItem, hb_fptPutVarFile( pArea,
hb_arrayGetNL( pItem, 1 ),
( BYTE * ) hb_arrayGetCPtr( pItem, 2 ) ) );
else
hb_itemPutNI( pItem, 0 );
break;
case DBI_BLOB_DIRECT_PUT: /* BLOBDirectPut() { <nOldPointer>, <xBlob> } */
{
/* pItem := { <nOldPointer>, <xBlob> } */
USHORT errCode = EDBF_UNSUPPORTED;
ULONG ulBlock = 0;
if( HB_IS_ARRAY( pItem ) )
{
PHB_ITEM pValue = hb_arrayGetItemPtr( pItem, 2 );
ulBlock = hb_arrayGetNL( pItem, 1 );
if( pValue )
{
if( hb_fptFileLockEx( pArea, TRUE ) )
{
errCode = hb_fptPutMemo( pArea, 0, pValue, &ulBlock );
hb_fptFileUnLock( pArea );
}
else
errCode = EDBF_LOCK;
}
}
hb_itemPutNInt( pItem, ulBlock );
if( errCode != SUCCESS )
{
if( errCode != FAILURE )
hb_memoErrorRT( pArea, 0, errCode, pArea->szMemoFileName, 0, 0 );
return FAILURE;
}
break;
}
case DBI_BLOB_ROOT_GET: /* BLOBRootGet() */
{
ULONG ulBlock;
USHORT errCode;
errCode = hb_fptGetRootBlock( pArea, &ulBlock );
if( errCode == SUCCESS )
{
errCode = hb_fptGetMemo( pArea, 0, pItem, FS_ERROR, ulBlock, 0, 0 );
}
if( errCode != SUCCESS )
{
if( errCode != FAILURE )
hb_memoErrorRT( pArea, 0, errCode, pArea->szMemoFileName, 0, 0 );
hb_itemClear( pItem );
return FAILURE;
}
break;
}
case DBI_BLOB_ROOT_PUT: /* BLOBRootPut( <xBlob> ) */
{
ULONG ulBlock;
USHORT errCode;
errCode = hb_fptGetRootBlock( pArea, &ulBlock );
if( errCode == SUCCESS )
{
if( hb_fptFileLockEx( pArea, TRUE ) )
{
errCode = hb_fptPutMemo( pArea, 0, pItem, &ulBlock );
hb_fptFileUnLock( pArea );
if( errCode == SUCCESS )
errCode = hb_fptPutRootBlock( pArea, ulBlock );
}
else
errCode = EDBF_LOCK;
}
if( errCode != SUCCESS )
{
if( errCode != FAILURE )
hb_memoErrorRT( pArea, 0, errCode, pArea->szMemoFileName, 0, 0 );
hb_itemPutL( pItem, FALSE );
return FAILURE;
}
hb_itemPutL( pItem, TRUE );
break;
}
case DBI_BLOB_ROOT_LOCK: /* BLOBRootLock() */
hb_itemPutL( pItem, hb_fptFileLockEx( pArea, FALSE ) );
hb_itemPutL( pItem, hb_fptRootBlockLock( pArea ) );
break;
case DBI_BLOB_ROOT_UNLOCK: /* BLOBRootUnlock() */
hb_itemPutL( pItem, hb_fptFileUnLock( pArea ) );
hb_itemPutL( pItem, hb_fptRootBlockUnLock( pArea ) );
break;
case DBI_BLOB_DIRECT_LEN:
@@ -4045,7 +4436,7 @@ static ERRCODE hb_fptFieldInfo( FPTAREAP pArea, USHORT uiIndex, USHORT uiType, P
{
HB_TRACE(HB_TR_DEBUG, ("hb_fptFieldInfo(%p, %hu, %hu, %p)", pArea, uiIndex, uiType, pItem));
if( uiIndex > pArea->uiFieldCount )
if( !uiIndex || uiIndex > pArea->uiFieldCount )
return FAILURE;
if( pArea->fHasMemo && pArea->hMemoFile != FS_ERROR &&
@@ -4058,24 +4449,52 @@ static ERRCODE hb_fptFieldInfo( FPTAREAP pArea, USHORT uiIndex, USHORT uiType, P
switch( uiType )
{
case DBS_BLOB_GET: /* BLOBGet() { <nStart>, <nCount> } */
/* TODO: !!! pItem := { <nStart>, <nCount> } */
{
/* pItem := { <nStart>, <nCount> } */
ULONG ulStart, ulCount;
USHORT errCode;
if( HB_IS_ARRAY( pItem ) )
{
ulStart = hb_arrayGetNL( pItem, 1 );
if( ulStart )
--ulStart;
ulCount = hb_arrayGetNL( pItem, 2 );
}
else
{
ulStart = ulCount = 0;
}
errCode = hb_fptGetMemo( pArea, uiIndex, pItem, FS_ERROR, 0, ulStart, ulCount );
if( errCode != SUCCESS )
{
if( errCode != FAILURE )
hb_memoErrorRT( pArea, 0, errCode, pArea->szMemoFileName, 0, 0 );
return FAILURE;
}
return SUCCESS;
}
case DBS_BLOB_LEN:
hb_itemPutNL( pItem, hb_fptGetMemoLen( pArea, uiIndex - 1 ) );
hb_itemPutNL( pItem, hb_fptGetMemoLen( pArea, uiIndex ) );
return SUCCESS;
case DBS_BLOB_OFFSET:
/* Clipper 5.3 does not support it :-( [druzus] */
hb_dbfGetMemoData( (DBFAREAP) pArea, uiIndex - 1,
&ulBlock, &ulSize, &ulType );
hb_itemPutNInt( pItem, ( HB_FOFFSET ) ulBlock * pArea->uiMemoBlockSize +
( pArea->bMemoType == DB_MEMO_FPT ? sizeof( FPTBLOCK ) : 0 ) );
return SUCCESS;
case DBS_BLOB_POINTER:
/*
* Clipper 5.3 it returns the same value as DBS_BLOB_OFFSET
* in Harbour - it's a Clipper bug [druzus]
*/
hb_dbfGetMemoData( (DBFAREAP) pArea, uiIndex - 1,
&ulBlock, &ulSize, &ulType );
hb_itemPutNL( pItem, ulBlock );
return SUCCESS;
case DBS_BLOB_TYPE:
hb_itemPutC( pItem, hb_fptGetMemoType( pArea, uiIndex - 1 ) );
hb_itemPutC( pItem, hb_fptGetMemoType( pArea, uiIndex ) );
return SUCCESS;
}
}
@@ -4107,11 +4526,11 @@ static ERRCODE hb_fptRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, P
if( pData->szMemoExt[ 0 ] )
hb_itemPutC( pItem, pData->szMemoExt );
else if( pData->bMemoType == DB_MEMO_FPT &&
else if( pData->bMemoType == DB_MEMO_FPT && pRDD->rddID != s_uiRddIdBLOB &&
hb_set.HB_SET_MFILEEXT && hb_set.HB_SET_MFILEEXT[ 0 ] )
hb_itemPutC( pItem, hb_set.HB_SET_MFILEEXT );
else
hb_itemPutC( pItem, hb_memoDefaultFileExt( pData->bMemoType ) );
hb_itemPutC( pItem, hb_memoDefaultFileExt( pData->bMemoType, pRDD->rddID ) );
if( szNew )
{
@@ -4145,12 +4564,15 @@ static ERRCODE hb_fptRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, P
hb_itemPutNI( pItem, pData->bMemoType ? pData->bMemoType : DB_MEMO_FPT );
switch( iType )
if( pRDD->rddID != s_uiRddIdBLOB )
{
case DB_MEMO_DBT:
case DB_MEMO_FPT:
case DB_MEMO_SMT:
pData->bMemoType = ( BYTE ) iType;
switch( iType )
{
case DB_MEMO_DBT:
case DB_MEMO_FPT:
case DB_MEMO_SMT:
pData->bMemoType = ( BYTE ) iType;
}
}
break;
}
@@ -4174,9 +4596,10 @@ static ERRCODE hb_fptRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, P
case RDDI_MEMOGCTYPE:
hb_itemPutNI( pItem, 0 );
break;
case RDDI_MEMOREADLOCK:
#if defined( HB_MEMO_SAFELOCK )
hb_itemPutL( pItem, TRUE );
hb_itemPutL( pItem, pRDD->rddID != s_uiRddIdBLOB );
#else
hb_itemPutL( pItem, FALSE );
#endif
@@ -4185,6 +4608,10 @@ static ERRCODE hb_fptRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, P
hb_itemPutL( pItem, TRUE );
break;
case RDDI_BLOB_SUPPORT:
hb_itemPutL( pItem, pRDD->rddID == s_uiRddIdBLOB );
break;
default:
return SUPER_RDDINFO( pRDD, uiIndex, ulConnect, pItem );
}
@@ -4192,31 +4619,51 @@ static ERRCODE hb_fptRddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnect, P
return SUCCESS;
}
/* for backward compatibility */
HB_FUNC( DBFDBT ) {;}
HB_FUNC( DBFSMT ) {;}
HB_FUNC( DBFFPT ) {;}
HB_FUNC( DBFBLOB ) {;}
HB_FUNC( DBFFPT_GETFUNCTABLE )
static void hb_dbffptRegisterRDD( USHORT * pusRddId )
{
RDDFUNCS * pTable;
USHORT * uiCount;
USHORT * uiCount, uiRddId;
uiCount = ( USHORT * ) hb_itemGetPtr( hb_param( 1, HB_IT_POINTER ) );
pTable = ( RDDFUNCS * ) hb_itemGetPtr( hb_param( 2, HB_IT_POINTER ) );
uiRddId = hb_parni( 4 );
HB_TRACE(HB_TR_DEBUG, ("DBFFPT_GETFUNCTABLE(%i, %p)", uiCount, pTable));
if( pTable )
{
ERRCODE errCode;
if ( uiCount )
* uiCount = RDDFUNCSCOUNT;
hb_retni( hb_rddInherit( pTable, &fptTable, &fptSuper, ( BYTE * ) "DBF" ) );
errCode = hb_rddInherit( pTable, &fptTable, &fptSuper, ( BYTE * ) "DBF" );
if ( errCode == SUCCESS )
*pusRddId = uiRddId;
hb_retni( errCode );
}
else
hb_retni( FAILURE );
}
HB_FUNC( DBFFPT_GETFUNCTABLE )
{
HB_TRACE(HB_TR_DEBUG, ("DBFFPT_GETFUNCTABLE()"));
hb_dbffptRegisterRDD( &s_uiRddIdFPT );
}
HB_FUNC( DBFBLOB_GETFUNCTABLE )
{
HB_TRACE(HB_TR_DEBUG, ("DBFBLOB_GETFUNCTABLE()"));
hb_dbffptRegisterRDD( &s_uiRddIdBLOB );
}
#define __PRG_SOURCE__ __FILE__
@@ -4231,8 +4678,9 @@ static void hb_dbffptRddInit( void * cargo )
{
HB_SYMBOL_UNUSED( cargo );
if( hb_rddRegister( "DBF", RDT_FULL ) > 1 ||
hb_rddRegister( "DBFFPT", RDT_FULL ) > 1 )
if( hb_rddRegister( "DBF", RDT_FULL ) > 1 ||
hb_rddRegister( "DBFFPT", RDT_FULL ) > 1 ||
hb_rddRegister( "DBFBLOB", RDT_FULL ) > 1 )
{
hb_errInternal( HB_EI_RDDINVALID, NULL, NULL, NULL );
@@ -4242,8 +4690,10 @@ static void hb_dbffptRddInit( void * cargo )
}
HB_INIT_SYMBOLS_BEGIN( dbffpt1__InitSymbols )
{ "DBFFPT", {HB_FS_PUBLIC}, {HB_FUNCNAME( DBFFPT )}, NULL },
{ "DBFFPT_GETFUNCTABLE", {HB_FS_PUBLIC}, {HB_FUNCNAME( DBFFPT_GETFUNCTABLE )}, NULL }
{ "DBFFPT", {HB_FS_PUBLIC}, {HB_FUNCNAME( DBFFPT )}, NULL },
{ "DBFFPT_GETFUNCTABLE", {HB_FS_PUBLIC}, {HB_FUNCNAME( DBFFPT_GETFUNCTABLE )}, NULL },
{ "DBFBLOB", {HB_FS_PUBLIC}, {HB_FUNCNAME( DBFBLOB )}, NULL },
{ "DBFBLOB_GETFUNCTABLE", {HB_FS_PUBLIC}, {HB_FUNCNAME( DBFBLOB_GETFUNCTABLE )}, NULL }
HB_INIT_SYMBOLS_END( dbffpt1__InitSymbols )
HB_CALL_ON_STARTUP_BEGIN( _hb_dbffpt_rdd_init_ )

View File

@@ -485,8 +485,11 @@ ERRCODE hb_waSetFieldExtent( AREAP pArea, USHORT uiFieldExtent )
pArea->uiFieldExtent = uiFieldExtent;
/* Alloc field array */
pArea->lpFields = ( LPFIELD ) hb_xgrab( uiFieldExtent * sizeof( FIELD ) );
memset( pArea->lpFields, 0, uiFieldExtent * sizeof( FIELD ) );
if( uiFieldExtent )
{
pArea->lpFields = ( LPFIELD ) hb_xgrab( uiFieldExtent * sizeof( FIELD ) );
memset( pArea->lpFields, 0, uiFieldExtent * sizeof( FIELD ) );
}
return SUCCESS;
}
@@ -1557,6 +1560,7 @@ ERRCODE hb_rddInfo( LPRDDNODE pRDD, USHORT uiIndex, ULONG ulConnection, PHB_ITEM
case RDDI_MULTITAG:
case RDDI_SORTRECNO:
case RDDI_MULTIKEY:
case RDDI_BLOB_SUPPORT:
hb_itemPutL( pItem, FALSE );
break;