GDAL
cpl_vsi_virtual.h
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 
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 
84  virtual void AdviseRead(CPL_UNUSED int nRanges,
85  CPL_UNUSED const vsi_l_offset *panOffsets,
86  CPL_UNUSED const size_t *panSizes)
87  {
88  }
89 
102  virtual size_t GetAdviseReadTotalBytesLimit() const
103  {
104  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 void ClearErr() = 0;
113 
114  virtual int Eof() = 0;
115 
116  virtual int Error() = 0;
117 
118  virtual int Flush()
119  {
120  return 0;
121  }
122 
123  virtual int Close() = 0;
124  // Base implementation that only supports file extension.
125  virtual int Truncate(vsi_l_offset nNewSize);
126 
127  virtual void *GetNativeFileDescriptor()
128  {
129  return nullptr;
130  }
131 
133  CPL_UNUSED vsi_l_offset nLength)
134  {
136  }
137 
138  virtual bool HasPRead() const;
139  virtual size_t PRead(void *pBuffer, size_t nSize,
140  vsi_l_offset nOffset) const;
141 
142  // NOTE: when adding new methods, besides the "actual" implementations,
143  // also consider the VSICachedFile one.
144 
145  virtual ~VSIVirtualHandle()
146  {
147  }
148 };
149 
150 /************************************************************************/
151 /* VSIVirtualHandleCloser */
152 /************************************************************************/
153 
157 {
159  void operator()(VSIVirtualHandle *poHandle)
160  {
161  if (poHandle)
162  {
163  poHandle->Close();
164  delete poHandle;
165  }
166  }
167 };
168 
170 typedef std::unique_ptr<VSIVirtualHandle, VSIVirtualHandleCloser>
171  VSIVirtualHandleUniquePtr;
172 
173 /************************************************************************/
174 /* VSIFilesystemHandler */
175 /************************************************************************/
176 
177 #ifndef DOXYGEN_SKIP
178 class CPL_DLL VSIFilesystemHandler
179 {
180 
181  public:
182  virtual ~VSIFilesystemHandler()
183  {
184  }
185 
186  VSIVirtualHandle *Open(const char *pszFilename, const char *pszAccess);
187 
188  virtual VSIVirtualHandle *Open(const char *pszFilename,
189  const char *pszAccess, bool bSetError,
190  CSLConstList papszOptions) = 0;
191  virtual int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
192  int nFlags) = 0;
193 
194  virtual int Unlink(const char *pszFilename)
195  {
196  (void)pszFilename;
197  errno = ENOENT;
198  return -1;
199  }
200 
201  virtual int *UnlinkBatch(CSLConstList papszFiles);
202 
203  virtual int Mkdir(const char *pszDirname, long nMode)
204  {
205  (void)pszDirname;
206  (void)nMode;
207  errno = ENOENT;
208  return -1;
209  }
210 
211  virtual int Rmdir(const char *pszDirname)
212  {
213  (void)pszDirname;
214  errno = ENOENT;
215  return -1;
216  }
217 
218  virtual int RmdirRecursive(const char *pszDirname);
219 
220  char **ReadDir(const char *pszDirname)
221  {
222  return ReadDirEx(pszDirname, 0);
223  }
224 
225  virtual char **ReadDirEx(const char * /*pszDirname*/, int /* nMaxFiles */)
226  {
227  return nullptr;
228  }
229 
230  virtual char **SiblingFiles(const char * /*pszFilename*/)
231  {
232  return nullptr;
233  }
234 
235  virtual int Rename(const char *oldpath, const char *newpath)
236  {
237  (void)oldpath;
238  (void)newpath;
239  errno = ENOENT;
240  return -1;
241  }
242 
243  virtual int IsCaseSensitive(const char *pszFilename)
244  {
245  (void)pszFilename;
246  return TRUE;
247  }
248 
249  virtual GIntBig GetDiskFreeSpace(const char * /* pszDirname */)
250  {
251  return -1;
252  }
253 
254  virtual int SupportsSparseFiles(const char * /* pszPath */)
255  {
256  return FALSE;
257  }
258 
259  virtual int HasOptimizedReadMultiRange(const char * /* pszPath */)
260  {
261  return FALSE;
262  }
263 
264  virtual const char *GetActualURL(const char * /*pszFilename*/)
265  {
266  return nullptr;
267  }
268 
269  virtual const char *GetOptions()
270  {
271  return nullptr;
272  }
273 
274  virtual char *GetSignedURL(const char * /*pszFilename*/,
275  CSLConstList /* papszOptions */)
276  {
277  return nullptr;
278  }
279 
280  virtual bool Sync(const char *pszSource, const char *pszTarget,
281  const char *const *papszOptions,
282  GDALProgressFunc pProgressFunc, void *pProgressData,
283  char ***ppapszOutputs);
284 
285  virtual int CopyFile(const char *pszSource, const char *pszTarget,
286  VSILFILE *fpSource, vsi_l_offset nSourceSize,
287  const char *const *papszOptions,
288  GDALProgressFunc pProgressFunc, void *pProgressData);
289 
290  virtual int
291  CopyFileRestartable(const char *pszSource, const char *pszTarget,
292  const char *pszInputPayload, char **ppszOutputPayload,
293  CSLConstList papszOptions,
294  GDALProgressFunc pProgressFunc, void *pProgressData);
295 
296  virtual VSIDIR *OpenDir(const char *pszPath, int nRecurseDepth,
297  const char *const *papszOptions);
298 
299  virtual char **GetFileMetadata(const char *pszFilename,
300  const char *pszDomain,
301  CSLConstList papszOptions);
302 
303  virtual bool SetFileMetadata(const char *pszFilename,
304  CSLConstList papszMetadata,
305  const char *pszDomain,
306  CSLConstList papszOptions);
307 
308  virtual bool
309  MultipartUploadGetCapabilities(int *pbNonSequentialUploadSupported,
310  int *pbParallelUploadSupported,
311  int *pbAbortSupported, size_t *pnMinPartSize,
312  size_t *pnMaxPartSize, int *pnMaxPartCount);
313 
314  virtual char *MultipartUploadStart(const char *pszFilename,
315  CSLConstList papszOptions);
316 
317  virtual char *MultipartUploadAddPart(const char *pszFilename,
318  const char *pszUploadId,
319  int nPartNumber,
320  vsi_l_offset nFileOffset,
321  const void *pData, size_t nDataLength,
322  CSLConstList papszOptions);
323 
324  virtual bool
325  MultipartUploadEnd(const char *pszFilename, const char *pszUploadId,
326  size_t nPartIdsCount, const char *const *apszPartIds,
327  vsi_l_offset nTotalSize, CSLConstList papszOptions);
328 
329  virtual bool MultipartUploadAbort(const char *pszFilename,
330  const char *pszUploadId,
331  CSLConstList papszOptions);
332 
333  virtual bool AbortPendingUploads(const char * /*pszFilename*/)
334  {
335  return true;
336  }
337 
338  virtual std::string
339  GetStreamingFilename(const std::string &osFilename) const
340  {
341  return osFilename;
342  }
343 
351  virtual std::string
352  GetCanonicalFilename(const std::string &osFilename) const
353  {
354  return osFilename;
355  }
356 
357  virtual bool IsLocal(const char * /* pszPath */)
358  {
359  return true;
360  }
361 
362  virtual bool SupportsSequentialWrite(const char * /* pszPath */,
363  bool /* bAllowLocalTempFile */)
364  {
365  return true;
366  }
367 
368  virtual bool SupportsRandomWrite(const char * /* pszPath */,
369  bool /* bAllowLocalTempFile */)
370  {
371  return true;
372  }
373 
374  virtual bool SupportsRead(const char * /* pszPath */)
375  {
376  return true;
377  }
378 
379  virtual VSIFilesystemHandler *Duplicate(const char * /* pszPrefix */)
380  {
381  CPLError(CE_Failure, CPLE_NotSupported,
382  "Duplicate() not supported on this file system");
383  return nullptr;
384  }
385 
392  virtual const char *GetDirectorySeparator(CPL_UNUSED const char *pszPath)
393  {
394  return "/";
395  }
396 };
397 #endif /* #ifndef DOXYGEN_SKIP */
398 
399 /************************************************************************/
400 /* VSIFileManager */
401 /************************************************************************/
402 
403 #ifndef DOXYGEN_SKIP
404 class CPL_DLL VSIFileManager
405 {
406  private:
407  VSIFilesystemHandler *poDefaultHandler = nullptr;
408  std::map<std::string, VSIFilesystemHandler *> oHandlers{};
409 
410  VSIFileManager();
411 
412  static VSIFileManager *Get();
413 
414  CPL_DISALLOW_COPY_ASSIGN(VSIFileManager)
415 
416  public:
417  ~VSIFileManager();
418 
419  static VSIFilesystemHandler *GetHandler(const char *);
420  static void InstallHandler(const std::string &osPrefix,
421  VSIFilesystemHandler *);
422  static void RemoveHandler(const std::string &osPrefix);
423 
424  static char **GetPrefixes();
425 };
426 #endif /* #ifndef DOXYGEN_SKIP */
427 
428 /************************************************************************/
429 /* ==================================================================== */
430 /* VSIArchiveFilesystemHandler */
431 /* ==================================================================== */
432 /************************************************************************/
433 
434 #ifndef DOXYGEN_SKIP
435 
436 class VSIArchiveEntryFileOffset
437 {
438  public:
439  virtual ~VSIArchiveEntryFileOffset();
440 };
441 
442 typedef struct
443 {
444  char *fileName;
445  vsi_l_offset uncompressed_size;
446  VSIArchiveEntryFileOffset *file_pos;
447  int bIsDir;
448  GIntBig nModifiedTime;
449 } VSIArchiveEntry;
450 
451 class VSIArchiveContent
452 {
453  public:
454  time_t mTime = 0;
455  vsi_l_offset nFileSize = 0;
456  int nEntries = 0;
457  VSIArchiveEntry *entries = nullptr;
458 
459  ~VSIArchiveContent();
460 };
461 
462 class VSIArchiveReader
463 {
464  public:
465  virtual ~VSIArchiveReader();
466 
467  virtual int GotoFirstFile() = 0;
468  virtual int GotoNextFile() = 0;
469  virtual VSIArchiveEntryFileOffset *GetFileOffset() = 0;
470  virtual GUIntBig GetFileSize() = 0;
471  virtual CPLString GetFileName() = 0;
472  virtual GIntBig GetModifiedTime() = 0;
473  virtual int GotoFileOffset(VSIArchiveEntryFileOffset *pOffset) = 0;
474 };
475 
476 class VSIArchiveFilesystemHandler : public VSIFilesystemHandler
477 {
478  CPL_DISALLOW_COPY_ASSIGN(VSIArchiveFilesystemHandler)
479 
480  protected:
481  CPLMutex *hMutex = nullptr;
482  /* We use a cache that contains the list of files contained in a VSIArchive
483  * file as */
484  /* unarchive.c is quite inefficient in listing them. This speeds up access
485  * to VSIArchive files */
486  /* containing ~1000 files like a CADRG product */
487  std::map<CPLString, VSIArchiveContent *> oFileList{};
488 
489  virtual const char *GetPrefix() = 0;
490  virtual std::vector<CPLString> GetExtensions() = 0;
491  virtual VSIArchiveReader *CreateReader(const char *pszArchiveFileName) = 0;
492 
493  public:
494  VSIArchiveFilesystemHandler();
495  virtual ~VSIArchiveFilesystemHandler();
496 
497  int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
498  int nFlags) override;
499  int Unlink(const char *pszFilename) override;
500  int Rename(const char *oldpath, const char *newpath) override;
501  int Mkdir(const char *pszDirname, long nMode) override;
502  int Rmdir(const char *pszDirname) override;
503  char **ReadDirEx(const char *pszDirname, int nMaxFiles) override;
504 
505  virtual const VSIArchiveContent *
506  GetContentOfArchive(const char *archiveFilename,
507  VSIArchiveReader *poReader = nullptr);
508  virtual char *SplitFilename(const char *pszFilename,
509  CPLString &osFileInArchive,
510  int bCheckMainFileExists);
511  virtual VSIArchiveReader *OpenArchiveFile(const char *archiveFilename,
512  const char *fileInArchiveName);
513  virtual int FindFileInArchive(const char *archiveFilename,
514  const char *fileInArchiveName,
515  const VSIArchiveEntry **archiveEntry);
516 
517  virtual bool IsLocal(const char *pszPath) override;
518 
519  virtual bool
520  SupportsSequentialWrite(const char * /* pszPath */,
521  bool /* bAllowLocalTempFile */) override
522  {
523  return false;
524  }
525 
526  virtual bool SupportsRandomWrite(const char * /* pszPath */,
527  bool /* bAllowLocalTempFile */) override
528  {
529  return false;
530  }
531 };
532 
533 /************************************************************************/
534 /* VSIDIR */
535 /************************************************************************/
536 
537 struct CPL_DLL VSIDIR
538 {
539  VSIDIR() = default;
540  virtual ~VSIDIR();
541 
542  virtual const VSIDIREntry *NextDirEntry() = 0;
543 
544  private:
545  VSIDIR(const VSIDIR &) = delete;
546  VSIDIR &operator=(const VSIDIR &) = delete;
547 };
548 
549 #endif /* #ifndef DOXYGEN_SKIP */
550 
551 VSIVirtualHandle CPL_DLL *
552 VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle);
554 VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle,
555  const GByte *pabyBeginningContent,
556  vsi_l_offset nCheatFileSize);
557 constexpr int VSI_CACHED_DEFAULT_CHUNK_SIZE = 32768;
558 VSIVirtualHandle CPL_DLL *
559 VSICreateCachedFile(VSIVirtualHandle *poBaseHandle,
560  size_t nChunkSize = VSI_CACHED_DEFAULT_CHUNK_SIZE,
561  size_t nCacheSize = 0);
562 
563 const int CPL_DEFLATE_TYPE_GZIP = 0;
564 const int CPL_DEFLATE_TYPE_ZLIB = 1;
565 const int CPL_DEFLATE_TYPE_RAW_DEFLATE = 2;
566 VSIVirtualHandle CPL_DLL *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
567  int nDeflateType,
568  int bAutoCloseBaseHandle);
569 
570 VSIVirtualHandle *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
571  int nDeflateType,
572  bool bAutoCloseBaseHandle, int nThreads,
573  size_t nChunkSize,
574  size_t nSOZIPIndexEltSize,
575  std::vector<uint8_t> *panSOZIPIndex);
576 
578 VSICreateUploadOnCloseFile(VSIVirtualHandleUniquePtr &&poWritableHandle,
579  VSIVirtualHandleUniquePtr &&poTmpFile,
580  const std::string &osTmpFilename);
581 
582 #endif /* ndef CPL_VSI_VIRTUAL_H_INCLUDED */
Convenient string class based on std::string.
Definition: cpl_string.h:320
#define CPLE_NotSupported
Not supported.
Definition: cpl_error.h:110
void CPLError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,...)
Report an error.
Definition: cpl_error.cpp:330
unsigned long long GUIntBig
Large unsigned integer type (generally 64-bit unsigned integer type).
Definition: cpl_port.h:218
#define CPL_UNUSED
Qualifier for an argument that is unused.
Definition: cpl_port.h:985
#define CPL_FORMAT_STRING(arg)
Macro into which to wrap the format argument of a printf-like function.
Definition: cpl_port.h:966
#define CPL_PRINT_FUNC_FORMAT(format_idx, arg_idx)
Tag a function to have printf() formatting.
Definition: cpl_port.h:950
#define CPL_DISALLOW_COPY_ASSIGN(ClassName)
Helper to remove the copy and assignment constructors so that the compiler will not generate the defa...
Definition: cpl_port.h:1042
char ** CSLConstList
Type of a constant null-terminated list of nul terminated strings.
Definition: cpl_port.h:1183
unsigned char GByte
Unsigned byte type.
Definition: cpl_port.h:185
long long GIntBig
Large signed integer type (generally 64-bit integer type).
Definition: cpl_port.h:215
Various convenience functions for working with strings and string lists.
Standard C Covers.
#define VSIStatBufL
Type for VSIStatL()
Definition: cpl_vsi.h:205
VSIRangeStatus
Range status.
Definition: cpl_vsi.h:184
@ VSI_RANGE_STATUS_UNKNOWN
Unknown.
Definition: cpl_vsi.h:185
struct VSIDIR VSIDIR
Opaque type for a directory iterator.
Definition: cpl_vsi.h:404
GUIntBig vsi_l_offset
Type for a file offset.
Definition: cpl_vsi.h:146
Directory entry.
Definition: cpl_vsi.h:416
Helper close to use with a std:unique_ptr<VSIVirtualHandle>, such as VSIVirtualHandleUniquePtr.
Definition: cpl_vsi_virtual.h:157
void operator()(VSIVirtualHandle *poHandle)
Operator () that closes and deletes the file handle.
Definition: cpl_vsi_virtual.h:159
Virtual file handle.
Definition: cpl_vsi_virtual.h:63
virtual int Close()=0
Close file.
virtual VSIRangeStatus GetRangeStatus(vsi_l_offset nOffset, vsi_l_offset nLength)
Return if a given file range contains data or holes filled with zeroes.
Definition: cpl_vsi_virtual.h:132
virtual vsi_l_offset Tell()=0
Tell current file offset.
virtual int Seek(vsi_l_offset nOffset, int nWhence)=0
Seek to requested offset.
virtual size_t Read(void *pBuffer, size_t nSize, size_t nCount)=0
Read bytes from file.
virtual void * GetNativeFileDescriptor()
Returns the "native" file descriptor for the virtual handle.
Definition: cpl_vsi_virtual.h:127
virtual size_t GetAdviseReadTotalBytesLimit() const
Return the total maximum number of bytes that AdviseRead() can handle at once.
Definition: cpl_vsi_virtual.h:102
virtual void AdviseRead(int nRanges, const vsi_l_offset *panOffsets, const size_t *panSizes)
This method is called when code plans to access soon one or several ranges in a file.
Definition: cpl_vsi_virtual.h:84
virtual int ReadMultiRange(int nRanges, void **ppData, const vsi_l_offset *panOffsets, const size_t *panSizes)
Read several ranges of bytes from file.
virtual size_t Write(const void *pBuffer, size_t nSize, size_t nCount)=0
Write bytes to file.
virtual int Truncate(vsi_l_offset nNewSize)
Truncate/expand the file to the specified size.