PostGIS 3.7.0dev-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 if( psSHP == SHPLIB_NULLPTR )
371 return SHPLIB_NULLPTR;
372
373 psSHP->bUpdated = FALSE;
374 memcpy( &(psSHP->sHooks), psHooks, sizeof(SAHooks) );
375
376/* -------------------------------------------------------------------- */
377/* Open the .shp and .shx files. Note that files pulled from */
378/* a PC to Unix with upper case filenames won't work! */
379/* -------------------------------------------------------------------- */
380 nLenWithoutExtension = SHPGetLenWithoutExtension(pszLayer);
381 pszFullname = STATIC_CAST(char *, malloc(nLenWithoutExtension + 5));
382 if( pszFullname == SHPLIB_NULLPTR )
383 {
384 free( psSHP );
385 return SHPLIB_NULLPTR;
386 }
387 memcpy(pszFullname, pszLayer, nLenWithoutExtension);
388 memcpy(pszFullname + nLenWithoutExtension, ".shp", 5);
389 psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
390 if( psSHP->fpSHP == SHPLIB_NULLPTR )
391 {
392 memcpy(pszFullname + nLenWithoutExtension, ".SHP", 5);
393 psSHP->fpSHP = psSHP->sHooks.FOpen(pszFullname, pszAccess );
394 }
395
396 if( psSHP->fpSHP == SHPLIB_NULLPTR )
397 {
398 size_t nMessageLen = strlen(pszFullname)*2+256;
399 char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
400 pszFullname[nLenWithoutExtension] = 0;
401 snprintf( pszMessage, nMessageLen, "Unable to open %s.shp or %s.SHP.",
402 pszFullname, pszFullname );
403 psHooks->Error( pszMessage );
404 free( pszMessage );
405
406 free( psSHP );
407 free( pszFullname );
408
409 return SHPLIB_NULLPTR;
410 }
411
412 memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
413 psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
414 if( psSHP->fpSHX == SHPLIB_NULLPTR )
415 {
416 memcpy(pszFullname + nLenWithoutExtension, ".SHX", 5);
417 psSHP->fpSHX = psSHP->sHooks.FOpen(pszFullname, pszAccess );
418 }
419
420 if( psSHP->fpSHX == SHPLIB_NULLPTR )
421 {
422 size_t nMessageLen = strlen(pszFullname)*2+256;
423 char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
424 pszFullname[nLenWithoutExtension] = 0;
425 snprintf( pszMessage, nMessageLen, "Unable to open %s.shx or %s.SHX. "
426 "Set SHAPE_RESTORE_SHX config option to YES to restore or "
427 "create it.", pszFullname, pszFullname );
428 psHooks->Error( pszMessage );
429 free( pszMessage );
430
431 psSHP->sHooks.FClose( psSHP->fpSHP );
432 free( psSHP );
433 free( pszFullname );
434 return SHPLIB_NULLPTR ;
435 }
436
437 free( pszFullname );
438
439/* -------------------------------------------------------------------- */
440/* Read the file size from the SHP file. */
441/* -------------------------------------------------------------------- */
442 pabyBuf = STATIC_CAST(uchar *, malloc(100));
443 if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP ) != 1 )
444 {
445 psSHP->sHooks.Error( ".shp file is unreadable, or corrupt." );
446 psSHP->sHooks.FClose( psSHP->fpSHP );
447 psSHP->sHooks.FClose( psSHP->fpSHX );
448 free( pabyBuf );
449 free( psSHP );
450
451 return SHPLIB_NULLPTR ;
452 }
453
454 psSHP->nFileSize = (STATIC_CAST(unsigned int, pabyBuf[24])<<24)|(pabyBuf[25]<<16)|
455 (pabyBuf[26]<<8)|pabyBuf[27];
456 if( psSHP->nFileSize < UINT_MAX / 2 )
457 psSHP->nFileSize *= 2;
458 else
459 psSHP->nFileSize = (UINT_MAX / 2) * 2;
460
461/* -------------------------------------------------------------------- */
462/* Read SHX file Header info */
463/* -------------------------------------------------------------------- */
464 if( psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHX ) != 1
465 || pabyBuf[0] != 0
466 || pabyBuf[1] != 0
467 || pabyBuf[2] != 0x27
468 || (pabyBuf[3] != 0x0a && pabyBuf[3] != 0x0d) )
469 {
470 psSHP->sHooks.Error( ".shx file is unreadable, or corrupt." );
471 psSHP->sHooks.FClose( psSHP->fpSHP );
472 psSHP->sHooks.FClose( psSHP->fpSHX );
473 free( pabyBuf );
474 free( psSHP );
475
476 return SHPLIB_NULLPTR;
477 }
478
479 psSHP->nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
480 ((pabyBuf[24] & 0x7F)<<24);
481 psSHP->nRecords = (psSHP->nRecords - 50) / 4;
482
483 psSHP->nShapeType = pabyBuf[32];
484
485 if( psSHP->nRecords < 0 || psSHP->nRecords > 256000000 )
486 {
487 char szErrorMsg[200];
488
489 snprintf( szErrorMsg, sizeof(szErrorMsg),
490 "Record count in .shp header is %d, which seems\n"
491 "unreasonable. Assuming header is corrupt.",
492 psSHP->nRecords );
493 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
494 psSHP->sHooks.Error( szErrorMsg );
495 psSHP->sHooks.FClose( psSHP->fpSHP );
496 psSHP->sHooks.FClose( psSHP->fpSHX );
497 free( psSHP );
498 free(pabyBuf);
499
500 return SHPLIB_NULLPTR;
501 }
502
503 /* If a lot of records are advertised, check that the file is big enough */
504 /* to hold them */
505 if( psSHP->nRecords >= 1024 * 1024 )
506 {
507 SAOffset nFileSize;
508 psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 2 );
509 nFileSize = psSHP->sHooks.FTell( psSHP->fpSHX );
510 if( nFileSize > 100 &&
511 nFileSize/2 < STATIC_CAST(SAOffset, psSHP->nRecords * 4 + 50) )
512 {
513 psSHP->nRecords = STATIC_CAST(int, (nFileSize - 100) / 8);
514 }
515 psSHP->sHooks.FSeek( psSHP->fpSHX, 100, 0 );
516 }
517
518/* -------------------------------------------------------------------- */
519/* Read the bounds. */
520/* -------------------------------------------------------------------- */
521 if( bBigEndian ) SwapWord( 8, pabyBuf+36 );
522 memcpy( &dValue, pabyBuf+36, 8 );
523 psSHP->adBoundsMin[0] = dValue;
524
525 if( bBigEndian ) SwapWord( 8, pabyBuf+44 );
526 memcpy( &dValue, pabyBuf+44, 8 );
527 psSHP->adBoundsMin[1] = dValue;
528
529 if( bBigEndian ) SwapWord( 8, pabyBuf+52 );
530 memcpy( &dValue, pabyBuf+52, 8 );
531 psSHP->adBoundsMax[0] = dValue;
532
533 if( bBigEndian ) SwapWord( 8, pabyBuf+60 );
534 memcpy( &dValue, pabyBuf+60, 8 );
535 psSHP->adBoundsMax[1] = dValue;
536
537 if( bBigEndian ) SwapWord( 8, pabyBuf+68 ); /* z */
538 memcpy( &dValue, pabyBuf+68, 8 );
539 psSHP->adBoundsMin[2] = dValue;
540
541 if( bBigEndian ) SwapWord( 8, pabyBuf+76 );
542 memcpy( &dValue, pabyBuf+76, 8 );
543 psSHP->adBoundsMax[2] = dValue;
544
545 if( bBigEndian ) SwapWord( 8, pabyBuf+84 ); /* z */
546 memcpy( &dValue, pabyBuf+84, 8 );
547 psSHP->adBoundsMin[3] = dValue;
548
549 if( bBigEndian ) SwapWord( 8, pabyBuf+92 );
550 memcpy( &dValue, pabyBuf+92, 8 );
551 psSHP->adBoundsMax[3] = dValue;
552
553 free( pabyBuf );
554
555/* -------------------------------------------------------------------- */
556/* Read the .shx file to get the offsets to each record in */
557/* the .shp file. */
558/* -------------------------------------------------------------------- */
559 psSHP->nMaxRecords = psSHP->nRecords;
560
561 psSHP->panRecOffset = STATIC_CAST(unsigned int *,
562 malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
563 psSHP->panRecSize = STATIC_CAST(unsigned int *,
564 malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) ));
565 if( bLazySHXLoading )
566 pabyBuf = SHPLIB_NULLPTR;
567 else
568 pabyBuf = STATIC_CAST(uchar *, malloc(8 * MAX(1,psSHP->nRecords) ));
569
570 if (psSHP->panRecOffset == SHPLIB_NULLPTR ||
571 psSHP->panRecSize == SHPLIB_NULLPTR ||
572 (!bLazySHXLoading && pabyBuf == SHPLIB_NULLPTR))
573 {
574 char szErrorMsg[200];
575
576 snprintf( szErrorMsg, sizeof(szErrorMsg),
577 "Not enough memory to allocate requested memory (nRecords=%d).\n"
578 "Probably broken SHP file",
579 psSHP->nRecords );
580 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
581 psSHP->sHooks.Error( szErrorMsg );
582 psSHP->sHooks.FClose( psSHP->fpSHP );
583 psSHP->sHooks.FClose( psSHP->fpSHX );
584 if (psSHP->panRecOffset) free( psSHP->panRecOffset );
585 if (psSHP->panRecSize) free( psSHP->panRecSize );
586 if (pabyBuf) free( pabyBuf );
587 free( psSHP );
588 return SHPLIB_NULLPTR;
589 }
590
591 if( bLazySHXLoading )
592 {
593 memset(psSHP->panRecOffset, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
594 memset(psSHP->panRecSize, 0, sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
595 free( pabyBuf ); // sometimes make cppcheck happy, but
596 return( psSHP );
597 }
598
599 if( STATIC_CAST(int, psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ))
600 != psSHP->nRecords )
601 {
602 char szErrorMsg[200];
603
604 snprintf( szErrorMsg, sizeof(szErrorMsg),
605 "Failed to read all values for %d records in .shx file: %s.",
606 psSHP->nRecords, strerror(errno) );
607 szErrorMsg[sizeof(szErrorMsg)-1] = '\0';
608 psSHP->sHooks.Error( szErrorMsg );
609
610 /* SHX is short or unreadable for some reason. */
611 psSHP->sHooks.FClose( psSHP->fpSHP );
612 psSHP->sHooks.FClose( psSHP->fpSHX );
613 free( psSHP->panRecOffset );
614 free( psSHP->panRecSize );
615 free( pabyBuf );
616 free( psSHP );
617
618 return SHPLIB_NULLPTR;
619 }
620
621 /* In read-only mode, we can close the SHX now */
622 if (strcmp(pszAccess, "rb") == 0)
623 {
624 psSHP->sHooks.FClose( psSHP->fpSHX );
625 psSHP->fpSHX = SHPLIB_NULLPTR;
626 }
627
628 for( i = 0; i < psSHP->nRecords; i++ )
629 {
630 unsigned int nOffset, nLength;
631
632 memcpy( &nOffset, pabyBuf + i * 8, 4 );
633 if( !bBigEndian ) SwapWord( 4, &nOffset );
634
635 memcpy( &nLength, pabyBuf + i * 8 + 4, 4 );
636 if( !bBigEndian ) SwapWord( 4, &nLength );
637
638 if( nOffset > STATIC_CAST(unsigned int, INT_MAX) )
639 {
640 char str[128];
641 snprintf( str, sizeof(str),
642 "Invalid offset for entity %d", i);
643 str[sizeof(str)-1] = '\0';
644
645 psSHP->sHooks.Error( str );
646 SHPClose(psSHP);
647 free( pabyBuf );
648 return SHPLIB_NULLPTR;
649 }
650 if( nLength > STATIC_CAST(unsigned int, INT_MAX / 2 - 4) )
651 {
652 char str[128];
653 snprintf( str, sizeof(str),
654 "Invalid length for entity %d", i);
655 str[sizeof(str)-1] = '\0';
656
657 psSHP->sHooks.Error( str );
658 SHPClose(psSHP);
659 free( pabyBuf );
660 return SHPLIB_NULLPTR;
661 }
662 psSHP->panRecOffset[i] = nOffset*2;
663 psSHP->panRecSize[i] = nLength*2;
664 }
665 free( pabyBuf );
666
667 return( psSHP );
668}
#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:888
#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: