LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/shape - shp_vsi.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 72 81 88.9 %
Date: 2025-08-19 18:03:11 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       28390 : static SAFile VSI_SHP_OpenInternal(const char *pszFilename,
      36             :                                    const char *pszAccess, int bEnforce2GBLimit)
      37             : 
      38             : {
      39             :     OGRSHPDBFFile *pFile;
      40       28390 :     VSILFILE *fp = VSIFOpenExL(pszFilename, pszAccess, TRUE);
      41       28390 :     if (fp == SHPLIB_NULLPTR)
      42       12138 :         return SHPLIB_NULLPTR;
      43       16252 :     pFile = static_cast<OGRSHPDBFFile *>(CPLCalloc(1, sizeof(OGRSHPDBFFile)));
      44       16252 :     pFile->fp = fp;
      45       16252 :     pFile->pszFilename = CPLStrdup(pszFilename);
      46       16252 :     pFile->bEnforce2GBLimit = bEnforce2GBLimit;
      47       16252 :     pFile->nCurOffset = 0;
      48       16252 :     return reinterpret_cast<SAFile>(pFile);
      49             : }
      50             : 
      51             : /************************************************************************/
      52             : /*                            VSI_SHP_Open()                            */
      53             : /************************************************************************/
      54             : 
      55       28390 : static SAFile VSI_SHP_Open(const char *pszFilename, const char *pszAccess,
      56             :                            void *userData)
      57             : 
      58             : {
      59             :     (void)userData;
      60       28390 :     return VSI_SHP_OpenInternal(pszFilename, pszAccess, FALSE);
      61             : }
      62             : 
      63             : /************************************************************************/
      64             : /*                            VSI_SHP_Read()                            */
      65             : /************************************************************************/
      66             : 
      67     2696940 : static SAOffset VSI_SHP_Read(void *p, SAOffset size, SAOffset nmemb,
      68             :                              SAFile file)
      69             : 
      70             : {
      71     2696940 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
      72     2696940 :     SAOffset ret = static_cast<SAOffset>(VSIFReadL(
      73             :         p, static_cast<size_t>(size), static_cast<size_t>(nmemb), pFile->fp));
      74     2696940 :     pFile->nCurOffset += ret * size;
      75     2696940 :     return ret;
      76             : }
      77             : 
      78             : /************************************************************************/
      79             : /*                      VSI_SHP_WriteMoreDataOK()                       */
      80             : /************************************************************************/
      81             : 
      82      364616 : int VSI_SHP_WriteMoreDataOK(SAFile file, SAOffset nExtraBytes)
      83             : {
      84      364616 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
      85      364616 :     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      364616 :     return TRUE;
     105             : }
     106             : 
     107             : /************************************************************************/
     108             : /*                           VSI_SHP_Write()                            */
     109             : /************************************************************************/
     110             : 
     111      299870 : static SAOffset VSI_SHP_Write(const void *p, SAOffset size, SAOffset nmemb,
     112             :                               SAFile file)
     113             : 
     114             : {
     115      299870 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
     116             :     SAOffset ret;
     117      299870 :     if (!VSI_SHP_WriteMoreDataOK(file, size * nmemb))
     118           0 :         return 0;
     119      299870 :     ret = static_cast<SAOffset>(VSIFWriteL(
     120             :         p, static_cast<size_t>(size), static_cast<size_t>(nmemb), pFile->fp));
     121      299870 :     pFile->nCurOffset += ret * size;
     122      299870 :     return ret;
     123             : }
     124             : 
     125             : /************************************************************************/
     126             : /*                            VSI_SHP_Seek()                            */
     127             : /************************************************************************/
     128             : 
     129      815162 : static SAOffset VSI_SHP_Seek(SAFile file, SAOffset offset, int whence)
     130             : 
     131             : {
     132      815162 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
     133      815162 :     int ret = VSIFSeekL(pFile->fp, static_cast<vsi_l_offset>(offset), whence);
     134      815162 :     if (whence == 0 && ret == 0)
     135      453676 :         pFile->nCurOffset = offset;
     136             :     else
     137      361486 :         pFile->nCurOffset = static_cast<SAOffset>(VSIFTellL(pFile->fp));
     138      815162 :     return ret;
     139             : }
     140             : 
     141             : /************************************************************************/
     142             : /*                            VSI_SHP_Tell()                            */
     143             : /************************************************************************/
     144             : 
     145      135695 : static SAOffset VSI_SHP_Tell(SAFile file)
     146             : 
     147             : {
     148      135695 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
     149      135695 :     return static_cast<SAOffset>(pFile->nCurOffset);
     150             : }
     151             : 
     152             : /************************************************************************/
     153             : /*                           VSI_SHP_Flush()                            */
     154             : /************************************************************************/
     155             : 
     156        6600 : static int VSI_SHP_Flush(SAFile file)
     157             : 
     158             : {
     159        6600 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
     160        6600 :     return VSIFFlushL(pFile->fp);
     161             : }
     162             : 
     163             : /************************************************************************/
     164             : /*                           VSI_SHP_Close()                            */
     165             : /************************************************************************/
     166             : 
     167       16236 : static int VSI_SHP_Close(SAFile file)
     168             : 
     169             : {
     170       16236 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
     171       16236 :     int ret = VSIFCloseL(pFile->fp);
     172       16236 :     CPLFree(pFile->pszFilename);
     173       16236 :     CPLFree(pFile);
     174       16236 :     return ret;
     175             : }
     176             : 
     177             : /************************************************************************/
     178             : /*                              SADError()                              */
     179             : /************************************************************************/
     180             : 
     181         356 : static void VSI_SHP_Error(const char *message)
     182             : 
     183             : {
     184         356 :     CPLError(CE_Failure, CPLE_AppDefined, "%s", message);
     185         356 : }
     186             : 
     187             : /************************************************************************/
     188             : /*                           VSI_SHP_Remove()                           */
     189             : /************************************************************************/
     190             : 
     191        1679 : static int VSI_SHP_Remove(const char *pszFilename, void *userData)
     192             : 
     193             : {
     194             :     (void)userData;
     195        1679 :     return VSIUnlink(pszFilename);
     196             : }
     197             : 
     198             : /************************************************************************/
     199             : /*                        SASetupDefaultHooks()                         */
     200             : /************************************************************************/
     201             : 
     202        3575 : void SASetupDefaultHooks(SAHooks *psHooks)
     203             : 
     204             : {
     205        3575 :     psHooks->FOpen = VSI_SHP_Open;
     206        3575 :     psHooks->FRead = VSI_SHP_Read;
     207        3575 :     psHooks->FWrite = VSI_SHP_Write;
     208        3575 :     psHooks->FSeek = VSI_SHP_Seek;
     209        3575 :     psHooks->FTell = VSI_SHP_Tell;
     210        3575 :     psHooks->FFlush = VSI_SHP_Flush;
     211        3575 :     psHooks->FClose = VSI_SHP_Close;
     212        3575 :     psHooks->Remove = VSI_SHP_Remove;
     213             : 
     214        3575 :     psHooks->Error = VSI_SHP_Error;
     215        3575 :     psHooks->Atof = CPLAtof;
     216        3575 :     psHooks->pvUserData = SHPLIB_NULLPTR;
     217        3575 : }
     218             : 
     219             : #ifndef SHP_VSI_ONLY_SETUP_HOOKS
     220             : 
     221             : /************************************************************************/
     222             : /*                         VSI_SHP_GetVSIL()                            */
     223             : /************************************************************************/
     224             : 
     225      201810 : VSILFILE *VSI_SHP_GetVSIL(SAFile file)
     226             : {
     227      201810 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
     228      201810 :     return pFile->fp;
     229             : }
     230             : 
     231             : /************************************************************************/
     232             : /*                        VSI_SHP_GetFilename()                         */
     233             : /************************************************************************/
     234             : 
     235         156 : const char *VSI_SHP_GetFilename(SAFile file)
     236             : {
     237         156 :     OGRSHPDBFFile *pFile = reinterpret_cast<OGRSHPDBFFile *>(file);
     238         156 :     return pFile->pszFilename;
     239             : }
     240             : 
     241             : /************************************************************************/
     242             : /*                        VSI_SHP_Open2GBLimit()                        */
     243             : /************************************************************************/
     244             : 
     245           0 : static SAFile VSI_SHP_Open2GBLimit(const char *pszFilename,
     246             :                                    const char *pszAccess, void *userData)
     247             : 
     248             : {
     249             :     (void)userData;
     250           0 :     return VSI_SHP_OpenInternal(pszFilename, pszAccess, TRUE);
     251             : }
     252             : 
     253             : /************************************************************************/
     254             : /*                         VSI_SHP_GetHook()                            */
     255             : /************************************************************************/
     256             : 
     257             : static const SAHooks sOGRHook = {VSI_SHP_Open,  VSI_SHP_Read,   VSI_SHP_Write,
     258             :                                  VSI_SHP_Seek,  VSI_SHP_Tell,   VSI_SHP_Flush,
     259             :                                  VSI_SHP_Close, VSI_SHP_Remove, VSI_SHP_Error,
     260             :                                  CPLAtof,       nullptr};
     261             : 
     262             : static const SAHooks sOGRHook2GBLimit = {
     263             :     VSI_SHP_Open2GBLimit, VSI_SHP_Read,  VSI_SHP_Write, VSI_SHP_Seek,
     264             :     VSI_SHP_Tell,         VSI_SHP_Flush, VSI_SHP_Close, VSI_SHP_Remove,
     265             :     VSI_SHP_Error,        CPLAtof,       nullptr};
     266             : 
     267       11178 : const SAHooks *VSI_SHP_GetHook(int b2GBLimit)
     268             : {
     269       11178 :     return (b2GBLimit) ? &sOGRHook2GBLimit : &sOGRHook;
     270             : }
     271             : 
     272             : #endif

Generated by: LCOV version 1.14