LCOV - code coverage report
Current view: top level - port - cpl_vsi_virtual.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 55 77 71.4 %
Date: 2024-04-29 01:40:10 Functions: 25 36 69.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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      16             :  * copy of this software and associated documentation files (the "Software"),
      17             :  * to deal in the Software without restriction, including without limitation
      18             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      19             :  * and/or sell copies of the Software, and to permit persons to whom the
      20             :  * Software is furnished to do so, subject to the following conditions:
      21             :  *
      22             :  * The above copyright notice and this permission notice shall be included
      23             :  * in all copies or substantial portions of the Software.
      24             :  *
      25             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      26             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      27             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      28             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      29             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      30             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      31             :  * DEALINGS IN THE SOFTWARE.
      32             :  ****************************************************************************/
      33             : 
      34             : #ifndef CPL_VSI_VIRTUAL_H_INCLUDED
      35             : #define CPL_VSI_VIRTUAL_H_INCLUDED
      36             : 
      37             : #include "cpl_vsi.h"
      38             : #include "cpl_vsi_error.h"
      39             : #include "cpl_string.h"
      40             : #include "cpl_multiproc.h"
      41             : 
      42             : #include <map>
      43             : #include <memory>
      44             : #include <vector>
      45             : #include <string>
      46             : 
      47             : // To avoid aliasing to GetDiskFreeSpace to GetDiskFreeSpaceA on Windows
      48             : #ifdef GetDiskFreeSpace
      49             : #undef GetDiskFreeSpace
      50             : #endif
      51             : 
      52             : // To avoid aliasing to CopyFile to CopyFileA on Windows
      53             : #ifdef CopyFile
      54             : #undef CopyFile
      55             : #endif
      56             : 
      57             : /************************************************************************/
      58             : /*                           VSIVirtualHandle                           */
      59             : /************************************************************************/
      60             : 
      61             : /** Virtual file handle */
      62             : struct CPL_DLL VSIVirtualHandle
      63             : {
      64             :   public:
      65             :     virtual int Seek(vsi_l_offset nOffset, int nWhence) = 0;
      66             :     virtual vsi_l_offset Tell() = 0;
      67             :     virtual size_t Read(void *pBuffer, size_t nSize, size_t nCount) = 0;
      68             :     virtual int ReadMultiRange(int nRanges, void **ppData,
      69             :                                const vsi_l_offset *panOffsets,
      70             :                                const size_t *panSizes);
      71             : 
      72             :     /** This method is called when code plans to access soon one or several
      73             :      * ranges in a file. Some file systems may be able to use this hint to
      74             :      * for example asynchronously start such requests.
      75             :      *
      76             :      * Offsets may be given in a non-increasing order, and may potentially
      77             :      * overlap.
      78             :      *
      79             :      * @param nRanges Size of the panOffsets and panSizes arrays.
      80             :      * @param panOffsets Array containing the start offset of each range.
      81             :      * @param panSizes Array containing the size (in bytes) of each range.
      82             :      * @since GDAL 3.7
      83             :      */
      84          90 :     virtual void AdviseRead(CPL_UNUSED int nRanges,
      85             :                             CPL_UNUSED const vsi_l_offset *panOffsets,
      86             :                             CPL_UNUSED const size_t *panSizes)
      87             :     {
      88          90 :     }
      89             : 
      90             :     /** Return the total maximum number of bytes that AdviseRead() can handle
      91             :      * at once.
      92             :      *
      93             :      * Some AdviseRead() implementations may give up if the sum of the values
      94             :      * in the panSizes[] array provided to AdviseRead() exceeds a limit.
      95             :      *
      96             :      * Callers might use that threshold to optimize the efficiency of
      97             :      * AdviseRead().
      98             :      *
      99             :      * A returned value of 0 indicates a unknown limit.
     100             :      * @since GDAL 3.9
     101             :      */
     102         217 :     virtual size_t GetAdviseReadTotalBytesLimit() const
     103             :     {
     104         217 :         return 0;
     105             :     }
     106             : 
     107             :     virtual size_t Write(const void *pBuffer, size_t nSize, size_t nCount) = 0;
     108             : 
     109             :     int Printf(CPL_FORMAT_STRING(const char *pszFormat), ...)
     110             :         CPL_PRINT_FUNC_FORMAT(2, 3);
     111             : 
     112             :     virtual int Eof() = 0;
     113             : 
     114       33692 :     virtual int Flush()
     115             :     {
     116       33692 :         return 0;
     117             :     }
     118             : 
     119             :     virtual int Close() = 0;
     120             :     // Base implementation that only supports file extension.
     121             :     virtual int Truncate(vsi_l_offset nNewSize);
     122             : 
     123           9 :     virtual void *GetNativeFileDescriptor()
     124             :     {
     125           9 :         return nullptr;
     126             :     }
     127             : 
     128         133 :     virtual VSIRangeStatus GetRangeStatus(CPL_UNUSED vsi_l_offset nOffset,
     129             :                                           CPL_UNUSED vsi_l_offset nLength)
     130             :     {
     131         133 :         return VSI_RANGE_STATUS_UNKNOWN;
     132             :     }
     133             : 
     134             :     virtual bool HasPRead() const;
     135             :     virtual size_t PRead(void *pBuffer, size_t nSize,
     136             :                          vsi_l_offset nOffset) const;
     137             : 
     138             :     // NOTE: when adding new methods, besides the "actual" implementations,
     139             :     // also consider the VSICachedFile one.
     140             : 
     141      283880 :     virtual ~VSIVirtualHandle()
     142      283880 :     {
     143      283880 :     }
     144             : };
     145             : 
     146             : /************************************************************************/
     147             : /*                        VSIVirtualHandleCloser                        */
     148             : /************************************************************************/
     149             : 
     150             : /** Helper close to use with a std:unique_ptr<VSIVirtualHandle>,
     151             :  *  such as VSIVirtualHandleUniquePtr. */
     152             : struct VSIVirtualHandleCloser
     153             : {
     154             :     /** Operator () that closes and deletes the file handle. */
     155        4198 :     void operator()(VSIVirtualHandle *poHandle)
     156             :     {
     157        4198 :         if (poHandle)
     158             :         {
     159        4182 :             poHandle->Close();
     160        4182 :             delete poHandle;
     161             :         }
     162        4198 :     }
     163             : };
     164             : 
     165             : /** Unique pointer of VSIVirtualHandle that calls the Close() method */
     166             : typedef std::unique_ptr<VSIVirtualHandle, VSIVirtualHandleCloser>
     167             :     VSIVirtualHandleUniquePtr;
     168             : 
     169             : /************************************************************************/
     170             : /*                         VSIFilesystemHandler                         */
     171             : /************************************************************************/
     172             : 
     173             : #ifndef DOXYGEN_SKIP
     174             : class CPL_DLL VSIFilesystemHandler
     175             : {
     176             : 
     177             :   public:
     178       23006 :     virtual ~VSIFilesystemHandler()
     179       23006 :     {
     180       23006 :     }
     181             : 
     182             :     VSIVirtualHandle *Open(const char *pszFilename, const char *pszAccess);
     183             : 
     184             :     virtual VSIVirtualHandle *Open(const char *pszFilename,
     185             :                                    const char *pszAccess, bool bSetError,
     186             :                                    CSLConstList papszOptions) = 0;
     187             :     virtual int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
     188             :                      int nFlags) = 0;
     189             : 
     190           0 :     virtual int Unlink(const char *pszFilename)
     191             :     {
     192             :         (void)pszFilename;
     193           0 :         errno = ENOENT;
     194           0 :         return -1;
     195             :     }
     196             : 
     197             :     virtual int *UnlinkBatch(CSLConstList papszFiles);
     198             : 
     199           0 :     virtual int Mkdir(const char *pszDirname, long nMode)
     200             :     {
     201             :         (void)pszDirname;
     202             :         (void)nMode;
     203           0 :         errno = ENOENT;
     204           0 :         return -1;
     205             :     }
     206             : 
     207           0 :     virtual int Rmdir(const char *pszDirname)
     208             :     {
     209             :         (void)pszDirname;
     210           0 :         errno = ENOENT;
     211           0 :         return -1;
     212             :     }
     213             : 
     214             :     virtual int RmdirRecursive(const char *pszDirname);
     215             : 
     216           4 :     char **ReadDir(const char *pszDirname)
     217             :     {
     218           4 :         return ReadDirEx(pszDirname, 0);
     219             :     }
     220             : 
     221           2 :     virtual char **ReadDirEx(const char * /*pszDirname*/, int /* nMaxFiles */)
     222             :     {
     223           2 :         return nullptr;
     224             :     }
     225             : 
     226       63345 :     virtual char **SiblingFiles(const char * /*pszFilename*/)
     227             :     {
     228       63345 :         return nullptr;
     229             :     }
     230             : 
     231           0 :     virtual int Rename(const char *oldpath, const char *newpath)
     232             :     {
     233             :         (void)oldpath;
     234             :         (void)newpath;
     235           0 :         errno = ENOENT;
     236           0 :         return -1;
     237             :     }
     238             : 
     239       26983 :     virtual int IsCaseSensitive(const char *pszFilename)
     240             :     {
     241             :         (void)pszFilename;
     242       26983 :         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        9784 :     virtual int HasOptimizedReadMultiRange(const char * /* pszPath */)
     256             :     {
     257        9784 :         return FALSE;
     258             :     }
     259             : 
     260           1 :     virtual const char *GetActualURL(const char * /*pszFilename*/)
     261             :     {
     262           1 :         return nullptr;
     263             :     }
     264             : 
     265          11 :     virtual const char *GetOptions()
     266             :     {
     267          11 :         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 VSIDIR *OpenDir(const char *pszPath, int nRecurseDepth,
     287             :                             const char *const *papszOptions);
     288             : 
     289             :     virtual char **GetFileMetadata(const char *pszFilename,
     290             :                                    const char *pszDomain,
     291             :                                    CSLConstList papszOptions);
     292             : 
     293             :     virtual bool SetFileMetadata(const char *pszFilename,
     294             :                                  CSLConstList papszMetadata,
     295             :                                  const char *pszDomain,
     296             :                                  CSLConstList papszOptions);
     297             : 
     298           0 :     virtual bool AbortPendingUploads(const char * /*pszFilename*/)
     299             :     {
     300           0 :         return true;
     301             :     }
     302             : 
     303             :     virtual std::string
     304       26367 :     GetStreamingFilename(const std::string &osFilename) const
     305             :     {
     306       26367 :         return osFilename;
     307             :     }
     308             : 
     309             :     /** Return the canonical filename.
     310             :      *
     311             :      * May be implemented by case-insensitive filesystems
     312             :      * (currently Win32 and MacOSX)
     313             :      * to return the filename with its actual case (i.e. the one that would
     314             :      * be used when listing the content of the directory).
     315             :      */
     316             :     virtual std::string
     317         248 :     GetCanonicalFilename(const std::string &osFilename) const
     318             :     {
     319         248 :         return osFilename;
     320             :     }
     321             : 
     322          97 :     virtual bool IsLocal(const char * /* pszPath */)
     323             :     {
     324          97 :         return true;
     325             :     }
     326             : 
     327          42 :     virtual bool SupportsSequentialWrite(const char * /* pszPath */,
     328             :                                          bool /* bAllowLocalTempFile */)
     329             :     {
     330          42 :         return true;
     331             :     }
     332             : 
     333         102 :     virtual bool SupportsRandomWrite(const char * /* pszPath */,
     334             :                                      bool /* bAllowLocalTempFile */)
     335             :     {
     336         102 :         return true;
     337             :     }
     338             : 
     339          42 :     virtual bool SupportsRead(const char * /* pszPath */)
     340             :     {
     341          42 :         return true;
     342             :     }
     343             : 
     344           2 :     virtual VSIFilesystemHandler *Duplicate(const char * /* pszPrefix */)
     345             :     {
     346           2 :         CPLError(CE_Failure, CPLE_NotSupported,
     347             :                  "Duplicate() not supported on this file system");
     348           2 :         return nullptr;
     349             :     }
     350             : 
     351             :     /** Return the directory separator.
     352             :      *
     353             :      * Default is forward slash. The only exception currently is the Windows
     354             :      * file system which returns anti-slash, unless the specified path is of the
     355             :      * form "{drive_letter}:/{rest_of_the_path}".
     356             :      */
     357      877658 :     virtual const char *GetDirectorySeparator(CPL_UNUSED const char *pszPath)
     358             :     {
     359      877658 :         return "/";
     360             :     }
     361             : };
     362             : #endif /* #ifndef DOXYGEN_SKIP */
     363             : 
     364             : /************************************************************************/
     365             : /*                            VSIFileManager                            */
     366             : /************************************************************************/
     367             : 
     368             : #ifndef DOXYGEN_SKIP
     369             : class CPL_DLL VSIFileManager
     370             : {
     371             :   private:
     372             :     VSIFilesystemHandler *poDefaultHandler = nullptr;
     373             :     std::map<std::string, VSIFilesystemHandler *> oHandlers{};
     374             : 
     375             :     VSIFileManager();
     376             : 
     377             :     static VSIFileManager *Get();
     378             : 
     379             :     CPL_DISALLOW_COPY_ASSIGN(VSIFileManager)
     380             : 
     381             :   public:
     382             :     ~VSIFileManager();
     383             : 
     384             :     static VSIFilesystemHandler *GetHandler(const char *);
     385             :     static void InstallHandler(const std::string &osPrefix,
     386             :                                VSIFilesystemHandler *);
     387             :     static void RemoveHandler(const std::string &osPrefix);
     388             : 
     389             :     static char **GetPrefixes();
     390             : };
     391             : #endif /* #ifndef DOXYGEN_SKIP */
     392             : 
     393             : /************************************************************************/
     394             : /* ==================================================================== */
     395             : /*                       VSIArchiveFilesystemHandler                   */
     396             : /* ==================================================================== */
     397             : /************************************************************************/
     398             : 
     399             : #ifndef DOXYGEN_SKIP
     400             : 
     401             : class VSIArchiveEntryFileOffset
     402             : {
     403             :   public:
     404             :     virtual ~VSIArchiveEntryFileOffset();
     405             : };
     406             : 
     407             : typedef struct
     408             : {
     409             :     char *fileName;
     410             :     vsi_l_offset uncompressed_size;
     411             :     VSIArchiveEntryFileOffset *file_pos;
     412             :     int bIsDir;
     413             :     GIntBig nModifiedTime;
     414             : } VSIArchiveEntry;
     415             : 
     416             : class VSIArchiveContent
     417             : {
     418             :   public:
     419             :     time_t mTime = 0;
     420             :     vsi_l_offset nFileSize = 0;
     421             :     int nEntries = 0;
     422             :     VSIArchiveEntry *entries = nullptr;
     423             : 
     424             :     ~VSIArchiveContent();
     425             : };
     426             : 
     427             : class VSIArchiveReader
     428             : {
     429             :   public:
     430             :     virtual ~VSIArchiveReader();
     431             : 
     432             :     virtual int GotoFirstFile() = 0;
     433             :     virtual int GotoNextFile() = 0;
     434             :     virtual VSIArchiveEntryFileOffset *GetFileOffset() = 0;
     435             :     virtual GUIntBig GetFileSize() = 0;
     436             :     virtual CPLString GetFileName() = 0;
     437             :     virtual GIntBig GetModifiedTime() = 0;
     438             :     virtual int GotoFileOffset(VSIArchiveEntryFileOffset *pOffset) = 0;
     439             : };
     440             : 
     441             : class VSIArchiveFilesystemHandler : public VSIFilesystemHandler
     442             : {
     443             :     CPL_DISALLOW_COPY_ASSIGN(VSIArchiveFilesystemHandler)
     444             : 
     445             :   protected:
     446             :     CPLMutex *hMutex = nullptr;
     447             :     /* We use a cache that contains the list of files contained in a VSIArchive
     448             :      * file as */
     449             :     /* unarchive.c is quite inefficient in listing them. This speeds up access
     450             :      * to VSIArchive files */
     451             :     /* containing ~1000 files like a CADRG product */
     452             :     std::map<CPLString, VSIArchiveContent *> oFileList{};
     453             : 
     454             :     virtual const char *GetPrefix() = 0;
     455             :     virtual std::vector<CPLString> GetExtensions() = 0;
     456             :     virtual VSIArchiveReader *CreateReader(const char *pszArchiveFileName) = 0;
     457             : 
     458             :   public:
     459             :     VSIArchiveFilesystemHandler();
     460             :     virtual ~VSIArchiveFilesystemHandler();
     461             : 
     462             :     int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
     463             :              int nFlags) override;
     464             :     int Unlink(const char *pszFilename) override;
     465             :     int Rename(const char *oldpath, const char *newpath) override;
     466             :     int Mkdir(const char *pszDirname, long nMode) override;
     467             :     int Rmdir(const char *pszDirname) override;
     468             :     char **ReadDirEx(const char *pszDirname, int nMaxFiles) override;
     469             : 
     470             :     virtual const VSIArchiveContent *
     471             :     GetContentOfArchive(const char *archiveFilename,
     472             :                         VSIArchiveReader *poReader = nullptr);
     473             :     virtual char *SplitFilename(const char *pszFilename,
     474             :                                 CPLString &osFileInArchive,
     475             :                                 int bCheckMainFileExists);
     476             :     virtual VSIArchiveReader *OpenArchiveFile(const char *archiveFilename,
     477             :                                               const char *fileInArchiveName);
     478             :     virtual int FindFileInArchive(const char *archiveFilename,
     479             :                                   const char *fileInArchiveName,
     480             :                                   const VSIArchiveEntry **archiveEntry);
     481             : 
     482             :     virtual bool IsLocal(const char *pszPath) override;
     483             : 
     484             :     virtual bool
     485           0 :     SupportsSequentialWrite(const char * /* pszPath */,
     486             :                             bool /* bAllowLocalTempFile */) override
     487             :     {
     488           0 :         return false;
     489             :     }
     490             : 
     491           0 :     virtual bool SupportsRandomWrite(const char * /* pszPath */,
     492             :                                      bool /* bAllowLocalTempFile */) override
     493             :     {
     494           0 :         return false;
     495             :     }
     496             : };
     497             : 
     498             : /************************************************************************/
     499             : /*                              VSIDIR                                  */
     500             : /************************************************************************/
     501             : 
     502             : struct CPL_DLL VSIDIR
     503             : {
     504        6187 :     VSIDIR() = default;
     505             :     virtual ~VSIDIR();
     506             : 
     507             :     virtual const VSIDIREntry *NextDirEntry() = 0;
     508             : 
     509             :   private:
     510             :     VSIDIR(const VSIDIR &) = delete;
     511             :     VSIDIR &operator=(const VSIDIR &) = delete;
     512             : };
     513             : 
     514             : #endif /* #ifndef DOXYGEN_SKIP */
     515             : 
     516             : VSIVirtualHandle CPL_DLL *
     517             : VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle);
     518             : VSIVirtualHandle *
     519             : VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle,
     520             :                               const GByte *pabyBeginningContent,
     521             :                               vsi_l_offset nCheatFileSize);
     522             : constexpr int VSI_CACHED_DEFAULT_CHUNK_SIZE = 32768;
     523             : VSIVirtualHandle CPL_DLL *
     524             : VSICreateCachedFile(VSIVirtualHandle *poBaseHandle,
     525             :                     size_t nChunkSize = VSI_CACHED_DEFAULT_CHUNK_SIZE,
     526             :                     size_t nCacheSize = 0);
     527             : 
     528             : const int CPL_DEFLATE_TYPE_GZIP = 0;
     529             : const int CPL_DEFLATE_TYPE_ZLIB = 1;
     530             : const int CPL_DEFLATE_TYPE_RAW_DEFLATE = 2;
     531             : VSIVirtualHandle CPL_DLL *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
     532             :                                                 int nDeflateType,
     533             :                                                 int bAutoCloseBaseHandle);
     534             : 
     535             : VSIVirtualHandle *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
     536             :                                         int nDeflateType,
     537             :                                         bool bAutoCloseBaseHandle, int nThreads,
     538             :                                         size_t nChunkSize,
     539             :                                         size_t nSOZIPIndexEltSize,
     540             :                                         std::vector<uint8_t> *panSOZIPIndex);
     541             : 
     542             : VSIVirtualHandle *
     543             : VSICreateUploadOnCloseFile(VSIVirtualHandleUniquePtr &&poWritableHandle,
     544             :                            VSIVirtualHandleUniquePtr &&poTmpFile,
     545             :                            const std::string &osTmpFilename);
     546             : 
     547             : #endif /* ndef CPL_VSI_VIRTUAL_H_INCLUDED */

Generated by: LCOV version 1.14