LCOV - code coverage report
Current view: top level - port - cpl_vsi_virtual.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 62 81 76.5 %
Date: 2025-07-09 17:50:03 Functions: 28 38 73.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  VSI Virtual File System
       4             :  * Purpose:  Declarations for classes related to the virtual filesystem.
       5             :  *           These would only be normally required by applications implementing
       6             :  *           their own virtual file system classes which should be rare.
       7             :  *           The class interface may be fragile through versions.
       8             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       9             :  *
      10             :  ******************************************************************************
      11             :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      12             :  * Copyright (c) 2010-2014, Even Rouault <even dot rouault at spatialys.com>
      13             :  *
      14             :  * SPDX-License-Identifier: MIT
      15             :  ****************************************************************************/
      16             : 
      17             : #ifndef CPL_VSI_VIRTUAL_H_INCLUDED
      18             : #define CPL_VSI_VIRTUAL_H_INCLUDED
      19             : 
      20             : #include "cpl_progress.h"
      21             : #include "cpl_vsi.h"
      22             : #include "cpl_vsi_error.h"
      23             : #include "cpl_string.h"
      24             : #include "cpl_multiproc.h"
      25             : 
      26             : #include <cstdint>
      27             : #include <map>
      28             : #include <memory>
      29             : #include <vector>
      30             : #include <string>
      31             : 
      32             : // To avoid aliasing to GetDiskFreeSpace to GetDiskFreeSpaceA on Windows
      33             : #ifdef GetDiskFreeSpace
      34             : #undef GetDiskFreeSpace
      35             : #endif
      36             : 
      37             : // To avoid aliasing to CopyFile to CopyFileA on Windows
      38             : #ifdef CopyFile
      39             : #undef CopyFile
      40             : #endif
      41             : 
      42             : /************************************************************************/
      43             : /*                           VSIVirtualHandle                           */
      44             : /************************************************************************/
      45             : 
      46             : /** Virtual file handle */
      47             : struct CPL_DLL VSIVirtualHandle
      48             : {
      49             :   public:
      50             :     virtual int Seek(vsi_l_offset nOffset, int nWhence) = 0;
      51             :     virtual vsi_l_offset Tell() = 0;
      52             :     virtual size_t Read(void *pBuffer, size_t nSize, size_t nCount) = 0;
      53             :     virtual int ReadMultiRange(int nRanges, void **ppData,
      54             :                                const vsi_l_offset *panOffsets,
      55             :                                const size_t *panSizes);
      56             : 
      57             :     /** This method is called when code plans to access soon one or several
      58             :      * ranges in a file. Some file systems may be able to use this hint to
      59             :      * for example asynchronously start such requests.
      60             :      *
      61             :      * Offsets may be given in a non-increasing order, and may potentially
      62             :      * overlap.
      63             :      *
      64             :      * @param nRanges Size of the panOffsets and panSizes arrays.
      65             :      * @param panOffsets Array containing the start offset of each range.
      66             :      * @param panSizes Array containing the size (in bytes) of each range.
      67             :      * @since GDAL 3.7
      68             :      */
      69          91 :     virtual void AdviseRead(CPL_UNUSED int nRanges,
      70             :                             CPL_UNUSED const vsi_l_offset *panOffsets,
      71             :                             CPL_UNUSED const size_t *panSizes)
      72             :     {
      73          91 :     }
      74             : 
      75             :     /** Return the total maximum number of bytes that AdviseRead() can handle
      76             :      * at once.
      77             :      *
      78             :      * Some AdviseRead() implementations may give up if the sum of the values
      79             :      * in the panSizes[] array provided to AdviseRead() exceeds a limit.
      80             :      *
      81             :      * Callers might use that threshold to optimize the efficiency of
      82             :      * AdviseRead().
      83             :      *
      84             :      * A returned value of 0 indicates a unknown limit.
      85             :      * @since GDAL 3.9
      86             :      */
      87         219 :     virtual size_t GetAdviseReadTotalBytesLimit() const
      88             :     {
      89         219 :         return 0;
      90             :     }
      91             : 
      92             :     virtual size_t Write(const void *pBuffer, size_t nSize, size_t nCount) = 0;
      93             : 
      94             :     int Printf(CPL_FORMAT_STRING(const char *pszFormat), ...)
      95             :         CPL_PRINT_FUNC_FORMAT(2, 3);
      96             : 
      97             :     virtual void ClearErr() = 0;
      98             : 
      99             :     virtual int Eof() = 0;
     100             : 
     101             :     virtual int Error() = 0;
     102             : 
     103       35377 :     virtual int Flush()
     104             :     {
     105       35377 :         return 0;
     106             :     }
     107             : 
     108             :     virtual int Close() = 0;
     109             :     // Base implementation that only supports file extension.
     110             :     virtual int Truncate(vsi_l_offset nNewSize);
     111             : 
     112           9 :     virtual void *GetNativeFileDescriptor()
     113             :     {
     114           9 :         return nullptr;
     115             :     }
     116             : 
     117         151 :     virtual VSIRangeStatus GetRangeStatus(CPL_UNUSED vsi_l_offset nOffset,
     118             :                                           CPL_UNUSED vsi_l_offset nLength)
     119             :     {
     120         151 :         return VSI_RANGE_STATUS_UNKNOWN;
     121             :     }
     122             : 
     123             :     virtual bool HasPRead() const;
     124             :     virtual size_t PRead(void *pBuffer, size_t nSize,
     125             :                          vsi_l_offset nOffset) const;
     126             : 
     127             :     /** Ask current operations to be interrupted.
     128             :      * Implementations must be thread-safe, as this will typically be called
     129             :      * from another thread than the active one for this file.
     130             :      */
     131          34 :     virtual void Interrupt()
     132             :     {
     133          34 :     }
     134             : 
     135             :     // NOTE: when adding new methods, besides the "actual" implementations,
     136             :     // also consider the VSICachedFile one.
     137             : 
     138      316605 :     virtual ~VSIVirtualHandle()
     139      316605 :     {
     140      316605 :     }
     141             : };
     142             : 
     143             : /************************************************************************/
     144             : /*                        VSIVirtualHandleCloser                        */
     145             : /************************************************************************/
     146             : 
     147             : /** Helper close to use with a std:unique_ptr<VSIVirtualHandle>,
     148             :  *  such as VSIVirtualHandleUniquePtr. */
     149             : struct VSIVirtualHandleCloser
     150             : {
     151             :     /** Operator () that closes and deletes the file handle. */
     152       10586 :     void operator()(VSIVirtualHandle *poHandle)
     153             :     {
     154       10586 :         if (poHandle)
     155             :         {
     156       10568 :             poHandle->Close();
     157       10568 :             delete poHandle;
     158             :         }
     159       10586 :     }
     160             : };
     161             : 
     162             : /** Unique pointer of VSIVirtualHandle that calls the Close() method */
     163             : typedef std::unique_ptr<VSIVirtualHandle, VSIVirtualHandleCloser>
     164             :     VSIVirtualHandleUniquePtr;
     165             : 
     166             : /************************************************************************/
     167             : /*                         VSIFilesystemHandler                         */
     168             : /************************************************************************/
     169             : 
     170             : #ifndef DOXYGEN_SKIP
     171             : class CPL_DLL VSIFilesystemHandler
     172             : {
     173             : 
     174             :   public:
     175       32511 :     virtual ~VSIFilesystemHandler()
     176       32511 :     {
     177       32511 :     }
     178             : 
     179             :     VSIVirtualHandle *Open(const char *pszFilename, const char *pszAccess);
     180             : 
     181             :     virtual VSIVirtualHandle *Open(const char *pszFilename,
     182             :                                    const char *pszAccess, bool bSetError,
     183             :                                    CSLConstList papszOptions) = 0;
     184             :     virtual int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
     185             :                      int nFlags) = 0;
     186             : 
     187           2 :     virtual int Unlink(const char *pszFilename)
     188             :     {
     189             :         (void)pszFilename;
     190           2 :         errno = ENOENT;
     191           2 :         return -1;
     192             :     }
     193             : 
     194             :     virtual int *UnlinkBatch(CSLConstList papszFiles);
     195             : 
     196           0 :     virtual int Mkdir(const char *pszDirname, long nMode)
     197             :     {
     198             :         (void)pszDirname;
     199             :         (void)nMode;
     200           0 :         errno = ENOENT;
     201           0 :         return -1;
     202             :     }
     203             : 
     204           0 :     virtual int Rmdir(const char *pszDirname)
     205             :     {
     206             :         (void)pszDirname;
     207           0 :         errno = ENOENT;
     208           0 :         return -1;
     209             :     }
     210             : 
     211             :     virtual int RmdirRecursive(const char *pszDirname);
     212             : 
     213           5 :     char **ReadDir(const char *pszDirname)
     214             :     {
     215           5 :         return ReadDirEx(pszDirname, 0);
     216             :     }
     217             : 
     218           3 :     virtual char **ReadDirEx(const char * /*pszDirname*/, int /* nMaxFiles */)
     219             :     {
     220           3 :         return nullptr;
     221             :     }
     222             : 
     223       76260 :     virtual char **SiblingFiles(const char * /*pszFilename*/)
     224             :     {
     225       76260 :         return nullptr;
     226             :     }
     227             : 
     228           0 :     virtual int Rename(const char *oldpath, const char *newpath,
     229             :                        GDALProgressFunc pProgressFunc, void *pProgressData)
     230             :     {
     231             :         (void)oldpath;
     232             :         (void)newpath;
     233             :         (void)pProgressFunc;
     234             :         (void)pProgressData;
     235           0 :         errno = ENOENT;
     236           0 :         return -1;
     237             :     }
     238             : 
     239       27826 :     virtual int IsCaseSensitive(const char *pszFilename)
     240             :     {
     241             :         (void)pszFilename;
     242       27826 :         return TRUE;
     243             :     }
     244             : 
     245           0 :     virtual GIntBig GetDiskFreeSpace(const char * /* pszDirname */)
     246             :     {
     247           0 :         return -1;
     248             :     }
     249             : 
     250           0 :     virtual int SupportsSparseFiles(const char * /* pszPath */)
     251             :     {
     252           0 :         return FALSE;
     253             :     }
     254             : 
     255       15264 :     virtual int HasOptimizedReadMultiRange(const char * /* pszPath */)
     256             :     {
     257       15264 :         return FALSE;
     258             :     }
     259             : 
     260           1 :     virtual const char *GetActualURL(const char * /*pszFilename*/)
     261             :     {
     262           1 :         return nullptr;
     263             :     }
     264             : 
     265          14 :     virtual const char *GetOptions()
     266             :     {
     267          14 :         return nullptr;
     268             :     }
     269             : 
     270           1 :     virtual char *GetSignedURL(const char * /*pszFilename*/,
     271             :                                CSLConstList /* papszOptions */)
     272             :     {
     273           1 :         return nullptr;
     274             :     }
     275             : 
     276             :     virtual bool Sync(const char *pszSource, const char *pszTarget,
     277             :                       const char *const *papszOptions,
     278             :                       GDALProgressFunc pProgressFunc, void *pProgressData,
     279             :                       char ***ppapszOutputs);
     280             : 
     281             :     virtual int CopyFile(const char *pszSource, const char *pszTarget,
     282             :                          VSILFILE *fpSource, vsi_l_offset nSourceSize,
     283             :                          const char *const *papszOptions,
     284             :                          GDALProgressFunc pProgressFunc, void *pProgressData);
     285             : 
     286             :     virtual int
     287             :     CopyFileRestartable(const char *pszSource, const char *pszTarget,
     288             :                         const char *pszInputPayload, char **ppszOutputPayload,
     289             :                         CSLConstList papszOptions,
     290             :                         GDALProgressFunc pProgressFunc, void *pProgressData);
     291             : 
     292             :     virtual VSIDIR *OpenDir(const char *pszPath, int nRecurseDepth,
     293             :                             const char *const *papszOptions);
     294             : 
     295             :     virtual char **GetFileMetadata(const char *pszFilename,
     296             :                                    const char *pszDomain,
     297             :                                    CSLConstList papszOptions);
     298             : 
     299             :     virtual bool SetFileMetadata(const char *pszFilename,
     300             :                                  CSLConstList papszMetadata,
     301             :                                  const char *pszDomain,
     302             :                                  CSLConstList papszOptions);
     303             : 
     304             :     virtual bool
     305             :     MultipartUploadGetCapabilities(int *pbNonSequentialUploadSupported,
     306             :                                    int *pbParallelUploadSupported,
     307             :                                    int *pbAbortSupported, size_t *pnMinPartSize,
     308             :                                    size_t *pnMaxPartSize, int *pnMaxPartCount);
     309             : 
     310             :     virtual char *MultipartUploadStart(const char *pszFilename,
     311             :                                        CSLConstList papszOptions);
     312             : 
     313             :     virtual char *MultipartUploadAddPart(const char *pszFilename,
     314             :                                          const char *pszUploadId,
     315             :                                          int nPartNumber,
     316             :                                          vsi_l_offset nFileOffset,
     317             :                                          const void *pData, size_t nDataLength,
     318             :                                          CSLConstList papszOptions);
     319             : 
     320             :     virtual bool
     321             :     MultipartUploadEnd(const char *pszFilename, const char *pszUploadId,
     322             :                        size_t nPartIdsCount, const char *const *apszPartIds,
     323             :                        vsi_l_offset nTotalSize, CSLConstList papszOptions);
     324             : 
     325             :     virtual bool MultipartUploadAbort(const char *pszFilename,
     326             :                                       const char *pszUploadId,
     327             :                                       CSLConstList papszOptions);
     328             : 
     329           0 :     virtual bool AbortPendingUploads(const char * /*pszFilename*/)
     330             :     {
     331           0 :         return true;
     332             :     }
     333             : 
     334             :     virtual std::string
     335       26708 :     GetStreamingFilename(const std::string &osFilename) const
     336             :     {
     337       26708 :         return osFilename;
     338             :     }
     339             : 
     340             :     virtual std::string
     341        1421 :     GetNonStreamingFilename(const std::string &osFilename) const
     342             :     {
     343        1421 :         return osFilename;
     344             :     }
     345             : 
     346             :     /** Return the canonical filename.
     347             :      *
     348             :      * May be implemented by case-insensitive filesystems
     349             :      * (currently Win32 and MacOSX)
     350             :      * to return the filename with its actual case (i.e. the one that would
     351             :      * be used when listing the content of the directory).
     352             :      */
     353             :     virtual std::string
     354         248 :     GetCanonicalFilename(const std::string &osFilename) const
     355             :     {
     356         248 :         return osFilename;
     357             :     }
     358             : 
     359         104 :     virtual bool IsLocal(const char * /* pszPath */)
     360             :     {
     361         104 :         return true;
     362             :     }
     363             : 
     364          45 :     virtual bool SupportsSequentialWrite(const char * /* pszPath */,
     365             :                                          bool /* bAllowLocalTempFile */)
     366             :     {
     367          45 :         return true;
     368             :     }
     369             : 
     370         294 :     virtual bool SupportsRandomWrite(const char * /* pszPath */,
     371             :                                      bool /* bAllowLocalTempFile */)
     372             :     {
     373         294 :         return true;
     374             :     }
     375             : 
     376          43 :     virtual bool SupportsRead(const char * /* pszPath */)
     377             :     {
     378          43 :         return true;
     379             :     }
     380             : 
     381           2 :     virtual VSIFilesystemHandler *Duplicate(const char * /* pszPrefix */)
     382             :     {
     383           2 :         CPLError(CE_Failure, CPLE_NotSupported,
     384             :                  "Duplicate() not supported on this file system");
     385           2 :         return nullptr;
     386             :     }
     387             : 
     388             :     /** Return the directory separator.
     389             :      *
     390             :      * Default is forward slash. The only exception currently is the Windows
     391             :      * file system which returns anti-slash, unless the specified path is of the
     392             :      * form "{drive_letter}:/{rest_of_the_path}".
     393             :      */
     394      916497 :     virtual const char *GetDirectorySeparator(CPL_UNUSED const char *pszPath)
     395             :     {
     396      916497 :         return "/";
     397             :     }
     398             : };
     399             : #endif /* #ifndef DOXYGEN_SKIP */
     400             : 
     401             : /************************************************************************/
     402             : /*                            VSIFileManager                            */
     403             : /************************************************************************/
     404             : 
     405             : #ifndef DOXYGEN_SKIP
     406             : class CPL_DLL VSIFileManager
     407             : {
     408             :   private:
     409             :     VSIFilesystemHandler *poDefaultHandler = nullptr;
     410             :     std::map<std::string, VSIFilesystemHandler *> oHandlers{};
     411             : 
     412             :     VSIFileManager();
     413             : 
     414             :     static VSIFileManager *Get();
     415             : 
     416             :     CPL_DISALLOW_COPY_ASSIGN(VSIFileManager)
     417             : 
     418             :   public:
     419             :     ~VSIFileManager();
     420             : 
     421             :     static VSIFilesystemHandler *GetHandler(const char *);
     422             :     static void InstallHandler(const std::string &osPrefix,
     423             :                                VSIFilesystemHandler *);
     424             :     static void RemoveHandler(const std::string &osPrefix);
     425             : 
     426             :     static char **GetPrefixes();
     427             : };
     428             : #endif /* #ifndef DOXYGEN_SKIP */
     429             : 
     430             : /************************************************************************/
     431             : /* ==================================================================== */
     432             : /*                       VSIArchiveFilesystemHandler                   */
     433             : /* ==================================================================== */
     434             : /************************************************************************/
     435             : 
     436             : #ifndef DOXYGEN_SKIP
     437             : 
     438             : class VSIArchiveEntryFileOffset
     439             : {
     440             :   public:
     441             :     virtual ~VSIArchiveEntryFileOffset();
     442             : };
     443             : 
     444             : typedef struct
     445             : {
     446             :     char *fileName;
     447             :     vsi_l_offset uncompressed_size;
     448             :     VSIArchiveEntryFileOffset *file_pos;
     449             :     int bIsDir;
     450             :     GIntBig nModifiedTime;
     451             : } VSIArchiveEntry;
     452             : 
     453             : class VSIArchiveContent
     454             : {
     455             :   public:
     456             :     time_t mTime = 0;
     457             :     vsi_l_offset nFileSize = 0;
     458             :     int nEntries = 0;
     459             :     VSIArchiveEntry *entries = nullptr;
     460             : 
     461             :     ~VSIArchiveContent();
     462             : };
     463             : 
     464             : class VSIArchiveReader
     465             : {
     466             :   public:
     467             :     virtual ~VSIArchiveReader();
     468             : 
     469             :     virtual int GotoFirstFile() = 0;
     470             :     virtual int GotoNextFile() = 0;
     471             :     virtual VSIArchiveEntryFileOffset *GetFileOffset() = 0;
     472             :     virtual GUIntBig GetFileSize() = 0;
     473             :     virtual CPLString GetFileName() = 0;
     474             :     virtual GIntBig GetModifiedTime() = 0;
     475             :     virtual int GotoFileOffset(VSIArchiveEntryFileOffset *pOffset) = 0;
     476             : };
     477             : 
     478             : class VSIArchiveFilesystemHandler : public VSIFilesystemHandler
     479             : {
     480             :     CPL_DISALLOW_COPY_ASSIGN(VSIArchiveFilesystemHandler)
     481             : 
     482             :   protected:
     483             :     CPLMutex *hMutex = nullptr;
     484             :     /* We use a cache that contains the list of files contained in a VSIArchive
     485             :      * file as */
     486             :     /* unarchive.c is quite inefficient in listing them. This speeds up access
     487             :      * to VSIArchive files */
     488             :     /* containing ~1000 files like a CADRG product */
     489             :     std::map<CPLString, VSIArchiveContent *> oFileList{};
     490             : 
     491             :     virtual const char *GetPrefix() = 0;
     492             :     virtual std::vector<CPLString> GetExtensions() = 0;
     493             :     virtual VSIArchiveReader *CreateReader(const char *pszArchiveFileName) = 0;
     494             : 
     495             :   public:
     496             :     VSIArchiveFilesystemHandler();
     497             :     virtual ~VSIArchiveFilesystemHandler();
     498             : 
     499             :     int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
     500             :              int nFlags) override;
     501             :     char **ReadDirEx(const char *pszDirname, int nMaxFiles) override;
     502             : 
     503             :     virtual const VSIArchiveContent *
     504             :     GetContentOfArchive(const char *archiveFilename,
     505             :                         VSIArchiveReader *poReader = nullptr);
     506             :     virtual char *SplitFilename(const char *pszFilename,
     507             :                                 CPLString &osFileInArchive,
     508             :                                 bool bCheckMainFileExists, bool bSetError);
     509             :     virtual VSIArchiveReader *OpenArchiveFile(const char *archiveFilename,
     510             :                                               const char *fileInArchiveName);
     511             :     virtual int FindFileInArchive(const char *archiveFilename,
     512             :                                   const char *fileInArchiveName,
     513             :                                   const VSIArchiveEntry **archiveEntry);
     514             : 
     515             :     virtual bool IsLocal(const char *pszPath) override;
     516             : 
     517             :     virtual bool
     518           0 :     SupportsSequentialWrite(const char * /* pszPath */,
     519             :                             bool /* bAllowLocalTempFile */) override
     520             :     {
     521           0 :         return false;
     522             :     }
     523             : 
     524           0 :     virtual bool SupportsRandomWrite(const char * /* pszPath */,
     525             :                                      bool /* bAllowLocalTempFile */) override
     526             :     {
     527           0 :         return false;
     528             :     }
     529             : };
     530             : 
     531             : /************************************************************************/
     532             : /*                              VSIDIR                                  */
     533             : /************************************************************************/
     534             : 
     535             : struct CPL_DLL VSIDIR
     536             : {
     537        3310 :     VSIDIR() = default;
     538             :     virtual ~VSIDIR();
     539             : 
     540             :     virtual const VSIDIREntry *NextDirEntry() = 0;
     541             : 
     542             :   private:
     543             :     VSIDIR(const VSIDIR &) = delete;
     544             :     VSIDIR &operator=(const VSIDIR &) = delete;
     545             : };
     546             : 
     547             : #endif /* #ifndef DOXYGEN_SKIP */
     548             : 
     549             : VSIVirtualHandle CPL_DLL *
     550             : VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle);
     551             : VSIVirtualHandle *
     552             : VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle,
     553             :                               const GByte *pabyBeginningContent,
     554             :                               vsi_l_offset nCheatFileSize);
     555             : constexpr int VSI_CACHED_DEFAULT_CHUNK_SIZE = 32768;
     556             : VSIVirtualHandle CPL_DLL *
     557             : VSICreateCachedFile(VSIVirtualHandle *poBaseHandle,
     558             :                     size_t nChunkSize = VSI_CACHED_DEFAULT_CHUNK_SIZE,
     559             :                     size_t nCacheSize = 0);
     560             : 
     561             : const int CPL_DEFLATE_TYPE_GZIP = 0;
     562             : const int CPL_DEFLATE_TYPE_ZLIB = 1;
     563             : const int CPL_DEFLATE_TYPE_RAW_DEFLATE = 2;
     564             : VSIVirtualHandle CPL_DLL *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
     565             :                                                 int nDeflateType,
     566             :                                                 int bAutoCloseBaseHandle);
     567             : 
     568             : VSIVirtualHandle *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
     569             :                                         int nDeflateType,
     570             :                                         bool bAutoCloseBaseHandle, int nThreads,
     571             :                                         size_t nChunkSize,
     572             :                                         size_t nSOZIPIndexEltSize,
     573             :                                         std::vector<uint8_t> *panSOZIPIndex);
     574             : 
     575             : VSIVirtualHandle *
     576             : VSICreateUploadOnCloseFile(VSIVirtualHandleUniquePtr &&poWritableHandle,
     577             :                            VSIVirtualHandleUniquePtr &&poTmpFile,
     578             :                            const std::string &osTmpFilename);
     579             : 
     580             : #endif /* ndef CPL_VSI_VIRTUAL_H_INCLUDED */

Generated by: LCOV version 1.14