1
1
/******************************************************************************
2
* $Id: mapxbase.c 7418 2008-02-29 00:02:49Z nsavard $
2
* $Id: mapxbase.c 10772 2010-11-29 18:27:02Z aboudreault $
5
5
* Purpose: .dbf access API. Derived from shapelib, and relicensed with
28
28
* DEALINGS IN THE SOFTWARE.
29
29
****************************************************************************/
31
#define _FILE_OFFSET_BITS 64
31
33
#include "mapserver.h"
32
34
#include <stdlib.h> /* for atof() and atoi() */
35
MS_CVSID("$Id: mapxbase.c 7418 2008-02-29 00:02:49Z nsavard $")
37
MS_CVSID("$Id: mapxbase.c 10772 2010-11-29 18:27:02Z aboudreault $")
39
/* try to use a large file version of fseek for files up to 4GB (#3514) */
41
# define safe_fseek _fseeki64
43
# define safe_fseek fseeko
45
# define safe_fseek fseek
37
48
/************************************************************************/
121
132
nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
122
133
+ psDBF->nHeaderLength;
124
fseek( psDBF->fp, nRecordOffset, 0 );
135
safe_fseek( psDBF->fp, nRecordOffset, 0 );
125
136
fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
150
161
/* Ensure the extension is converted to dbf or DBF if it is */
151
162
/* currently .shp or .shx. */
152
163
/* -------------------------------------------------------------------- */
153
pszDBFFilename = (char *) malloc(strlen(pszFilename)+1);
164
pszDBFFilename = (char *) msSmallMalloc(strlen(pszFilename)+1);
154
165
strcpy( pszDBFFilename, pszFilename );
156
167
if( strcmp(pszFilename+strlen(pszFilename)-4,".shp")
168
179
/* Open the file. */
169
180
/* -------------------------------------------------------------------- */
170
181
psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
182
MS_CHECK_ALLOC(psDBF, sizeof(DBFInfo), NULL);
171
183
psDBF->fp = fopen( pszDBFFilename, pszAccess );
172
184
if( psDBF->fp == NULL )
184
196
/* -------------------------------------------------------------------- */
185
197
/* Read Table Header info */
186
198
/* -------------------------------------------------------------------- */
187
pabyBuf = (uchar *) malloc(500);
199
pabyBuf = (uchar *) msSmallMalloc(500);
188
200
fread( pabyBuf, 32, 1, psDBF->fp );
190
202
psDBF->nRecords = nRecords =
196
208
psDBF->nFields = nFields = (nHeadLen - 32) / 32;
198
psDBF->pszCurrentRecord = (char *) malloc(nRecLen);
210
psDBF->pszCurrentRecord = (char *) msSmallMalloc(nRecLen);
200
212
/* -------------------------------------------------------------------- */
201
213
/* Read in Field Definitions */
206
218
fseek( psDBF->fp, 32, 0 );
207
219
fread( pabyBuf, nHeadLen, 1, psDBF->fp );
209
psDBF->panFieldOffset = (int *) malloc(sizeof(int) * nFields);
210
psDBF->panFieldSize = (int *) malloc(sizeof(int) * nFields);
211
psDBF->panFieldDecimals = (int *) malloc(sizeof(int) * nFields);
212
psDBF->pachFieldType = (char *) malloc(sizeof(char) * nFields);
221
psDBF->panFieldOffset = (int *) msSmallMalloc(sizeof(int) * nFields);
222
psDBF->panFieldSize = (int *) msSmallMalloc(sizeof(int) * nFields);
223
psDBF->panFieldDecimals = (int *) msSmallMalloc(sizeof(int) * nFields);
224
psDBF->pachFieldType = (char *) msSmallMalloc(sizeof(char) * nFields);
214
226
for( iField = 0; iField < nFields; iField++ )
327
339
/* Create the info structure. */
328
340
/* -------------------------------------------------------------------- */
329
341
psDBF = (DBFHandle) malloc(sizeof(DBFInfo));
344
msSetError(MS_MEMERR, "%s: %d: Out of memory allocating %u bytes.\n", "msDBFCreate()",
345
__FILE__, __LINE__, sizeof(DBFInfo));
332
351
psDBF->nRecords = 0;
487
506
static char *msDBFReadAttribute(DBFHandle psDBF, int hEntity, int iField )
490
int nRecordOffset, i;
510
unsigned int nRecordOffset;
492
512
char *pReturnField = NULL;
494
514
/* -------------------------------------------------------------------- */
495
515
/* Is the request valid? */
496
516
/* -------------------------------------------------------------------- */
516
536
nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
518
fseek( psDBF->fp, nRecordOffset, 0 );
538
safe_fseek( psDBF->fp, nRecordOffset, 0 );
519
539
fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
521
541
psDBF->nCurrentRecord = hEntity;
672
692
/************************************************************************/
673
693
static int msDBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField, void * pValue )
675
int nRecordOffset, i, j;
695
unsigned int nRecordOffset;
677
698
char szSField[40], szFormat[12];
710
731
nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
712
fseek( psDBF->fp, nRecordOffset, 0 );
733
safe_fseek( psDBF->fp, nRecordOffset, 0 );
713
734
fread( psDBF->pszCurrentRecord, psDBF->nRecordLength, 1, psDBF->fp );
715
736
psDBF->nCurrentRecord = hEntity;
727
748
if( psDBF->panFieldDecimals[iField] == 0 ) {
728
sprintf( szFormat, "%%%dd", psDBF->panFieldSize[iField] );
729
sprintf(szSField, szFormat, (int) *((double *) pValue) );
749
snprintf( szFormat, sizeof(szFormat), "%%%dd", psDBF->panFieldSize[iField] );
750
snprintf(szSField, sizeof(szSField), szFormat, (int) *((double *) pValue) );
730
751
if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
731
752
szSField[psDBF->panFieldSize[iField]] = '\0';
732
753
strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), szSField, strlen(szSField) );
734
sprintf( szFormat, "%%%d.%df", psDBF->panFieldSize[iField], psDBF->panFieldDecimals[iField] );
735
sprintf(szSField, szFormat, *((double *) pValue) );
755
snprintf( szFormat, sizeof(szFormat), "%%%d.%df", psDBF->panFieldSize[iField], psDBF->panFieldDecimals[iField] );
756
snprintf(szSField, sizeof(szSField), szFormat, *((double *) pValue) );
736
757
if( (int) strlen(szSField) > psDBF->panFieldSize[iField] )
737
758
szSField[psDBF->panFieldSize[iField]] = '\0';
738
759
strncpy((char *) (pabyRec+psDBF->panFieldOffset[iField]), szSField, strlen(szSField) );
831
if((items = (char **)malloc(sizeof(char *)*nFields)) == NULL) {
832
msSetError(MS_MEMERR, NULL, "msGetDBFItems()");
852
items = (char **)malloc(sizeof(char *)*nFields);
853
MS_CHECK_ALLOC(items, sizeof(char *)*nFields, NULL);
836
855
for(i=0;i<nFields;i++) {
837
856
msDBFGetFieldInfo(dbffile, i, fName, NULL, NULL);
838
items[i] = strdup(fName);
857
items[i] = msStrdup(fName);
857
if((values = (char **)malloc(sizeof(char *)*nFields)) == NULL) {
858
msSetError(MS_MEMERR, NULL, "msGetAllDBFValues()");
876
values = (char **)malloc(sizeof(char *)*nFields);
877
MS_CHECK_ALLOC(values, sizeof(char *)*nFields, NULL);
862
879
for(i=0;i<nFields;i++)
863
values[i] = strdup(msDBFReadStringAttribute(dbffile, record, i));
880
values[i] = msStrdup(msDBFReadStringAttribute(dbffile, record, i));
870
887
int *itemindexes=NULL, i;
872
889
if(numitems == 0) return(NULL);
874
891
itemindexes = (int *)malloc(sizeof(int)*numitems);
876
msSetError(MS_MEMERR, NULL, "msGetItemIndexes()");
892
MS_CHECK_ALLOC(itemindexes, sizeof(int)*numitems, NULL);
880
894
for(i=0;i<numitems;i++) {
881
895
itemindexes[i] = msDBFGetItemIndex(dbffile, items[i]);
882
896
if(itemindexes[i] == -1) {
897
911
if(numitems == 0) return(NULL);
899
if((values = (char **)malloc(sizeof(char *)*numitems)) == NULL) {
900
msSetError(MS_MEMERR, NULL, "msGetSomeDBFValues()");
913
values = (char **)malloc(sizeof(char *)*numitems);
914
MS_CHECK_ALLOC(values, sizeof(char *)*numitems, NULL);
904
916
for(i=0;i<numitems;i++) {
905
917
value = msDBFReadStringAttribute(dbffile, record, itemindexes[i]);
906
918
if (value == NULL)
907
919
return NULL; /* Error already reported by msDBFReadStringAttribute() */
908
values[i] = strdup(value);
920
values[i] = msStrdup(value);