LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/shape - shp_vsi.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 72 81 88.9 %
Date: 2025-01-18 12:42:00 Functions: 15 16 93.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  IO Redirection via VSI services for shp/dbf io.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2007,  Frank Warmerdam
       9             :  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "shp_vsi.h"
      15             : #include "cpl_error.h"
      16             : #include "cpl_conv.h"
      17             : #include "cpl_vsi_error.h"
      18             : #include <limits.h>
      19             : 
      20             : #include "shapefil_private.h"
      21             : 
      22             : typedef struct
      23             : {
      24             :     VSILFILE *fp;
      25             :     char *pszFilename;
      26             :     int bEnforce2GBLimit;
      27             :     int bHasWarned2GB;
      28             :     SAOffset nCurOffset;
      29             : } OGRSHPDBFFile;
      30             : 
      31             : /************************************************************************/
      32             : /*                         VSI_SHP_OpenInternal()                       */
      33             : /************************************************************************/
      34             : 
      35       26103 : static SAFile VSI_SHP_OpenInternal(const char *pszFilename,
      36             :                                    const char *pszAccess, int bEnforce2GBLimit)
      37             : 
      38             : {
      39             :     OGRSHPDBFFile *pFile;
      40       26103 :     VSILFILE *fp = VSIFOpenExL(pszFilename, pszAccess, TRUE);
      41       26103 :     if (fp == SHPLIB_NULLPTR)
      42       11170 :         return SHPLIB_NULLPTR;
      43       14933 :     pFile = (OGRSHPDBFFile *)CPLCalloc(1, sizeof(OGRSHPDBFFile));
      44       14933 :     pFile->fp = fp;
      45       14933 :     pFile->pszFilename = CPLStrdup(pszFilename);
      46       14933 :     pFile->bEnforce2GBLimit = bEnforce2GBLimit;
      47       14933 :     pFile->nCurOffset = 0;
      48       14933 :     return (SAFile)pFile;
      49             : }
      50             : 
      51             : /************************************************************************/
      52             : /*                            VSI_SHP_Open()                            */
      53             : /************************************************************************/
      54             : 
      55       26103 : static SAFile VSI_SHP_Open(const char *pszFilename, const char *pszAccess,
      56             :                            void *userData)
      57             : 
      58             : {
      59             :     (void)userData;
      60       26103 :     return VSI_SHP_OpenInternal(pszFilename, pszAccess, FALSE);
      61             : }
      62             : 
      63             : /************************************************************************/
      64             : /*                            VSI_SHP_Read()                            */
      65             : /************************************************************************/
      66             : 
      67     2685090 : static SAOffset VSI_SHP_Read(void *p, SAOffset size, SAOffset nmemb,
      68             :                              SAFile file)
      69             : 
      70             : {
      71     2685090 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
      72             :     SAOffset ret =
      73     2685090 :         (SAOffset)VSIFReadL(p, (size_t)size, (size_t)nmemb, pFile->fp);
      74     2685090 :     pFile->nCurOffset += ret * size;
      75     2685090 :     return ret;
      76             : }
      77             : 
      78             : /************************************************************************/
      79             : /*                      VSI_SHP_WriteMoreDataOK()                       */
      80             : /************************************************************************/
      81             : 
      82      359257 : int VSI_SHP_WriteMoreDataOK(SAFile file, SAOffset nExtraBytes)
      83             : {
      84      359257 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
      85      359257 :     if (pFile->nCurOffset + nExtraBytes > INT_MAX)
      86             :     {
      87           0 :         if (pFile->bEnforce2GBLimit)
      88             :         {
      89           0 :             CPLError(CE_Failure, CPLE_AppDefined,
      90             :                      "2GB file size limit reached for %s", pFile->pszFilename);
      91           0 :             return FALSE;
      92             :         }
      93           0 :         else if (!pFile->bHasWarned2GB)
      94             :         {
      95           0 :             pFile->bHasWarned2GB = TRUE;
      96           0 :             CPLError(CE_Warning, CPLE_AppDefined,
      97             :                      "2GB file size limit reached for %s. "
      98             :                      "Going on, but might cause compatibility issues with "
      99             :                      "third party software",
     100             :                      pFile->pszFilename);
     101             :         }
     102             :     }
     103             : 
     104      359257 :     return TRUE;
     105             : }
     106             : 
     107             : /************************************************************************/
     108             : /*                           VSI_SHP_Write()                            */
     109             : /************************************************************************/
     110             : 
     111      295610 : static SAOffset VSI_SHP_Write(const void *p, SAOffset size, SAOffset nmemb,
     112             :                               SAFile file)
     113             : 
     114             : {
     115      295610 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
     116             :     SAOffset ret;
     117      295610 :     if (!VSI_SHP_WriteMoreDataOK(file, size * nmemb))
     118           0 :         return 0;
     119      295610 :     ret = (SAOffset)VSIFWriteL(p, (size_t)size, (size_t)nmemb, pFile->fp);
     120      295610 :     pFile->nCurOffset += ret * size;
     121      295610 :     return ret;
     122             : }
     123             : 
     124             : /************************************************************************/
     125             : /*                            VSI_SHP_Seek()                            */
     126             : /************************************************************************/
     127             : 
     128      801768 : static SAOffset VSI_SHP_Seek(SAFile file, SAOffset offset, int whence)
     129             : 
     130             : {
     131      801768 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
     132      801768 :     SAOffset ret = (SAOffset)VSIFSeekL(pFile->fp, (vsi_l_offset)offset, whence);
     133      801768 :     if (whence == 0 && ret == 0)
     134      439917 :         pFile->nCurOffset = offset;
     135             :     else
     136      361851 :         pFile->nCurOffset = (SAOffset)VSIFTellL(pFile->fp);
     137      801768 :     return ret;
     138             : }
     139             : 
     140             : /************************************************************************/
     141             : /*                            VSI_SHP_Tell()                            */
     142             : /************************************************************************/
     143             : 
     144      133563 : static SAOffset VSI_SHP_Tell(SAFile file)
     145             : 
     146             : {
     147      133563 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
     148      133563 :     return (SAOffset)pFile->nCurOffset;
     149             : }
     150             : 
     151             : /************************************************************************/
     152             : /*                           VSI_SHP_Flush()                            */
     153             : /************************************************************************/
     154             : 
     155        6213 : static int VSI_SHP_Flush(SAFile file)
     156             : 
     157             : {
     158        6213 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
     159        6213 :     return VSIFFlushL(pFile->fp);
     160             : }
     161             : 
     162             : /************************************************************************/
     163             : /*                           VSI_SHP_Close()                            */
     164             : /************************************************************************/
     165             : 
     166       14917 : static int VSI_SHP_Close(SAFile file)
     167             : 
     168             : {
     169       14917 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
     170       14917 :     int ret = VSIFCloseL(pFile->fp);
     171       14917 :     CPLFree(pFile->pszFilename);
     172       14917 :     CPLFree(pFile);
     173       14917 :     return ret;
     174             : }
     175             : 
     176             : /************************************************************************/
     177             : /*                              SADError()                              */
     178             : /************************************************************************/
     179             : 
     180         348 : static void VSI_SHP_Error(const char *message)
     181             : 
     182             : {
     183         348 :     CPLError(CE_Failure, CPLE_AppDefined, "%s", message);
     184         348 : }
     185             : 
     186             : /************************************************************************/
     187             : /*                           VSI_SHP_Remove()                           */
     188             : /************************************************************************/
     189             : 
     190        1591 : static int VSI_SHP_Remove(const char *pszFilename, void *userData)
     191             : 
     192             : {
     193             :     (void)userData;
     194        1591 :     return VSIUnlink(pszFilename);
     195             : }
     196             : 
     197             : /************************************************************************/
     198             : /*                        SASetupDefaultHooks()                         */
     199             : /************************************************************************/
     200             : 
     201        3365 : void SASetupDefaultHooks(SAHooks *psHooks)
     202             : 
     203             : {
     204        3365 :     psHooks->FOpen = VSI_SHP_Open;
     205        3365 :     psHooks->FRead = VSI_SHP_Read;
     206        3365 :     psHooks->FWrite = VSI_SHP_Write;
     207        3365 :     psHooks->FSeek = VSI_SHP_Seek;
     208        3365 :     psHooks->FTell = VSI_SHP_Tell;
     209        3365 :     psHooks->FFlush = VSI_SHP_Flush;
     210        3365 :     psHooks->FClose = VSI_SHP_Close;
     211        3365 :     psHooks->Remove = VSI_SHP_Remove;
     212             : 
     213        3365 :     psHooks->Error = VSI_SHP_Error;
     214        3365 :     psHooks->Atof = CPLAtof;
     215        3365 :     psHooks->pvUserData = SHPLIB_NULLPTR;
     216        3365 : }
     217             : 
     218             : #ifndef SHP_VSI_ONLY_SETUP_HOOKS
     219             : 
     220             : /************************************************************************/
     221             : /*                         VSI_SHP_GetVSIL()                            */
     222             : /************************************************************************/
     223             : 
     224      191464 : VSILFILE *VSI_SHP_GetVSIL(SAFile file)
     225             : {
     226      191464 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
     227      191464 :     return pFile->fp;
     228             : }
     229             : 
     230             : /************************************************************************/
     231             : /*                        VSI_SHP_GetFilename()                         */
     232             : /************************************************************************/
     233             : 
     234         156 : const char *VSI_SHP_GetFilename(SAFile file)
     235             : {
     236         156 :     OGRSHPDBFFile *pFile = (OGRSHPDBFFile *)file;
     237         156 :     return pFile->pszFilename;
     238             : }
     239             : 
     240             : /************************************************************************/
     241             : /*                        VSI_SHP_Open2GBLimit()                        */
     242             : /************************************************************************/
     243             : 
     244           0 : static SAFile VSI_SHP_Open2GBLimit(const char *pszFilename,
     245             :                                    const char *pszAccess, void *userData)
     246             : 
     247             : {
     248             :     (void)userData;
     249           0 :     return VSI_SHP_OpenInternal(pszFilename, pszAccess, TRUE);
     250             : }
     251             : 
     252             : /************************************************************************/
     253             : /*                         VSI_SHP_GetHook()                            */
     254             : /************************************************************************/
     255             : 
     256             : static const SAHooks sOGRHook = {
     257             :     VSI_SHP_Open,  VSI_SHP_Read,  VSI_SHP_Write, VSI_SHP_Seek,
     258             :     VSI_SHP_Tell,  VSI_SHP_Flush, VSI_SHP_Close, VSI_SHP_Remove,
     259             :     VSI_SHP_Error, CPLAtof,       NULL};
     260             : 
     261             : static const SAHooks sOGRHook2GBLimit = {
     262             :     VSI_SHP_Open2GBLimit, VSI_SHP_Read,  VSI_SHP_Write, VSI_SHP_Seek,
     263             :     VSI_SHP_Tell,         VSI_SHP_Flush, VSI_SHP_Close, VSI_SHP_Remove,
     264             :     VSI_SHP_Error,        CPLAtof,       NULL};
     265             : 
     266       10281 : const SAHooks *VSI_SHP_GetHook(int b2GBLimit)
     267             : {
     268       10281 :     return (b2GBLimit) ? &sOGRHook2GBLimit : &sOGRHook;
     269             : }
     270             : 
     271             : #endif

Generated by: LCOV version 1.14