PostGIS 3.6.2dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ SHPOpenLL()

SHPHandle SHPAPI_CALL SHPOpenLL ( const char *  pszShapeFile,
const char *  pszAccess,
SAHooks psHooks 
)

Definition at line 329 of file shpopen.c.

331{
332 char *pszFullname;
333 SHPHandle psSHP;
334
335 uchar *pabyBuf;
336 int i;
337 double dValue;
338 int bLazySHXLoading = FALSE;
339 int nLenWithoutExtension;
340
341/* -------------------------------------------------------------------- */
342/* Ensure the access string is one of the legal ones. We */
343/* ensure the result string indicates binary to avoid common */
344/* problems on Windows. */
345/* -------------------------------------------------------------------- */
346 if( strcmp(pszAccess,"rb+") == 0 || strcmp(pszAccess,"r+b") == 0
347 || strcmp(pszAccess,"r+") == 0 )
348 pszAccess = "r+b";
349 else
350 {
351 bLazySHXLoading = strchr(pszAccess, 'l') != SHPLIB_NULLPTR;
352 pszAccess = "rb";
353 }
354
355/* -------------------------------------------------------------------- */
356/* Establish the byte order on this machine. */
357/* -------------------------------------------------------------------- */
358#if !defined(bBigEndian)
359 i = 1;
360 if( *((uchar *) &i) == 1 )
362 else
364#endif
365
366/* -------------------------------------------------------------------- */
367/* Initialize the info structure. */
368/* -------------------------------------------------------------------- */
369 psSHP = STATIC_CAST(SHPHandle, calloc(1,sizeof(SHPInfo)));
370
371 psSHP->bUpdated = FALSE;
372 memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
373
374/* -------------------------------------------------------------------- */
375/* Open the .shp and .shx files. Note that files pulled from */
376/* a PC to Unix with upper case filenames won't work! */
377/* -------------------------------------------------------------------- */
378 nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
379 pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
380 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
381 memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
382 psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
383 if( psSHP->fpSHP == SHPLIB_NULLPTR )
384 {
385 memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
386 psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
387 }
388
389 if( psSHP->fpSHP == SHPLIB_NULLPTR )
390 {
391 size_t nMessageLen = strlen(pszFullname)*2+256;
392 char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
393 pszFullname[nLenWithoutExtension] = 0;
394 snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
395 pszFullname, pszFullname );
396 psHooks->Error( pszMessage );
397 free( pszMessage );
398
399 free( psSHP );
400 free( pszFullname );
401
402 return SHPLIB_NULLPTR;
403 }
404
405 memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
406 psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
407 if( psSHP->fpSHX == SHPLIB_NULLPTR )
408 {
409 memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
410 psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
411 }
412
413 if( psSHP->fpSHX == SHPLIB_NULLPTR )
414 {
415 size_t nMessageLen = strlen(pszFullname)*2+256;
416 char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
417 pszFullname[nLenWithoutExtension] = 0;
418 snprintf( pszMessage, nMessageLen, "Unable to open %s.shx or %s.SHX. "
419 "Set SHAPE_RESTORE_SHX config option to YES to restore or "
420 "create it.", pszFullname, pszFullname );
421 psHooks->Error( pszMessage );
422 free( pszMessage );
423
424 psSHP->sHooks.FClose( psSHP->fpSHP );
425 free( psSHP );
426 free( pszFullname );
427 return SHPLIB_NULLPTR ;
428 }
429
430 free( pszFullname );
431
432/* -------------------------------------------------------------------- */
433/* Read the file size from the SHP file. */
434/* -------------------------------------------------------------------- */
435 pabyBuf = STATIC_CAST(uchar *, malloc(100));
436 if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP ) != 1 )
437 {
438 psSHP->sHooks.Error( ".shp file is unreadable, or corrupt." );
439 psSHP->sHooks.FClose( psSHP->fpSHP );
440 psSHP->sHooks.FClose( psSHP->fpSHX );
441 free( pabyBuf );
442 free( psSHP );
443
444 return SHPLIB_NULLPTR ;
445 }
446
447 psSHP->nFileSize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
448 (pabyBuf[26]<<8)|pabyBuf[27];
449 if( psSHP->nFileSize < UINT_MAX / 2 )
450 psSHP->nFileSize *= 2;
451 else
452 psSHP->nFileSize = (UINT_MAX / 2) * 2;
453
454/* -------------------------------------------------------------------- */
455/* Read SHX file Header info */
456/* -------------------------------------------------------------------- */
457 if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
458 || pabyBuf[0] != 0
459 || pabyBuf[1] != 0
460 || pabyBuf[2] != 0x27
461 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
462 {
463 psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
464 psSHP->sHooks.FClose( psSHP->fpSHP );
465 psSHP->sHooks.FClose( psSHP->fpSHX );
466 free( pabyBuf );
467 free( psSHP );
468
469 return SHPLIB_NULLPTR;
470 }
471
472 psSHP->nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
473 ((pabyBuf[24] & 0x7F)<<24);
474 psSHP->nRecords = (psSHP->nRecords - 50) / 4;
475
476 psSHP->nShapeType = pabyBuf[32];
477
478 if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
479 {
480 char szErrorMsg[200];
481
482 snprintf( szErrorMsg, sizeof(szErrorMsg),
483 "Record count in .shp header is %d, which seems\n"
484 "unreasonable. Assuming header is corrupt.",
485 psSHP->nRecords );
486 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
487 psSHP->sHooks.Error( szErrorMsg );
488 psSHP->sHooks.FClose( psSHP->fpSHP );
489 psSHP->sHooks.FClose( psSHP->fpSHX );
490 free( psSHP );
491 free(pabyBuf);
492
493 return SHPLIB_NULLPTR;
494 }
495
496 /* If a lot of records are advertised, check that the file is big enough */
497 /* to hold them */
498 if( psSHP->nRecords >= 1024 * 1024 )
499 {
500 SAOffset nFileSize;
501 psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 2 );
502 nFileSize = psSHP->sHooks.FTell( psSHP->fpSHX );
503 if( nFileSize > 100 &&
504 nFileSize/2 < STATIC_CAST(SAOffset, psSHP->nRecords * 4 + 50) )
505 {
506 psSHP->nRecords = STATIC_CAST(int, (nFileSize - 100) / 8);
507 }
508 psSHP->sHooks.FSeek( psSHP->fpSHX, 100, 0 );
509 }
510
511/* -------------------------------------------------------------------- */
512/* Read the bounds. */
513/* -------------------------------------------------------------------- */
514 if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
515 memcpy( &dValue, pabyBuf+36, 8 );
516 psSHP->adBoundsMin[0] = dValue;
517
518 if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
519 memcpy( &dValue, pabyBuf+44, 8 );
520 psSHP->adBoundsMin[1] = dValue;
521
522 if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
523 memcpy( &dValue, pabyBuf+52, 8 );
524 psSHP->adBoundsMax[0] = dValue;
525
526 if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
527 memcpy( &dValue, pabyBuf+60, 8 );
528 psSHP->adBoundsMax[1] = dValue;
529
530 if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */
531 memcpy( &dValue, pabyBuf+68, 8 );
532 psSHP->adBoundsMin[2] = dValue;
533
534 if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
535 memcpy( &dValue, pabyBuf+76, 8 );
536 psSHP->adBoundsMax[2] = dValue;
537
538 if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* z */
539 memcpy( &dValue, pabyBuf+84, 8 );
540 psSHP->adBoundsMin[3] = dValue;
541
542 if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
543 memcpy( &dValue, pabyBuf+92, 8 );
544 psSHP->adBoundsMax[3] = dValue;
545
546 free( pabyBuf );
547
548/* -------------------------------------------------------------------- */
549/* Read the .shx file to get the offsets to each record in */
550/* the .shp file. */
551/* -------------------------------------------------------------------- */
552 psSHP->nMaxRecords = psSHP->nRecords;
553
554 psSHP->panRecOffset = STATIC_CAST(unsigned int *,
555 malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
556 psSHP->panRecSize = STATIC_CAST(unsigned int *,
557 malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
558 if( bLazySHXLoading )
559 pabyBuf = SHPLIB_NULLPTR;
560 else
561 pabyBuf = STATIC_CAST(uchar *, malloc(8 * MAX(1,psSHP->nRecords) ));
562
563 if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
564 psSHP->panRecSize == SHPLIB_NULLPTR ||
565 (!bLazySHXLoading && pabyBuf == SHPLIB_NULLPTR))
566 {
567 char szErrorMsg[200];
568
569 snprintf( szErrorMsg, sizeof(szErrorMsg),
570 "Not enough memory to allocate requested memory (nRecords=%d).\n"
571 "Probably broken SHP file",
572 psSHP->nRecords );
573 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
574 psSHP->sHooks.Error( szErrorMsg );
575 psSHP->sHooks.FClose( psSHP->fpSHP );
576 psSHP->sHooks.FClose( psSHP->fpSHX );
577 if (psSHP->panRecOffset) free( psSHP->panRecOffset );
578 if (psSHP->panRecSize) free( psSHP->panRecSize );
579 if (pabyBuf) free( pabyBuf );
580 free( psSHP );
581 return SHPLIB_NULLPTR;
582 }
583
584 if( bLazySHXLoading )
585 {
586 memset(psSHP->panRecOffset, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
587 memset(psSHP->panRecSize, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
588 free( pabyBuf ); // sometimes make cppcheck happy, but
589 return( psSHP );
590 }
591
592 if( STATIC_CAST(int, psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ))
593 != psSHP->nRecords )
594 {
595 char szErrorMsg[200];
596
597 snprintf( szErrorMsg, sizeof(szErrorMsg),
598 "Failed to read all values for %d records in .shx file: %s.",
599 psSHP->nRecords, strerror(errno) );
600 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
601 psSHP->sHooks.Error( szErrorMsg );
602
603 /* SHX is short or unreadable for some reason. */
604 psSHP->sHooks.FClose( psSHP->fpSHP );
605 psSHP->sHooks.FClose( psSHP->fpSHX );
606 free( psSHP->panRecOffset );
607 free( psSHP->panRecSize );
608 free( pabyBuf );
609 free( psSHP );
610
611 return SHPLIB_NULLPTR;
612 }
613
614 /* In read-only mode, we can close the SHX now */
615 if (strcmp(pszAccess, "rb") == 0)
616 {
617 psSHP->sHooks.FClose( psSHP->fpSHX );
618 psSHP->fpSHX = SHPLIB_NULLPTR;
619 }
620
621 for( i = 0; i < psSHP->nRecords; i++ )
622 {
623 unsigned int nOffset, nLength;
624
625 memcpy( &nOffset, pabyBuf + i * 8, 4 );
626 if( !bBigEndian ) SwapWord( 4, &nOffset );
627
628 memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
629 if( !bBigEndian ) SwapWord( 4, &nLength );
630
631 if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
632 {
633 char str[128];
634 snprintf( str, sizeof(str),
635 "Invalid offset for entity %d", i);
636 str[sizeof(str)-1] = '\0';
637
638 psSHP->sHooks.Error( str );
639 SHPClose(psSHP);
640 free( pabyBuf );
641 return SHPLIB_NULLPTR;
642 }
643 if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
644 {
645 char str[128];
646 snprintf( str, sizeof(str),
647 "Invalid length for entity %d", i);
648 str[sizeof(str)-1] = '\0';
649
650 psSHP->sHooks.Error( str );
651 SHPClose(psSHP);
652 free( pabyBuf );
653 return SHPLIB_NULLPTR;
654 }
655 psSHP->panRecOffset[i] = nOffset*2;
656 psSHP->panRecSize[i] = nLength*2;
657 }
658 free( pabyBuf );
659
660 return( psSHP );
661}
#define str(s)
void * malloc(YYSIZE_T)
void free(void *)
unsigned long SAOffset
Definition shapefil.h:286
static int bBigEndian
Definition shpopen.c:93
unsigned char uchar
Definition shpopen.c:49
static void SwapWord(int length, void *wordP)
Definition shpopen.c:110
static int SHPGetLenWithoutExtension(const char *pszBasename)
Definition shpopen.c:305
void SHPAPI_CALL SHPClose(SHPHandle psSHP)
Definition shpopen.c:879
#define STATIC_CAST(type, x)
Definition shpopen.c:100
#define TRUE
Definition shpopen.c:59
#define FALSE
Definition shpopen.c:58
#define SHPLIB_NULLPTR
Definition shpopen.c:101
#define MAX(a, b)
Definition shpopen.c:65
void(* Error)(const char *message)
Definition shapefil.h:299
SAFile(* FOpen)(const char *filename, const char *access)
Definition shapefil.h:290
SAOffset(* FTell)(SAFile file)
Definition shapefil.h:294
int(* FClose)(SAFile file)
Definition shapefil.h:296
SAOffset(* FRead)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
Definition shapefil.h:291
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)
Definition shapefil.h:293
SAFile fpSHX
Definition shapefil.h:318
int nShapeType
Definition shapefil.h:320
SAFile fpSHP
Definition shapefil.h:317
int nMaxRecords
Definition shapefil.h:325
unsigned int * panRecSize
Definition shapefil.h:327
SAHooks sHooks
Definition shapefil.h:315
double adBoundsMin[4]
Definition shapefil.h:329
int nRecords
Definition shapefil.h:324
int bUpdated
Definition shapefil.h:332
unsigned int nFileSize
Definition shapefil.h:322
unsigned int * panRecOffset
Definition shapefil.h:326
double adBoundsMax[4]
Definition shapefil.h:330

References SHPInfo::adBoundsMax, SHPInfo::adBoundsMin, bBigEndian, SHPInfo::bUpdated, SAHooks::Error, FALSE, SAHooks::FClose, SAHooks::FOpen, SHPInfo::fpSHP, SHPInfo::fpSHX, SAHooks::FRead, free(), SAHooks::FSeek, SAHooks::FTell, malloc(), MAX, SHPInfo::nFileSize, SHPInfo::nMaxRecords, SHPInfo::nRecords, SHPInfo::nShapeType, SHPInfo::panRecOffset, SHPInfo::panRecSize, SHPInfo::sHooks, SHPClose(), SHPGetLenWithoutExtension(), SHPLIB_NULLPTR, STATIC_CAST, str, SwapWord(), and TRUE.

Referenced by SHPCreateLL(), SHPOpen(), and SHPOpenLLEx().

Here is the call graph for this function:
Here is the caller graph for this function: