[GRASS-SVN] r30804 - grass/trunk/lib/external/shapelib
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Mar 30 05:21:48 EDT 2008
Author: neteler
Date: 2008-03-30 05:21:48 -0400 (Sun, 30 Mar 2008)
New Revision: 30804
Modified:
grass/trunk/lib/external/shapelib/README
grass/trunk/lib/external/shapelib/dbfopen.c
grass/trunk/lib/external/shapelib/shapefil.h
grass/trunk/lib/external/shapelib/shpopen.c
Log:
sync'ed to GDAL SVN-trunk: gdal/ogr/ogrsf_frmts/shape/
Modified: grass/trunk/lib/external/shapelib/README
===================================================================
--- grass/trunk/lib/external/shapelib/README 2008-03-30 04:01:55 UTC (rev 30803)
+++ grass/trunk/lib/external/shapelib/README 2008-03-30 09:21:48 UTC (rev 30804)
@@ -2,12 +2,12 @@
ogr/ogrsf_frmts/shape/
Last update
+* taken from GDAL 1.5.1-SVN (Sun Mar 30 11:20:43 CEST 2008)
* taken from GDAL 1.5.0-CVS (Wed Sep 5 13:48:48 CEST 2007)
-
* taken from GDAL 1.3.2-CVS (Sat Jun 17 22:08:04 CEST 2006)
Additional fixes:
- - dbfopen.c
+ - dbfopen.c (around line 1013)
GDAL bug #809 (http://trac.osgeo.org/gdal/ticket/809)
- Use <grass/shapefil.h> etc rather than "shapefil.h"
Modified: grass/trunk/lib/external/shapelib/dbfopen.c
===================================================================
--- grass/trunk/lib/external/shapelib/dbfopen.c 2008-03-30 04:01:55 UTC (rev 30803)
+++ grass/trunk/lib/external/shapelib/dbfopen.c 2008-03-30 09:21:48 UTC (rev 30804)
@@ -33,9 +33,9 @@
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
- * $Log$
- * Revision 1.9 2007-09-05 11:50:23 markus
- * SHAPELIB copy updated
+ * $Log: dbfopen.c,v $
+ * Revision 1.74 2007/12/06 07:00:25 fwarmerdam
+ * dbfopen now using SAHooks for fileio
*
* Revision 1.73 2007/09/03 19:48:11 fwarmerdam
* move DBFReadAttribute() static dDoubleField into dbfinfo
@@ -179,9 +179,10 @@
/* Write the initial 32 byte file header, and all the field */
/* descriptions. */
/* -------------------------------------------------------------------- */
- fseek( psDBF->fp, 0, 0 );
- fwrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
- fwrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields, psDBF->fp );
+ psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
+ psDBF->sHooks.FWrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
+ psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
+ psDBF->fp );
/* -------------------------------------------------------------------- */
/* Write out the newline character if there is room for it. */
@@ -191,7 +192,7 @@
char cNewline;
cNewline = 0x0d;
- fwrite( &cNewline, 1, 1, psDBF->fp );
+ psDBF->sHooks.FWrite( &cNewline, 1, 1, psDBF->fp );
}
}
@@ -204,18 +205,20 @@
static int DBFFlushRecord( DBFHandle psDBF )
{
- int nRecordOffset;
+ SAOffset nRecordOffset;
if( psDBF->bCurrentRecordModified && psDBF->nCurrentRecord > -1 )
{
psDBF->bCurrentRecordModified = FALSE;
- nRecordOffset = psDBF->nRecordLength * psDBF->nCurrentRecord
- + psDBF->nHeaderLength;
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) psDBF->nCurrentRecord
+ + psDBF->nHeaderLength;
- if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0
- || fwrite( psDBF->pszCurrentRecord, psDBF->nRecordLength,
- 1, psDBF->fp ) != 1 )
+ if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0
+ || psDBF->sHooks.FWrite( psDBF->pszCurrentRecord,
+ psDBF->nRecordLength,
+ 1, psDBF->fp ) != 1 )
{
#ifdef USE_CPL
CPLError( CE_Failure, CPLE_FileIO,
@@ -241,28 +244,29 @@
{
if( psDBF->nCurrentRecord != iRecord )
{
- int nRecordOffset;
+ SAOffset nRecordOffset;
if( !DBFFlushRecord( psDBF ) )
return FALSE;
- nRecordOffset = psDBF->nRecordLength * iRecord + psDBF->nHeaderLength;
+ nRecordOffset =
+ psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
- if( fseek( psDBF->fp, nRecordOffset, 0 ) != 0 )
+ if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
{
#ifdef USE_CPL
CPLError( CE_Failure, CPLE_FileIO,
- "fseek(%d) failed on DBF file.\n",
- nRecordOffset );
+ "fseek(%ld) failed on DBF file.\n",
+ (long) nRecordOffset );
#else
- fprintf( stderr, "fseek(%d) failed on DBF file.\n",
- nRecordOffset );
+ fprintf( stderr, "fseek(%ld) failed on DBF file.\n",
+ (long) nRecordOffset );
#endif
return FALSE;
}
- if( fread( psDBF->pszCurrentRecord, psDBF->nRecordLength,
- 1, psDBF->fp ) != 1 )
+ if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord,
+ psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
{
#ifdef USE_CPL
CPLError( CE_Failure, CPLE_FileIO,
@@ -296,18 +300,18 @@
DBFFlushRecord( psDBF );
- fseek( psDBF->fp, 0, 0 );
- fread( abyFileHeader, 32, 1, psDBF->fp );
+ psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
+ psDBF->sHooks.FRead( abyFileHeader, 32, 1, psDBF->fp );
abyFileHeader[4] = (unsigned char) (psDBF->nRecords % 256);
abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256);
abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256);
abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256);
- fseek( psDBF->fp, 0, 0 );
- fwrite( abyFileHeader, 32, 1, psDBF->fp );
+ psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
+ psDBF->sHooks.FWrite( abyFileHeader, 32, 1, psDBF->fp );
- fflush( psDBF->fp );
+ psDBF->sHooks.FFlush( psDBF->fp );
}
/************************************************************************/
@@ -320,8 +324,25 @@
DBFOpen( const char * pszFilename, const char * pszAccess )
{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return DBFOpenLL( pszFilename, pszAccess, &sHooks );
+}
+
+/************************************************************************/
+/* DBFOpen() */
+/* */
+/* Open a .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
+
+{
DBFHandle psDBF;
- unsigned char *pabyBuf;
+ unsigned char *pabyBuf;
int nFields, nHeadLen, iField, i;
char *pszBasename, *pszFullname;
@@ -357,12 +378,13 @@
sprintf( pszFullname, "%s.dbf", pszBasename );
psDBF = (DBFHandle) calloc( 1, sizeof(DBFInfo) );
- psDBF->fp = fopen( pszFullname, pszAccess );
+ psDBF->fp = psHooks->FOpen( pszFullname, pszAccess );
+ memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
if( psDBF->fp == NULL )
{
sprintf( pszFullname, "%s.DBF", pszBasename );
- psDBF->fp = fopen(pszFullname, pszAccess );
+ psDBF->fp = psDBF->sHooks.FOpen(pszFullname, pszAccess );
}
free( pszBasename );
@@ -382,9 +404,9 @@
/* Read Table Header info */
/* -------------------------------------------------------------------- */
pabyBuf = (unsigned char *) malloc(500);
- if( fread( pabyBuf, 32, 1, psDBF->fp ) != 1 )
+ if( psDBF->sHooks.FRead( pabyBuf, 32, 1, psDBF->fp ) != 1 )
{
- fclose( psDBF->fp );
+ psDBF->sHooks.FClose( psDBF->fp );
free( pabyBuf );
free( psDBF );
return NULL;
@@ -407,10 +429,10 @@
pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
psDBF->pszHeader = (char *) pabyBuf;
- fseek( psDBF->fp, 32, 0 );
- if( fread( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
+ psDBF->sHooks.FSeek( psDBF->fp, 32, 0 );
+ if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
{
- fclose( psDBF->fp );
+ psDBF->sHooks.FClose( psDBF->fp );
free( pabyBuf );
free( psDBF->pszCurrentRecord );
free( psDBF );
@@ -484,7 +506,7 @@
/* -------------------------------------------------------------------- */
/* Close, and free resources. */
/* -------------------------------------------------------------------- */
- fclose( psDBF->fp );
+ psDBF->sHooks.FClose( psDBF->fp );
if( psDBF->panFieldOffset != NULL )
{
@@ -513,10 +535,28 @@
DBFCreate( const char * pszFilename )
{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return DBFCreateLL( pszFilename, &sHooks );
+}
+
+/************************************************************************/
+/* DBFCreate() */
+/* */
+/* Create a new .dbf file. */
+/************************************************************************/
+
+DBFHandle SHPAPI_CALL
+DBFCreateLL( const char * pszFilename, SAHooks *psHooks )
+
+{
DBFHandle psDBF;
- FILE *fp;
+ SAFile fp;
char *pszFullname, *pszBasename;
int i;
+ char chZero = '\0';
/* -------------------------------------------------------------------- */
/* Compute the base (layer) name. If there is any extension */
@@ -539,14 +579,14 @@
/* -------------------------------------------------------------------- */
/* Create the file. */
/* -------------------------------------------------------------------- */
- fp = fopen( pszFullname, "wb" );
+ fp = psHooks->FOpen( pszFullname, "wb" );
if( fp == NULL )
return( NULL );
+
+ psHooks->FWrite( &chZero, 1, 1, fp );
+ psHooks->FClose( fp );
- fputc( 0, fp );
- fclose( fp );
-
- fp = fopen( pszFullname, "rb+" );
+ fp = psHooks->FOpen( pszFullname, "rb+" );
if( fp == NULL )
return( NULL );
@@ -557,6 +597,7 @@
/* -------------------------------------------------------------------- */
psDBF = (DBFHandle) calloc(1,sizeof(DBFInfo));
+ memcpy( &(psDBF->sHooks), psHooks, sizeof(SAHooks) );
psDBF->fp = fp;
psDBF->nRecords = 0;
psDBF->nFields = 0;
Modified: grass/trunk/lib/external/shapelib/shapefil.h
===================================================================
--- grass/trunk/lib/external/shapelib/shapefil.h 2008-03-30 04:01:55 UTC (rev 30803)
+++ grass/trunk/lib/external/shapelib/shapefil.h 2008-03-30 09:21:48 UTC (rev 30804)
@@ -36,10 +36,23 @@
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
- * $Log$
- * Revision 1.6 2007-09-05 11:50:23 markus
- * SHAPELIB copy updated
+ * $Log: shapefil.h,v $
+ * Revision 1.40 2007/12/06 07:00:25 fwarmerdam
+ * dbfopen now using SAHooks for fileio
*
+ * Revision 1.39 2007/12/04 20:37:56 fwarmerdam
+ * preliminary implementation of hooks api for io and errors
+ *
+ * Revision 1.38 2007/11/21 22:39:56 fwarmerdam
+ * close shx file in readonly mode (GDAL #1956)
+ *
+ * Revision 1.37 2007/10/27 03:31:14 fwarmerdam
+ * limit default depth of tree to 12 levels (gdal ticket #1594)
+ *
+ * Revision 1.36 2007/09/10 23:33:15 fwarmerdam
+ * Upstreamed support for visibility flag in SHPAPI_CALL for the needs
+ * of GDAL (gdal ticket #1810).
+ *
* Revision 1.35 2007/09/03 19:48:10 fwarmerdam
* move DBFReadAttribute() static dDoubleField into dbfinfo
*
@@ -91,6 +104,7 @@
#ifdef USE_CPL
#include "cpl_error.h"
+#include "cpl_vsi.h"
#endif
#ifdef __cplusplus
@@ -113,7 +127,7 @@
/* is disabled. */
/* -------------------------------------------------------------------- */
#define DISABLE_MULTIPATCH_MEASURE
-
+
/* -------------------------------------------------------------------- */
/* SHPAPI_CALL */
/* */
@@ -149,7 +163,12 @@
#endif
#ifndef SHPAPI_CALL
-# define SHPAPI_CALL
+# if defined(USE_GCC_VISIBILITY_FLAG)
+# define SHPAPI_CALL __attribute__ ((visibility("default")))
+# define SHPAPI_CALL1(x) __attribute__ ((visibility("default"))) x
+# else
+# define SHPAPI_CALL
+# endif
#endif
#ifndef SHPAPI_CALL1
@@ -166,15 +185,40 @@
#else
# define SHP_CVSID(string)
#endif
+
+/* -------------------------------------------------------------------- */
+/* IO/Error hook functions. */
+/* -------------------------------------------------------------------- */
+typedef int *SAFile;
+#ifndef SAOffset
+typedef unsigned long SAOffset;
+#endif
+
+typedef struct {
+ SAFile (*FOpen) ( const char *filename, const char *path);
+ SAOffset (*FRead) ( void *p, SAOffset size, SAOffset nmemb, SAFile file);
+ SAOffset (*FWrite)( void *p, SAOffset size, SAOffset nmemb, SAFile file);
+ SAOffset (*FSeek) ( SAFile file, SAOffset offset, int whence );
+ SAOffset (*FTell) ( SAFile file );
+ int (*FFlush)( SAFile file );
+ int (*FClose)( SAFile file );
+
+ void (*Error) ( const char *message );
+} SAHooks;
+
+void SHPAPI_CALL SASetupDefaultHooks( SAHooks *psHooks );
+
/************************************************************************/
/* SHP Support. */
/************************************************************************/
typedef struct
{
- FILE *fpSHP;
- FILE *fpSHX;
+ SAHooks sHooks;
+ SAFile fpSHP;
+ SAFile fpSHX;
+
int nShapeType; /* SHPT_* */
int nFileSize; /* SHP file */
@@ -262,10 +306,19 @@
/* -------------------------------------------------------------------- */
/* SHP API Prototypes */
/* -------------------------------------------------------------------- */
+
+/* If pszAccess is read-only, the fpSHX field of the returned structure */
+/* will be NULL as it is not necessary to keep the SHX file open */
SHPHandle SHPAPI_CALL
SHPOpen( const char * pszShapeFile, const char * pszAccess );
SHPHandle SHPAPI_CALL
+ SHPOpenLL( const char *pszShapeFile, const char *pszAccess,
+ SAHooks *psHooks );
+SHPHandle SHPAPI_CALL
SHPCreate( const char * pszShapeFile, int nShapeType );
+SHPHandle SHPAPI_CALL
+ SHPCreateLL( const char * pszShapeFile, int nShapeType,
+ SAHooks *psHooks );
void SHPAPI_CALL
SHPGetInfo( SHPHandle hSHP, int * pnEntities, int * pnShapeType,
double * padfMinBound, double * padfMaxBound );
@@ -309,6 +362,9 @@
/* this can be two or four for binary or quad tree */
#define MAX_SUBNODE 4
+/* upper limit of tree levels for automatic estimation */
+#define MAX_DEFAULT_TREE_DEPTH 12
+
typedef struct shape_tree_node
{
/* region covered by this node */
@@ -376,8 +432,10 @@
/************************************************************************/
typedef struct
{
- FILE *fp;
+ SAHooks sHooks;
+ SAFile fp;
+
int nRecords;
int nRecordLength;
@@ -415,10 +473,16 @@
#define XBASE_FLDHDR_SZ 32
+
DBFHandle SHPAPI_CALL
DBFOpen( const char * pszDBFFile, const char * pszAccess );
DBFHandle SHPAPI_CALL
+ DBFOpenLL( const char * pszDBFFile, const char * pszAccess,
+ SAHooks *psHooks );
+DBFHandle SHPAPI_CALL
DBFCreate( const char * pszDBFFile );
+DBFHandle SHPAPI_CALL
+ DBFCreateLL( const char * pszDBFFile, SAHooks *psHooks );
int SHPAPI_CALL
DBFGetFieldCount( DBFHandle psDBF );
Modified: grass/trunk/lib/external/shapelib/shpopen.c
===================================================================
--- grass/trunk/lib/external/shapelib/shpopen.c 2008-03-30 04:01:55 UTC (rev 30803)
+++ grass/trunk/lib/external/shapelib/shpopen.c 2008-03-30 09:21:48 UTC (rev 30804)
@@ -33,10 +33,32 @@
* DEALINGS IN THE SOFTWARE.
******************************************************************************
*
- * $Log$
- * Revision 1.7 2007-09-05 11:50:23 markus
- * SHAPELIB copy updated
+ * $Log: shpopen.c,v $
+ * Revision 1.59 2008/03/14 05:25:31 fwarmerdam
+ * Correct crash on buggy geometries (gdal #2218)
*
+ * Revision 1.58 2008/01/08 23:28:26 bram
+ * on line 2095, use a float instead of a double to avoid a compiler warning
+ *
+ * Revision 1.57 2007/12/06 07:00:25 fwarmerdam
+ * dbfopen now using SAHooks for fileio
+ *
+ * Revision 1.56 2007/12/04 20:37:56 fwarmerdam
+ * preliminary implementation of hooks api for io and errors
+ *
+ * Revision 1.55 2007/11/21 22:39:56 fwarmerdam
+ * close shx file in readonly mode (GDAL #1956)
+ *
+ * Revision 1.54 2007/11/15 00:12:47 mloskot
+ * Backported recent changes from GDAL (Ticket #1415) to Shapelib.
+ *
+ * Revision 1.53 2007/11/14 22:31:08 fwarmerdam
+ * checks after mallocs to detect for corrupted/voluntary broken shapefiles.
+ * http://trac.osgeo.org/gdal/ticket/1991
+ *
+ * Revision 1.52 2007/06/21 15:58:33 fwarmerdam
+ * fix for SHPRewindObject when rings touch at one vertex (gdal #976)
+ *
* Revision 1.51 2006/09/04 15:24:01 fwarmerdam
* Fixed up log message for 1.49.
*
@@ -208,9 +230,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-#ifdef USE_CPL
-#include <cpl_vsi.h>
-#endif
SHP_CVSID("$Id$")
@@ -287,6 +306,12 @@
int32 i32;
double dValue;
int32 *panSHX;
+
+ if (psSHP->fpSHX == NULL)
+ {
+ psSHP->sHooks.Error( "SHPWriteHeader failed : SHX file is closed");
+ return;
+ }
/* -------------------------------------------------------------------- */
/* Prepare header block for .shp file. */
@@ -344,13 +369,10 @@
/* -------------------------------------------------------------------- */
/* Write .shp file header. */
/* -------------------------------------------------------------------- */
- if( fseek( psSHP->fpSHP, 0, 0 ) != 0
- || fwrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
+ if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0
+ || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_OpenFailed,
- "Failure writing .shp header (%s)", VSIStrerror( errno ) );
-#endif
+ psSHP->sHooks.Error( "Failure writing .shp header" );
return;
}
@@ -361,13 +383,10 @@
ByteCopy( &i32, abyHeader+24, 4 );
if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
- if( fseek( psSHP->fpSHX, 0, 0 ) != 0
- || fwrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
+ if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0
+ || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_OpenFailed,
- "Failure writing .shx header (%s)", VSIStrerror( errno ) );
-#endif
+ psSHP->sHooks.Error( "Failure writing .shx header" );
return;
}
@@ -384,13 +403,10 @@
if( !bBigEndian ) SwapWord( 4, panSHX+i*2+1 );
}
- if( (int)fwrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX )
+ if( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX )
!= psSHP->nRecords )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_OpenFailed,
- "Failure writing .shx contents (%s)", VSIStrerror( errno ) );
-#endif
+ psSHP->sHooks.Error( "Failure writing .shx contents" );
}
free( panSHX );
@@ -398,19 +414,34 @@
/* -------------------------------------------------------------------- */
/* Flush to disk. */
/* -------------------------------------------------------------------- */
- fflush( psSHP->fpSHP );
- fflush( psSHP->fpSHX );
+ psSHP->sHooks.FFlush( psSHP->fpSHP );
+ psSHP->sHooks.FFlush( psSHP->fpSHX );
}
/************************************************************************/
-/* shpopen() */
+/* SHPOpen() */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPOpen( const char * pszLayer, const char * pszAccess )
+
+{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return SHPOpenLL( pszLayer, pszAccess, &sHooks );
+}
+
+/************************************************************************/
+/* SHPOpen() */
/* */
/* Open the .shp and .shx files based on the basename of the */
/* files or either file name. */
/************************************************************************/
SHPHandle SHPAPI_CALL
-SHPOpen( const char * pszLayer, const char * pszAccess )
+SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
{
char *pszFullname, *pszBasename;
@@ -446,6 +477,7 @@
psSHP = (SHPHandle) calloc(sizeof(SHPInfo),1);
psSHP->bUpdated = FALSE;
+ memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
/* -------------------------------------------------------------------- */
/* Compute the base (layer) name. If there is any extension */
@@ -466,12 +498,12 @@
/* a PC to Unix with upper case filenames won't work! */
/* -------------------------------------------------------------------- */
pszFullname = (char *) malloc(strlen(pszBasename) + 5);
- sprintf( pszFullname, "%s.shp", pszBasename );
- psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ sprintf( pszFullname, "%s.shp", pszBasename ) ;
+ psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
if( psSHP->fpSHP == NULL )
{
sprintf( pszFullname, "%s.SHP", pszBasename );
- psSHP->fpSHP = fopen(pszFullname, pszAccess );
+ psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
}
if( psSHP->fpSHP == NULL )
@@ -488,11 +520,11 @@
}
sprintf( pszFullname, "%s.shx", pszBasename );
- psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
if( psSHP->fpSHX == NULL )
{
sprintf( pszFullname, "%s.SHX", pszBasename );
- psSHP->fpSHX = fopen(pszFullname, pszAccess );
+ psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
}
if( psSHP->fpSHX == NULL )
@@ -502,7 +534,7 @@
"Unable to open %s.shx or %s.SHX.",
pszBasename, pszBasename );
#endif
- fclose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
free( psSHP );
free( pszBasename );
free( pszFullname );
@@ -516,7 +548,7 @@
/* Read the file size from the SHP file. */
/* -------------------------------------------------------------------- */
pabyBuf = (uchar *) malloc(100);
- fread( pabyBuf, 100, 1, psSHP->fpSHP );
+ psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
psSHP->nFileSize = (pabyBuf[24] * 256 * 256 * 256
+ pabyBuf[25] * 256 * 256
@@ -526,18 +558,15 @@
/* -------------------------------------------------------------------- */
/* Read SHX file Header info */
/* -------------------------------------------------------------------- */
- if( fread( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
+ if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
|| pabyBuf[0] != 0
|| pabyBuf[1] != 0
|| pabyBuf[2] != 0x27
|| (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- ".shx file is unreadable, or corrupt." );
-#endif
- fclose( psSHP->fpSHP );
- fclose( psSHP->fpSHX );
+ psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
free( psSHP );
return( NULL );
@@ -551,15 +580,17 @@
if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- "Record count in .shp header is %d, which seems\n"
- "unreasonable. Assuming header is corrupt.",
+ char szError[200];
+
+ sprintf( szError,
+ "Record count in .shp header is %d, which seems\n"
+ "unreasonable. Assuming header is corrupt.",
psSHP->nRecords );
-#endif
- fclose( psSHP->fpSHP );
- fclose( psSHP->fpSHX );
+ psSHP->sHooks.Error( szError );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
free( psSHP );
+ free(pabyBuf);
return( NULL );
}
@@ -611,25 +642,55 @@
(int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
psSHP->panRecSize =
(int *) malloc(sizeof(int) * MAX(1,psSHP->nMaxRecords) );
+ pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
- pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
- if( (int) fread( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )
+ if (psSHP->panRecOffset == NULL ||
+ psSHP->panRecSize == NULL ||
+ pabyBuf == NULL)
+ {
+ char szError[200];
+
+ sprintf(szError,
+ "Not enough memory to allocate requested memory (nRecords=%d).\n"
+ "Probably broken SHP file",
+ psSHP->nRecords );
+ psSHP->sHooks.Error( szError );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ if (psSHP->panRecOffset) free( psSHP->panRecOffset );
+ if (psSHP->panRecSize) free( psSHP->panRecSize );
+ if (pabyBuf) free( pabyBuf );
+ free( psSHP );
+ return( NULL );
+ }
+
+ if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX )
!= psSHP->nRecords )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- "Failed to read all values for %d records in .shx file.",
- psSHP->nRecords );
-#endif
+ char szError[200];
+
+ sprintf( szError,
+ "Failed to read all values for %d records in .shx file.",
+ psSHP->nRecords );
+ psSHP->sHooks.Error( szError );
+
/* SHX is short or unreadable for some reason. */
- fclose( psSHP->fpSHP );
- fclose( psSHP->fpSHX );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
+ psSHP->sHooks.FClose( psSHP->fpSHX );
free( psSHP->panRecOffset );
free( psSHP->panRecSize );
+ free( pabyBuf );
free( psSHP );
return( NULL );
}
+
+ /* In read-only mode, we can close the SHX now */
+ if (strcmp(pszAccess, "rb") == 0)
+ {
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ psSHP->fpSHX = NULL;
+ }
for( i = 0; i < psSHP->nRecords; i++ )
{
@@ -674,8 +735,9 @@
free( psSHP->panRecOffset );
free( psSHP->panRecSize );
- fclose( psSHP->fpSHX );
- fclose( psSHP->fpSHP );
+ if ( psSHP->fpSHX != NULL)
+ psSHP->sHooks.FClose( psSHP->fpSHX );
+ psSHP->sHooks.FClose( psSHP->fpSHP );
if( psSHP->pabyRec != NULL )
{
@@ -727,9 +789,27 @@
SHPCreate( const char * pszLayer, int nShapeType )
{
+ SAHooks sHooks;
+
+ SASetupDefaultHooks( &sHooks );
+
+ return SHPCreateLL( pszLayer, nShapeType, &sHooks );
+}
+
+/************************************************************************/
+/* SHPCreate() */
+/* */
+/* Create a new shape file and return a handle to the open */
+/* shape file with read/write access. */
+/************************************************************************/
+
+SHPHandle SHPAPI_CALL
+SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
+
+{
char *pszBasename, *pszFullname;
int i;
- FILE *fpSHP, *fpSHX;
+ SAFile fpSHP, fpSHX;
uchar abyHeader[100];
int32 i32;
double dValue;
@@ -762,26 +842,18 @@
/* -------------------------------------------------------------------- */
pszFullname = (char *) malloc(strlen(pszBasename) + 5);
sprintf( pszFullname, "%s.shp", pszBasename );
- fpSHP = fopen(pszFullname, "wb" );
+ fpSHP = psHooks->FOpen(pszFullname, "wb" );
if( fpSHP == NULL )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- "Failed to create file %s.",
- pszFullname );
-#endif
+ psHooks->Error( "Failed to create file .shp file." );
return( NULL );
}
sprintf( pszFullname, "%s.shx", pszBasename );
- fpSHX = fopen(pszFullname, "wb" );
+ fpSHX = psHooks->FOpen(pszFullname, "wb" );
if( fpSHX == NULL )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- "Failed to create file %s.",
- pszFullname );
-#endif
+ psHooks->Error( "Failed to create file .shx file." );
return( NULL );
}
@@ -818,12 +890,9 @@
/* -------------------------------------------------------------------- */
/* Write .shp file header. */
/* -------------------------------------------------------------------- */
- if( fwrite( abyHeader, 100, 1, fpSHP ) != 1 )
+ if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- "Failed to write .shp header." );
-#endif
+ psHooks->Error( "Failed to write .shp header." );
return NULL;
}
@@ -834,22 +903,19 @@
ByteCopy( &i32, abyHeader+24, 4 );
if( !bBigEndian ) SwapWord( 4, abyHeader+24 );
- if( fwrite( abyHeader, 100, 1, fpSHX ) != 1 )
+ if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- "Failed to write .shx header." );
-#endif
+ psHooks->Error( "Failed to write .shx header." );
return NULL;
}
/* -------------------------------------------------------------------- */
/* Close the files, and then open them as regular existing files. */
/* -------------------------------------------------------------------- */
- fclose( fpSHP );
- fclose( fpSHX );
+ psHooks->FClose( fpSHP );
+ psHooks->FClose( fpSHX );
- return( SHPOpen( pszLayer, "r+b" ) );
+ return( SHPOpenLL( pszLayer, "r+b", psHooks ) );
}
/************************************************************************/
@@ -992,15 +1058,7 @@
}
if( psObject->panPartStart[0] != 0 )
- {
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_AppDefined,
- "panPartStart[0] != 0, patching internally. Please fix your code!\n" );
-#else
- fprintf( stderr, "panPartStart[0] != 0, patching internally. Please fix your code!\n" );
-#endif
psObject->panPartStart[0] = 0;
- }
}
/* -------------------------------------------------------------------- */
@@ -1382,13 +1440,10 @@
/* -------------------------------------------------------------------- */
/* Write out record. */
/* -------------------------------------------------------------------- */
- if( fseek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
- || fwrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
+ if( psSHP->sHooks.FSeek( psSHP->fpSHP, nRecordOffset, 0 ) != 0
+ || psSHP->sHooks.FWrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
{
-#ifdef USE_CPL
- CPLError( CE_Failure, CPLE_FileIO,
- "Error in fseek() or fwrite() writing object to .shp file." );
-#endif
+ psSHP->sHooks.Error( "Error in psSHP->sHooks.FSeek() or fwrite() writing object to .shp file." );
free( pabyRec );
return -1;
}
@@ -1445,7 +1500,9 @@
SHPReadObject( SHPHandle psSHP, int hEntity )
{
+ int nEntitySize, nRequiredSize;
SHPObject *psShape;
+ char pszErrorMsg[128];
/* -------------------------------------------------------------------- */
/* Validate the record/entity number. */
@@ -1456,17 +1513,39 @@
/* -------------------------------------------------------------------- */
/* Ensure our record buffer is large enough. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 > psSHP->nBufSize )
+ nEntitySize = psSHP->panRecSize[hEntity]+8;
+ if( nEntitySize > psSHP->nBufSize )
{
- psSHP->nBufSize = psSHP->panRecSize[hEntity]+8;
- psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,psSHP->nBufSize);
+ psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
+ if (psSHP->pabyRec == NULL)
+ {
+ char szError[200];
+
+ /* Reallocate previous successfull size for following features */
+ psSHP->pabyRec = malloc(psSHP->nBufSize);
+
+ sprintf( szError,
+ "Not enough memory to allocate requested memory (nBufSize=%d). "
+ "Probably broken SHP file", psSHP->nBufSize );
+ psSHP->sHooks.Error( szError );
+ return NULL;
+ }
+
+ /* Only set new buffer size after successfull alloc */
+ psSHP->nBufSize = nEntitySize;
}
+ /* In case we were not able to reallocate the buffer on a previous step */
+ if (psSHP->pabyRec == NULL)
+ {
+ return NULL;
+ }
+
/* -------------------------------------------------------------------- */
/* Read the record. */
/* -------------------------------------------------------------------- */
- if( fseek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0
- || fread( psSHP->pabyRec, psSHP->panRecSize[hEntity]+8, 1,
+ if( psSHP->sHooks.FSeek( psSHP->fpSHP, psSHP->panRecOffset[hEntity], 0 ) != 0
+ || psSHP->sHooks.FRead( psSHP->pabyRec, nEntitySize, 1,
psSHP->fpSHP ) != 1 )
{
/*
@@ -1474,9 +1553,7 @@
* for example to detect if file is truncated.
*/
-#ifdef USE_CPL
- CPLDebug( "Shape", "Error in fseek() or fread() reading object from .shp file." );
-#endif
+ psSHP->sHooks.Error( "Error in fseek() or fread() reading object from .shp file." );
return NULL;
}
@@ -1487,7 +1564,16 @@
psShape->nShapeId = hEntity;
psShape->bMeasureIsUsed = FALSE;
+ if ( 8 + 4 > nEntitySize )
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
memcpy( &psShape->nSHPType, psSHP->pabyRec + 8, 4 );
+
if( bBigEndian ) SwapWord( 4, &(psShape->nSHPType) );
/* ==================================================================== */
@@ -1503,6 +1589,14 @@
int32 nPoints, nParts;
int i, nOffset;
+ if ( 40 + 8 + 4 > nEntitySize )
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
/* -------------------------------------------------------------------- */
/* Get the X/Y bounds. */
/* -------------------------------------------------------------------- */
@@ -1526,6 +1620,39 @@
if( bBigEndian ) SwapWord( 4, &nPoints );
if( bBigEndian ) SwapWord( 4, &nParts );
+ if (nPoints < 0 || nParts < 0 ||
+ nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
+ hEntity, nPoints, nParts);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
+ /* With the previous checks on nPoints and nParts, */
+ /* we should not overflow here and after */
+ /* since 50 M * (16 + 8 + 8) = 1 600 MB */
+ nRequiredSize = 44 + 8 + 4 * nParts + 16 * nPoints;
+ if ( psShape->nSHPType == SHPT_POLYGONZ
+ || psShape->nSHPType == SHPT_ARCZ
+ || psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ nRequiredSize += 16 + 8 * nPoints;
+ }
+ if( psShape->nSHPType == SHPT_MULTIPATCH )
+ {
+ nRequiredSize += 4 * nParts;
+ }
+ if (nRequiredSize > nEntitySize)
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
+ hEntity, nPoints, nParts, nEntitySize);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
psShape->nVertices = nPoints;
psShape->padfX = (double *) calloc(nPoints,sizeof(double));
psShape->padfY = (double *) calloc(nPoints,sizeof(double));
@@ -1535,6 +1662,21 @@
psShape->nParts = nParts;
psShape->panPartStart = (int *) calloc(nParts,sizeof(int));
psShape->panPartType = (int *) calloc(nParts,sizeof(int));
+
+ if (psShape->padfX == NULL ||
+ psShape->padfY == NULL ||
+ psShape->padfZ == NULL ||
+ psShape->padfM == NULL ||
+ psShape->panPartStart == NULL ||
+ psShape->panPartType == NULL)
+ {
+ snprintf(pszErrorMsg, 128,
+ "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. "
+ "Probably broken SHP file", hEntity, nPoints, nParts );
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
for( i = 0; i < nParts; i++ )
psShape->panPartType[i] = SHPP_RING;
@@ -1546,6 +1688,25 @@
for( i = 0; i < nParts; i++ )
{
if( bBigEndian ) SwapWord( 4, psShape->panPartStart+i );
+
+ /* We check that the offset is inside the vertex array */
+ if (psShape->panPartStart[i] < 0 ||
+ psShape->panPartStart[i] >= psShape->nVertices)
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, nVertices = %d",
+ hEntity, i, psShape->panPartStart[i], psShape->nVertices);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+ if (i > 0 && psShape->panPartStart[i] <= psShape->panPartStart[i-1])
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : panPartStart[%d] = %d, panPartStart[%d] = %d",
+ hEntity, i, psShape->panPartStart[i], i - 1, psShape->panPartStart[i - 1]);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
}
nOffset = 44 + 8 + 4*nParts;
@@ -1612,7 +1773,7 @@
/* big enough, but really it will only occur for the Z shapes */
/* (options), and the M shapes. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ if( nEntitySize >= nOffset + 16 + 8*nPoints )
{
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -1640,15 +1801,60 @@
int32 nPoints;
int i, nOffset;
+ if ( 44 + 4 > nEntitySize )
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
+
if( bBigEndian ) SwapWord( 4, &nPoints );
+ if (nPoints < 0 || nPoints > 50 * 1000 * 1000)
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d",
+ hEntity, nPoints);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
+ nRequiredSize = 48 + nPoints * 16;
+ if( psShape->nSHPType == SHPT_MULTIPOINTZ )
+ {
+ nRequiredSize += 16 + nPoints * 8;
+ }
+ if (nRequiredSize > nEntitySize)
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
+ hEntity, nPoints, nEntitySize);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
psShape->nVertices = nPoints;
psShape->padfX = (double *) calloc(nPoints,sizeof(double));
psShape->padfY = (double *) calloc(nPoints,sizeof(double));
psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
psShape->padfM = (double *) calloc(nPoints,sizeof(double));
+ if (psShape->padfX == NULL ||
+ psShape->padfY == NULL ||
+ psShape->padfZ == NULL ||
+ psShape->padfM == NULL)
+ {
+ snprintf(pszErrorMsg, 128,
+ "Not enough memory to allocate requested memory (nPoints=%d) for shape %d. "
+ "Probably broken SHP file", hEntity, nPoints );
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
+
for( i = 0; i < nPoints; i++ )
{
memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
@@ -1700,7 +1906,7 @@
/* big enough, but really it will only occur for the Z shapes */
/* (options), and the M shapes. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
+ if( nEntitySize >= nOffset + 16 + 8*nPoints )
{
memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
@@ -1733,6 +1939,14 @@
psShape->padfZ = (double *) calloc(1,sizeof(double));
psShape->padfM = (double *) calloc(1,sizeof(double));
+ if (20 + 8 + (( psShape->nSHPType == SHPT_POINTZ ) ? 8 : 0)> nEntitySize)
+ {
+ snprintf(pszErrorMsg, 128, "Corrupted .shp file : shape %d : nEntitySize = %d",
+ hEntity, nEntitySize);
+ psSHP->sHooks.Error( pszErrorMsg );
+ SHPDestroyObject(psShape);
+ return NULL;
+ }
memcpy( psShape->padfX, psSHP->pabyRec + 12, 8 );
memcpy( psShape->padfY, psSHP->pabyRec + 20, 8 );
@@ -1759,7 +1973,7 @@
/* big enough, but really it will only occur for the Z shapes */
/* (options), and the M shapes. */
/* -------------------------------------------------------------------- */
- if( psSHP->panRecSize[hEntity]+8 >= nOffset + 8 )
+ if( nEntitySize >= nOffset + 8 )
{
memcpy( psShape->padfM, psSHP->pabyRec + nOffset, 8 );
@@ -1985,7 +2199,7 @@
/* Rule #2:
* Test if edge-ray intersection is on the right from the test point (dfTestY,dfTestY)
*/
- float const intersect =
+ double const intersect =
( psObject->padfX[iEdge+nVertStart]
+ ( dfTestY - psObject->padfY[iEdge+nVertStart] )
/ ( psObject->padfY[iNext+nVertStart] - psObject->padfY[iEdge+nVertStart] )
More information about the grass-commit
mailing list