LCOV - code coverage report
Current view: top level - port - cpl_vsi_virtual.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 57 81 70.4 %
Date: 2024-11-21 22:18:42 Functions: 26 38 68.4 %

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