LCOV - code coverage report
Current view: top level - frmts/gtiff - tifvsi.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 249 263 94.7 %
Date: 2024-05-18 15:15:27 Functions: 25 25 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GeoTIFF Driver
       4             :  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
       5             :  *           including > 2GB support.  Based on tif_unix.c from libtiff
       6             :  *           distribution.
       7             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8             :  *
       9             :  ******************************************************************************
      10             :  * Copyright (c) 2005, Frank Warmerdam, warmerdam@pobox.com
      11             :  * Copyright (c) 2010-2012, Even Rouault <even dot rouault at spatialys.com>
      12             :  *
      13             :  * Permission is hereby granted, free of charge, to any person obtaining a
      14             :  * copy of this software and associated documentation files (the "Software"),
      15             :  * to deal in the Software without restriction, including without limitation
      16             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17             :  * and/or sell copies of the Software, and to permit persons to whom the
      18             :  * Software is furnished to do so, subject to the following conditions:
      19             :  *
      20             :  * The above copyright notice and this permission notice shall be included
      21             :  * in all copies or substantial portions of the Software.
      22             :  *
      23             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29             :  * DEALINGS IN THE SOFTWARE.
      30             :  ****************************************************************************/
      31             : 
      32             : // TIFF Library UNIX-specific Routines.
      33             : 
      34             : #include "cpl_port.h"
      35             : #include "tifvsi.h"
      36             : 
      37             : #include <assert.h>
      38             : #include <string.h>
      39             : #include <cerrno>
      40             : #if HAVE_FCNTL_H
      41             : #include <fcntl.h>
      42             : #endif
      43             : 
      44             : #include "cpl_conv.h"
      45             : #include "cpl_vsi.h"
      46             : #include "cpl_string.h"
      47             : 
      48             : // We avoid including xtiffio.h since it drags in the libgeotiff version
      49             : // of the VSI functions.
      50             : 
      51             : #ifdef RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
      52             : #include "gdal_libgeotiff_symbol_rename.h"
      53             : #endif
      54             : 
      55             : #include "xtiffio.h"
      56             : 
      57             : #include <limits>
      58             : 
      59             : #if (TIFFLIB_VERSION > 20220520) || defined(INTERNAL_LIBTIFF)  // > 4.4.0
      60             : #define SUPPORTS_LIBTIFF_OPEN_OPTIONS
      61             : 
      62             : extern int GTiffWarningHandlerExt(TIFF *tif, void *user_data,
      63             :                                   const char *module, const char *fmt,
      64             :                                   va_list ap);
      65             : extern int GTiffErrorHandlerExt(TIFF *tif, void *user_data, const char *module,
      66             :                                 const char *fmt, va_list ap);
      67             : 
      68             : #endif
      69             : 
      70             : constexpr int BUFFER_SIZE = 65536;
      71             : 
      72             : struct GDALTiffHandle;
      73             : 
      74             : struct GDALTiffHandleShared
      75             : {
      76             :     VSILFILE *fpL;
      77             :     bool bReadOnly;
      78             :     bool bLazyStrileLoading;
      79             :     char *pszName;
      80             :     GDALTiffHandle *psActiveHandle;  // only used on the parent
      81             :     int nUserCounter;
      82             :     bool bAtEndOfFile;
      83             :     vsi_l_offset nFileLength;
      84             : };
      85             : 
      86             : struct GDALTiffHandle
      87             : {
      88             :     bool bFree;
      89             : 
      90             :     GDALTiffHandle *psParent;  // nullptr for the parent itself
      91             :     GDALTiffHandleShared *psShared;
      92             : 
      93             :     GByte *abyWriteBuffer;
      94             :     int nWriteBufferSize;
      95             : 
      96             :     // For pseudo-mmap'ed /vsimem/ file
      97             :     vsi_l_offset nDataLength;
      98             :     void *pBase;
      99             : 
     100             :     // If we pre-cached data (typically from /vsicurl/ )
     101             :     int nCachedRanges;
     102             :     void **ppCachedData;
     103             :     vsi_l_offset *panCachedOffsets;
     104             :     size_t *panCachedSizes;
     105             : };
     106             : 
     107             : static bool GTHFlushBuffer(thandle_t th);
     108             : 
     109     3217500 : static void SetActiveGTH(GDALTiffHandle *psGTH)
     110             : {
     111     3217500 :     auto psShared = psGTH->psShared;
     112     3217500 :     if (psShared->psActiveHandle != psGTH)
     113             :     {
     114       15991 :         if (psShared->psActiveHandle != nullptr)
     115             :         {
     116       14504 :             GTHFlushBuffer(static_cast<thandle_t>(psShared->psActiveHandle));
     117             :         }
     118       15991 :         psShared->psActiveHandle = psGTH;
     119             :     }
     120     3217500 : }
     121             : 
     122         228 : void *VSI_TIFFGetCachedRange(thandle_t th, vsi_l_offset nOffset, size_t nSize)
     123             : {
     124         228 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     125         282 :     for (int i = 0; i < psGTH->nCachedRanges; i++)
     126             :     {
     127         282 :         if (nOffset >= psGTH->panCachedOffsets[i] &&
     128         282 :             nOffset + nSize <=
     129         282 :                 psGTH->panCachedOffsets[i] + psGTH->panCachedSizes[i])
     130             :         {
     131         228 :             return static_cast<GByte *>(psGTH->ppCachedData[i]) +
     132         228 :                    (nOffset - psGTH->panCachedOffsets[i]);
     133             :         }
     134          54 :         if (nOffset < psGTH->panCachedOffsets[i])
     135           0 :             break;
     136             :     }
     137           0 :     return nullptr;
     138             : }
     139             : 
     140     2511610 : static tsize_t _tiffReadProc(thandle_t th, tdata_t buf, tsize_t size)
     141             : {
     142     2511610 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     143             :     // SetActiveGTH(psGTH);
     144             : 
     145     2511610 :     if (psGTH->nCachedRanges)
     146             :     {
     147          10 :         const vsi_l_offset nCurOffset = VSIFTellL(psGTH->psShared->fpL);
     148             :         void *data =
     149          10 :             VSI_TIFFGetCachedRange(th, nCurOffset, static_cast<size_t>(size));
     150          10 :         if (data)
     151             :         {
     152          10 :             memcpy(buf, data, size);
     153          10 :             VSIFSeekL(psGTH->psShared->fpL, nCurOffset + size, SEEK_SET);
     154          10 :             return size;
     155             :         }
     156             :     }
     157             : 
     158             : #ifdef DEBUG_VERBOSE_EXTRA
     159             :     CPLDebug("GTiff", "Reading %d bytes at offset " CPL_FRMT_GUIB,
     160             :              static_cast<int>(size), VSIFTellL(psGTH->psShared->fpL));
     161             : #endif
     162     2511600 :     return VSIFReadL(buf, 1, size, psGTH->psShared->fpL);
     163             : }
     164             : 
     165     2568000 : static bool GTHFlushBuffer(thandle_t th)
     166             : {
     167     2568000 :     GDALTiffHandle *psGTH = static_cast<GDALTiffHandle *>(th);
     168     2568000 :     bool bRet = true;
     169     2568000 :     if (psGTH->abyWriteBuffer && psGTH->nWriteBufferSize)
     170             :     {
     171             :         const tsize_t nRet =
     172       22048 :             VSIFWriteL(psGTH->abyWriteBuffer, 1, psGTH->nWriteBufferSize,
     173       11024 :                        psGTH->psShared->fpL);
     174       11024 :         bRet = nRet == psGTH->nWriteBufferSize;
     175       11024 :         if (!bRet)
     176             :         {
     177           0 :             TIFFErrorExt(th, "_tiffWriteProc", "%s", VSIStrerror(errno));
     178             :         }
     179       11024 :         psGTH->nWriteBufferSize = 0;
     180             :     }
     181     2568000 :     return bRet;
     182             : }
     183             : 
     184      401280 : static tsize_t _tiffWriteProc(thandle_t th, tdata_t buf, tsize_t size)
     185             : {
     186      401280 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     187      401280 :     SetActiveGTH(psGTH);
     188             : 
     189             :     // If we have a write buffer and are at end of file, then accumulate
     190             :     // the bytes until the buffer is full.
     191      401017 :     if (psGTH->psShared->bAtEndOfFile && psGTH->abyWriteBuffer)
     192             :     {
     193       91637 :         const GByte *pabyData = reinterpret_cast<GByte *>(buf);
     194       91637 :         tsize_t nRemainingBytes = size;
     195             :         while (true)
     196             :         {
     197       96936 :             if (psGTH->nWriteBufferSize + nRemainingBytes <= BUFFER_SIZE)
     198             :             {
     199       91637 :                 memcpy(psGTH->abyWriteBuffer + psGTH->nWriteBufferSize,
     200             :                        pabyData, nRemainingBytes);
     201       91637 :                 psGTH->nWriteBufferSize += static_cast<int>(nRemainingBytes);
     202       91637 :                 if (psGTH->psShared->bAtEndOfFile)
     203             :                 {
     204       91637 :                     psGTH->psShared->nFileLength += size;
     205             :                 }
     206       91637 :                 return size;
     207             :             }
     208             : 
     209        5299 :             int nAppendable = BUFFER_SIZE - psGTH->nWriteBufferSize;
     210        5299 :             memcpy(psGTH->abyWriteBuffer + psGTH->nWriteBufferSize, pabyData,
     211             :                    nAppendable);
     212       10598 :             const tsize_t nRet = VSIFWriteL(psGTH->abyWriteBuffer, 1,
     213        5299 :                                             BUFFER_SIZE, psGTH->psShared->fpL);
     214        5299 :             psGTH->nWriteBufferSize = 0;
     215        5299 :             if (nRet != BUFFER_SIZE)
     216             :             {
     217           0 :                 TIFFErrorExt(th, "_tiffWriteProc", "%s", VSIStrerror(errno));
     218           0 :                 return 0;
     219             :             }
     220             : 
     221        5299 :             pabyData += nAppendable;
     222        5299 :             nRemainingBytes -= nAppendable;
     223        5299 :         }
     224             :     }
     225             : 
     226      309380 :     const tsize_t nRet = VSIFWriteL(buf, 1, size, psGTH->psShared->fpL);
     227      309882 :     if (nRet < size)
     228             :     {
     229          73 :         TIFFErrorExt(th, "_tiffWriteProc", "%s", VSIStrerror(errno));
     230             :     }
     231             : 
     232      309798 :     if (psGTH->psShared->bAtEndOfFile)
     233             :     {
     234      114979 :         psGTH->psShared->nFileLength += nRet;
     235             :     }
     236      309798 :     return nRet;
     237             : }
     238             : 
     239     2721450 : static toff_t _tiffSeekProc(thandle_t th, toff_t off, int whence)
     240             : {
     241     2721450 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     242     2721450 :     SetActiveGTH(psGTH);
     243             : 
     244             :     // Optimization: if we are already at end, then no need to
     245             :     // issue a VSIFSeekL().
     246     2721000 :     if (whence == SEEK_END)
     247             :     {
     248      229869 :         if (psGTH->psShared->bAtEndOfFile)
     249             :         {
     250      179561 :             return static_cast<toff_t>(psGTH->psShared->nFileLength);
     251             :         }
     252             : 
     253       50308 :         if (VSIFSeekL(psGTH->psShared->fpL, off, whence) != 0)
     254             :         {
     255           0 :             TIFFErrorExt(th, "_tiffSeekProc", "%s", VSIStrerror(errno));
     256           0 :             return static_cast<toff_t>(-1);
     257             :         }
     258       50309 :         psGTH->psShared->bAtEndOfFile = true;
     259       50309 :         psGTH->psShared->nFileLength = VSIFTellL(psGTH->psShared->fpL);
     260       50308 :         return static_cast<toff_t>(psGTH->psShared->nFileLength);
     261             :     }
     262             : 
     263     2491130 :     GTHFlushBuffer(th);
     264     2491380 :     psGTH->psShared->bAtEndOfFile = false;
     265     2491380 :     psGTH->psShared->nFileLength = 0;
     266             : 
     267     2491380 :     if (VSIFSeekL(psGTH->psShared->fpL, off, whence) == 0)
     268             :     {
     269     2491080 :         return static_cast<toff_t>(VSIFTellL(psGTH->psShared->fpL));
     270             :     }
     271             :     else
     272             :     {
     273           0 :         TIFFErrorExt(th, "_tiffSeekProc", "%s", VSIStrerror(errno));
     274           0 :         return static_cast<toff_t>(-1);
     275             :     }
     276             : }
     277             : 
     278       56523 : static void FreeGTH(GDALTiffHandle *psGTH)
     279             : {
     280       56523 :     psGTH->psShared->nUserCounter--;
     281       56523 :     if (psGTH->psParent == nullptr)
     282             :     {
     283       55039 :         assert(psGTH->psShared->nUserCounter == 0);
     284       55039 :         CPLFree(psGTH->psShared->pszName);
     285       55038 :         CPLFree(psGTH->psShared);
     286             :     }
     287             :     else
     288             :     {
     289        1484 :         if (psGTH->psShared->psActiveHandle == psGTH)
     290        1487 :             psGTH->psShared->psActiveHandle = nullptr;
     291             :     }
     292       56522 :     CPLFree(psGTH->abyWriteBuffer);
     293       56523 :     CPLFree(psGTH->ppCachedData);
     294       56524 :     CPLFree(psGTH->panCachedOffsets);
     295       56513 :     CPLFree(psGTH->panCachedSizes);
     296       56522 :     CPLFree(psGTH);
     297       56525 : }
     298             : 
     299       56521 : static int _tiffCloseProc(thandle_t th)
     300             : {
     301       56521 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     302       56521 :     SetActiveGTH(psGTH);
     303       56520 :     GTHFlushBuffer(th);
     304       56518 :     if (psGTH->bFree)
     305       56509 :         FreeGTH(psGTH);
     306       56519 :     return 0;
     307             : }
     308             : 
     309       26013 : static toff_t _tiffSizeProc(thandle_t th)
     310             : {
     311       26013 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     312       26013 :     SetActiveGTH(psGTH);
     313             : 
     314       26001 :     if (psGTH->psShared->bAtEndOfFile)
     315             :     {
     316        6823 :         return static_cast<toff_t>(psGTH->psShared->nFileLength);
     317             :     }
     318             : 
     319       19178 :     const vsi_l_offset old_off = VSIFTellL(psGTH->psShared->fpL);
     320       19177 :     CPL_IGNORE_RET_VAL(VSIFSeekL(psGTH->psShared->fpL, 0, SEEK_END));
     321             : 
     322             :     const toff_t file_size =
     323       19177 :         static_cast<toff_t>(VSIFTellL(psGTH->psShared->fpL));
     324       19181 :     CPL_IGNORE_RET_VAL(VSIFSeekL(psGTH->psShared->fpL, old_off, SEEK_SET));
     325             : 
     326       19178 :     return file_size;
     327             : }
     328             : 
     329       19002 : static int _tiffMapProc(thandle_t th, tdata_t *pbase, toff_t *psize)
     330             : {
     331       19002 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     332             :     // SetActiveGTH(psGTH);
     333             : 
     334       19002 :     if (psGTH->pBase)
     335             :     {
     336           8 :         *pbase = psGTH->pBase;
     337           8 :         *psize = static_cast<toff_t>(psGTH->nDataLength);
     338           8 :         return 1;
     339             :     }
     340       18994 :     return 0;
     341             : }
     342             : 
     343           8 : static void _tiffUnmapProc(thandle_t /* th */, tdata_t /* base */,
     344             :                            toff_t /* size */)
     345             : {
     346           8 : }
     347             : 
     348        5399 : VSILFILE *VSI_TIFFGetVSILFile(thandle_t th)
     349             : {
     350        5399 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     351        5399 :     SetActiveGTH(psGTH);
     352        5399 :     VSI_TIFFFlushBufferedWrite(th);
     353        5399 :     return psGTH->psShared->fpL;
     354             : }
     355             : 
     356        5624 : int VSI_TIFFFlushBufferedWrite(thandle_t th)
     357             : {
     358        5624 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     359        5624 :     SetActiveGTH(psGTH);
     360        5624 :     psGTH->psShared->bAtEndOfFile = false;
     361        5624 :     return GTHFlushBuffer(th);
     362             : }
     363             : 
     364         242 : int VSI_TIFFHasCachedRanges(thandle_t th)
     365             : {
     366         242 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     367         242 :     return psGTH->nCachedRanges != 0;
     368             : }
     369             : 
     370       24675 : toff_t VSI_TIFFSeek(TIFF *tif, toff_t off, int whence)
     371             : {
     372       24675 :     thandle_t th = TIFFClientdata(tif);
     373       24675 :     return _tiffSeekProc(th, off, whence);
     374             : }
     375             : 
     376       48999 : int VSI_TIFFWrite(TIFF *tif, const void *buffer, size_t buffersize)
     377             : {
     378       48999 :     thandle_t th = TIFFClientdata(tif);
     379       48999 :     return static_cast<size_t>(_tiffWriteProc(th, const_cast<tdata_t>(buffer),
     380       48999 :                                               buffersize)) == buffersize;
     381             : }
     382             : 
     383          80 : void VSI_TIFFSetCachedRanges(thandle_t th, int nRanges, void **ppData,
     384             :                              const vsi_l_offset *panOffsets,
     385             :                              const size_t *panSizes)
     386             : {
     387          80 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     388          80 :     psGTH->nCachedRanges = nRanges;
     389          80 :     if (nRanges)
     390             :     {
     391          40 :         psGTH->ppCachedData = static_cast<void **>(
     392          40 :             CPLRealloc(psGTH->ppCachedData, nRanges * sizeof(void *)));
     393          40 :         memcpy(psGTH->ppCachedData, ppData, nRanges * sizeof(void *));
     394             : 
     395          80 :         psGTH->panCachedOffsets = static_cast<vsi_l_offset *>(CPLRealloc(
     396          40 :             psGTH->panCachedOffsets, nRanges * sizeof(vsi_l_offset)));
     397          40 :         memcpy(psGTH->panCachedOffsets, panOffsets,
     398          40 :                nRanges * sizeof(vsi_l_offset));
     399             : 
     400          40 :         psGTH->panCachedSizes = static_cast<size_t *>(
     401          40 :             CPLRealloc(psGTH->panCachedSizes, nRanges * sizeof(size_t)));
     402          40 :         memcpy(psGTH->panCachedSizes, panSizes, nRanges * sizeof(size_t));
     403             :     }
     404          80 : }
     405             : 
     406       56530 : static bool IsReadOnly(const char *mode)
     407             : {
     408       56530 :     bool bReadOnly = true;
     409      228337 :     for (int i = 0; mode[i] != '\0'; i++)
     410             :     {
     411      171807 :         if (mode[i] == 'w' || mode[i] == '+' || mode[i] == 'a')
     412             :         {
     413       72265 :             bReadOnly = false;
     414             :         }
     415             :     }
     416       56530 :     return bReadOnly;
     417             : }
     418             : 
     419       56528 : static void InitializeWriteBuffer(GDALTiffHandle *psGTH, const char *pszMode)
     420             : {
     421             :     // No need to buffer on /vsimem/
     422       56528 :     const bool bReadOnly = IsReadOnly(pszMode);
     423       56524 :     bool bAllocBuffer = !bReadOnly;
     424       56524 :     if (STARTS_WITH(psGTH->psShared->pszName, "/vsimem/"))
     425             :     {
     426       47141 :         if (bReadOnly &&
     427        6545 :             CPLTestBool(CPLGetConfigOption("GTIFF_USE_MMAP", "NO")))
     428             :         {
     429           8 :             psGTH->nDataLength = 0;
     430           8 :             psGTH->pBase = VSIGetMemFileBuffer(psGTH->psShared->pszName,
     431             :                                                &psGTH->nDataLength, FALSE);
     432             :         }
     433       40596 :         bAllocBuffer = false;
     434             :     }
     435             : 
     436       56521 :     psGTH->abyWriteBuffer =
     437       56521 :         bAllocBuffer ? static_cast<GByte *>(VSIMalloc(BUFFER_SIZE)) : nullptr;
     438       56521 :     psGTH->nWriteBufferSize = 0;
     439       56521 : }
     440             : 
     441             : #ifdef SUPPORTS_LIBTIFF_OPEN_OPTIONS
     442       56532 : static void VSI_TIFFSetOpenOptions(TIFFOpenOptions *opts)
     443             : {
     444       56532 :     TIFFOpenOptionsSetErrorHandlerExtR(opts, GTiffErrorHandlerExt, nullptr);
     445       56524 :     TIFFOpenOptionsSetWarningHandlerExtR(opts, GTiffWarningHandlerExt, nullptr);
     446             : #if defined(INTERNAL_LIBTIFF) || TIFFLIB_VERSION > 20230908
     447             :     // Read-once and stored in static storage otherwise affects
     448             :     // autotest/benchmark/test_gtiff.py::test_gtiff_byte
     449         555 :     static const GIntBig nMemLimit = []()
     450             :     {
     451         555 :         if (const char *pszLimit =
     452         555 :                 CPLGetConfigOption("GTIFF_MAX_CUMULATED_MEM_USAGE", nullptr))
     453           0 :             return CPLAtoGIntBig(pszLimit);
     454             :         else
     455         555 :             return CPLGetUsablePhysicalRAM() * 9 / 10;
     456       56522 :     }();
     457       56525 :     if (nMemLimit > 0 && nMemLimit < std::numeric_limits<tmsize_t>::max())
     458             :     {
     459             :         //CPLDebug("GTiff", "TIFFOpenOptionsSetMaxCumulatedMemAlloc(%" PRIu64 ")",
     460             :         //         static_cast<uint64_t>(nMemLimit));
     461       56520 :         TIFFOpenOptionsSetMaxCumulatedMemAlloc(
     462             :             opts, static_cast<tmsize_t>(nMemLimit));
     463             :     }
     464             : #endif
     465       56521 : }
     466             : #endif
     467             : 
     468       56525 : static TIFF *VSI_TIFFOpen_common(GDALTiffHandle *psGTH, const char *pszMode)
     469             : {
     470       56525 :     InitializeWriteBuffer(psGTH, pszMode);
     471             : 
     472             : #ifdef SUPPORTS_LIBTIFF_OPEN_OPTIONS
     473       56520 :     XTIFFInitialize();
     474       56523 :     TIFFOpenOptions *opts = TIFFOpenOptionsAlloc();
     475       56524 :     if (opts == nullptr)
     476             :     {
     477           0 :         FreeGTH(psGTH);
     478           0 :         return nullptr;
     479             :     }
     480       56524 :     VSI_TIFFSetOpenOptions(opts);
     481      113029 :     TIFF *tif = TIFFClientOpenExt(
     482       56513 :         psGTH->psShared->pszName, pszMode, reinterpret_cast<thandle_t>(psGTH),
     483             :         _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
     484             :         _tiffSizeProc, _tiffMapProc, _tiffUnmapProc, opts);
     485       56516 :     TIFFOpenOptionsFree(opts);
     486             : #else
     487             :     TIFF *tif = XTIFFClientOpen(
     488             :         psGTH->psShared->pszName, pszMode, reinterpret_cast<thandle_t>(psGTH),
     489             :         _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
     490             :         _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
     491             : #endif
     492       56500 :     if (tif == nullptr)
     493          14 :         FreeGTH(psGTH);
     494             : 
     495       56495 :     return tif;
     496             : }
     497             : 
     498             : // Open a TIFF file for read/writing.
     499       55043 : TIFF *VSI_TIFFOpen(const char *name, const char *mode, VSILFILE *fpL)
     500             : {
     501             : 
     502       55043 :     if (VSIFSeekL(fpL, 0, SEEK_SET) < 0)
     503           0 :         return nullptr;
     504             : 
     505             :     GDALTiffHandle *psGTH =
     506       55041 :         static_cast<GDALTiffHandle *>(CPLCalloc(1, sizeof(GDALTiffHandle)));
     507       55042 :     psGTH->bFree = true;
     508       55042 :     psGTH->psParent = nullptr;
     509       55041 :     psGTH->psShared = static_cast<GDALTiffHandleShared *>(
     510       55042 :         CPLCalloc(1, sizeof(GDALTiffHandleShared)));
     511       55041 :     psGTH->psShared->bReadOnly = (strchr(mode, '+') == nullptr);
     512       55041 :     psGTH->psShared->bLazyStrileLoading = (strchr(mode, 'D') != nullptr);
     513       55041 :     psGTH->psShared->pszName = CPLStrdup(name);
     514       55040 :     psGTH->psShared->fpL = fpL;
     515       55040 :     psGTH->psShared->psActiveHandle = psGTH;
     516       55040 :     psGTH->psShared->nFileLength = 0;
     517       55040 :     psGTH->psShared->bAtEndOfFile = false;
     518       55040 :     psGTH->psShared->nUserCounter = 1;
     519             : 
     520       55040 :     return VSI_TIFFOpen_common(psGTH, mode);
     521             : }
     522             : 
     523        1487 : TIFF *VSI_TIFFOpenChild(TIFF *parent)
     524             : {
     525             :     GDALTiffHandle *psGTHParent =
     526        1487 :         reinterpret_cast<GDALTiffHandle *>(TIFFClientdata(parent));
     527             : 
     528             :     GDALTiffHandle *psGTH =
     529        1487 :         static_cast<GDALTiffHandle *>(CPLCalloc(1, sizeof(GDALTiffHandle)));
     530        1487 :     psGTH->bFree = true;
     531        1487 :     psGTH->psParent = psGTHParent;
     532        1487 :     psGTH->psShared = psGTHParent->psShared;
     533        1487 :     psGTH->psShared->nUserCounter++;
     534             : 
     535        1487 :     SetActiveGTH(psGTH);
     536        1487 :     VSIFSeekL(psGTH->psShared->fpL, 0, SEEK_SET);
     537        1487 :     psGTH->psShared->bAtEndOfFile = false;
     538             : 
     539        1487 :     const char *mode =
     540         691 :         psGTH->psShared->bReadOnly && psGTH->psShared->bLazyStrileLoading
     541        2974 :             ? "rDO"
     542        1592 :         : psGTH->psShared->bReadOnly          ? "r"
     543         796 :         : psGTH->psShared->bLazyStrileLoading ? "r+D"
     544             :                                               : "r+";
     545        1487 :     return VSI_TIFFOpen_common(psGTH, mode);
     546             : }
     547             : 
     548             : // Re-open a TIFF handle (seeking to the appropriate directory is then needed)
     549           9 : TIFF *VSI_TIFFReOpen(TIFF *tif)
     550             : {
     551           9 :     thandle_t th = TIFFClientdata(tif);
     552           9 :     GDALTiffHandle *psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     553             : 
     554             :     // Disable freeing of psGTH in _tiffCloseProc(), which could be called
     555             :     // if XTIFFClientOpen() fails, or obviously by XTIFFClose()
     556           9 :     psGTH->bFree = false;
     557             : 
     558           9 :     const char *mode =
     559           0 :         psGTH->psShared->bReadOnly && psGTH->psShared->bLazyStrileLoading
     560          18 :             ? "rDO"
     561          18 :         : psGTH->psShared->bReadOnly          ? "r"
     562           9 :         : psGTH->psShared->bLazyStrileLoading ? "r+D"
     563             :                                               : "r+";
     564             : 
     565           9 :     SetActiveGTH(psGTH);
     566           9 :     VSIFSeekL(psGTH->psShared->fpL, 0, SEEK_SET);
     567           9 :     psGTH->psShared->bAtEndOfFile = false;
     568             : 
     569             : #ifdef SUPPORTS_LIBTIFF_OPEN_OPTIONS
     570           9 :     TIFF *newHandle = nullptr;
     571           9 :     TIFFOpenOptions *opts = TIFFOpenOptionsAlloc();
     572           9 :     if (opts != nullptr)
     573             :     {
     574           9 :         VSI_TIFFSetOpenOptions(opts);
     575          18 :         newHandle = TIFFClientOpenExt(
     576           9 :             psGTH->psShared->pszName, mode, reinterpret_cast<thandle_t>(psGTH),
     577             :             _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
     578             :             _tiffSizeProc, _tiffMapProc, _tiffUnmapProc, opts);
     579           9 :         TIFFOpenOptionsFree(opts);
     580             :     }
     581             : #else
     582             :     TIFF *newHandle = XTIFFClientOpen(
     583             :         psGTH->psShared->pszName, mode, reinterpret_cast<thandle_t>(psGTH),
     584             :         _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
     585             :         _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
     586             : #endif
     587           9 :     if (newHandle != nullptr)
     588           9 :         XTIFFClose(tif);
     589             : 
     590           9 :     psGTH->bFree = true;
     591             : 
     592           9 :     return newHandle;
     593             : }

Generated by: LCOV version 1.14