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 :
25 : #include <cstdint>
26 : #include <map>
27 : #include <memory>
28 : #include <mutex>
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 :
52 : #ifdef GDAL_COMPILATION
53 : /*! @cond Doxygen_Suppress */
54 48356 : inline int Seek(int &&nOffset, int nWhence)
55 : {
56 48356 : return Seek(static_cast<vsi_l_offset>(nOffset), nWhence);
57 : }
58 :
59 : inline int Seek(unsigned &&nOffset, int nWhence)
60 : {
61 : return Seek(static_cast<vsi_l_offset>(nOffset), nWhence);
62 : }
63 :
64 : template <typename T>
65 : inline std::enable_if_t<std::is_same_v<T, uint64_t> &&
66 : !std::is_same_v<uint64_t, vsi_l_offset>,
67 : int>
68 82873 : Seek(T nOffset, int nWhence)
69 : {
70 82873 : return Seek(static_cast<vsi_l_offset>(nOffset), nWhence);
71 : }
72 :
73 : template <typename T>
74 : inline std::enable_if_t<std::is_same_v<T, size_t> &&
75 : !std::is_same_v<T, uint64_t> &&
76 : !std::is_same_v<size_t, unsigned> &&
77 : !std::is_same_v<size_t, vsi_l_offset>,
78 : int>
79 : Seek(T nOffset, int nWhence) = delete;
80 :
81 : int Seek(int &nOffset, int nWhence) = delete;
82 : int Seek(const int &nOffset, int nWhence) = delete;
83 : int Seek(unsigned &nOffset, int nWhence) = delete;
84 : int Seek(const unsigned &nOffset, int nWhence) = delete;
85 : /*! @endcond */
86 : #endif
87 :
88 : virtual vsi_l_offset Tell() = 0;
89 : size_t Read(void *pBuffer, size_t nSize, size_t nCount);
90 :
91 : virtual size_t Read(void *pBuffer, size_t nBytes) = 0;
92 :
93 : /** Read a primitive type from LSB-ordered byte sequence.
94 : *
95 : * Failure to read the value can be detected by testing *pbError,
96 : * or Eof() || Error()
97 : *
98 : * @param[out] pbError Pointer to a boolean that will be set to true if
99 : * the value cannot be read, or nullptr.
100 : * Note that this boolean must be initialized to false by the caller,
101 : * and that this method will not set it to false.
102 : */
103 379 : template <class T> inline T ReadLSB(bool *pbError = nullptr)
104 : {
105 : T val;
106 379 : if (Read(&val, sizeof(val)) != sizeof(val))
107 : {
108 2 : if (pbError)
109 2 : *pbError = true;
110 2 : return 0;
111 : }
112 377 : return CPL_AS_LSB(val);
113 : }
114 :
115 : /** Read a primitive type from LSB-ordered byte sequence */
116 2111 : template <class T> inline bool ReadLSB(T &val)
117 : {
118 2111 : if (Read(&val, sizeof(val)) != sizeof(val))
119 : {
120 12 : return false;
121 : }
122 2099 : val = CPL_AS_LSB(val);
123 2099 : return true;
124 : }
125 :
126 : bool ReadLSB(bool &) = delete;
127 :
128 : virtual int ReadMultiRange(int nRanges, void **ppData,
129 : const vsi_l_offset *panOffsets,
130 : const size_t *panSizes);
131 :
132 : /** This method is called when code plans to access soon one or several
133 : * ranges in a file. Some file systems may be able to use this hint to
134 : * for example asynchronously start such requests.
135 : *
136 : * Offsets may be given in a non-increasing order, and may potentially
137 : * overlap.
138 : *
139 : * @param nRanges Size of the panOffsets and panSizes arrays.
140 : * @param panOffsets Array containing the start offset of each range.
141 : * @param panSizes Array containing the size (in bytes) of each range.
142 : * @since GDAL 3.7
143 : */
144 98 : virtual void AdviseRead(CPL_UNUSED int nRanges,
145 : CPL_UNUSED const vsi_l_offset *panOffsets,
146 : CPL_UNUSED const size_t *panSizes)
147 : {
148 98 : }
149 :
150 : /** Return the total maximum number of bytes that AdviseRead() can handle
151 : * at once.
152 : *
153 : * Some AdviseRead() implementations may give up if the sum of the values
154 : * in the panSizes[] array provided to AdviseRead() exceeds a limit.
155 : *
156 : * Callers might use that threshold to optimize the efficiency of
157 : * AdviseRead().
158 : *
159 : * A returned value of 0 indicates a unknown limit.
160 : * @since GDAL 3.9
161 : */
162 226 : virtual size_t GetAdviseReadTotalBytesLimit() const
163 : {
164 226 : return 0;
165 : }
166 :
167 : virtual size_t Write(const void *pBuffer, size_t nBytes) = 0;
168 : size_t Write(const void *pBuffer, size_t nSize, size_t nCount);
169 :
170 : /** Write a primitive type as LSB-ordered byte sequence */
171 18675 : template <class T> inline bool WriteLSB(T val)
172 : {
173 18675 : val = CPL_AS_LSB(val);
174 18675 : return Write(&val, sizeof(val)) == sizeof(val);
175 : }
176 :
177 : int Printf(CPL_FORMAT_STRING(const char *pszFormat), ...)
178 : CPL_PRINT_FUNC_FORMAT(2, 3);
179 :
180 : virtual void ClearErr() = 0;
181 :
182 : virtual int Eof() = 0;
183 :
184 : virtual int Error() = 0;
185 :
186 48853 : virtual int Flush()
187 : {
188 48853 : return 0;
189 : }
190 :
191 : virtual int Close() = 0;
192 : // Base implementation that only supports file extension.
193 : virtual int Truncate(vsi_l_offset nNewSize);
194 :
195 9 : virtual void *GetNativeFileDescriptor()
196 : {
197 9 : return nullptr;
198 : }
199 :
200 154 : virtual VSIRangeStatus GetRangeStatus(CPL_UNUSED vsi_l_offset nOffset,
201 : CPL_UNUSED vsi_l_offset nLength)
202 : {
203 154 : return VSI_RANGE_STATUS_UNKNOWN;
204 : }
205 :
206 : virtual bool HasPRead() const;
207 : virtual size_t PRead(void *pBuffer, size_t nSize,
208 : vsi_l_offset nOffset) const;
209 :
210 : /** Ask current operations to be interrupted.
211 : * Implementations must be thread-safe, as this will typically be called
212 : * from another thread than the active one for this file.
213 : */
214 13 : virtual void Interrupt()
215 : {
216 13 : }
217 :
218 : /** For a file created with CreateOnlyVisibleAtCloseTime(), ask for the
219 : * file to not be created at all (if possible)
220 : */
221 88 : virtual void CancelCreation()
222 : {
223 88 : }
224 :
225 : // NOTE: when adding new methods, besides the "actual" implementations,
226 : // also consider the VSICachedFile and VSIVirtualHandleOnlyVisibleAtCloseTime one.
227 :
228 375228 : virtual ~VSIVirtualHandle()
229 375228 : {
230 375228 : }
231 : };
232 :
233 : /************************************************************************/
234 : /* VSIVirtualHandleCloser */
235 : /************************************************************************/
236 :
237 : /** Helper close to use with a std:unique_ptr<VSIVirtualHandle>,
238 : * such as VSIVirtualHandleUniquePtr. */
239 : struct VSIVirtualHandleCloser
240 :
241 : {
242 : /** Operator () that closes and deletes the file handle. */
243 55577 : void operator()(VSIVirtualHandle *poHandle)
244 : {
245 55577 : if (poHandle)
246 : {
247 55529 : poHandle->Close();
248 55703 : delete poHandle;
249 : }
250 55971 : }
251 : };
252 :
253 : /** Unique pointer of VSIVirtualHandle that calls the Close() method */
254 : typedef std::unique_ptr<VSIVirtualHandle, VSIVirtualHandleCloser>
255 : VSIVirtualHandleUniquePtr;
256 :
257 : /************************************************************************/
258 : /* VSIProxyFileHandle */
259 : /************************************************************************/
260 :
261 : #ifndef DOXYGEN_SKIP
262 : class VSIProxyFileHandle /* non final */ : public VSIVirtualHandle
263 : {
264 : protected:
265 : VSIVirtualHandleUniquePtr m_nativeHandle{};
266 :
267 : public:
268 270 : explicit VSIProxyFileHandle(VSIVirtualHandleUniquePtr &&nativeHandle)
269 270 : : m_nativeHandle(std::move(nativeHandle))
270 : {
271 270 : }
272 :
273 976 : int Seek(vsi_l_offset nOffset, int nWhence) override
274 : {
275 976 : return m_nativeHandle->Seek(nOffset, nWhence);
276 : }
277 :
278 890 : vsi_l_offset Tell() override
279 : {
280 890 : return m_nativeHandle->Tell();
281 : }
282 :
283 1187 : size_t Read(void *pBuffer, size_t nBytes) override
284 : {
285 1187 : return m_nativeHandle->Read(pBuffer, nBytes);
286 : }
287 :
288 0 : int ReadMultiRange(int nRanges, void **ppData,
289 : const vsi_l_offset *panOffsets,
290 : const size_t *panSizes) override
291 : {
292 0 : return m_nativeHandle->ReadMultiRange(nRanges, ppData, panOffsets,
293 0 : panSizes);
294 : }
295 :
296 0 : void AdviseRead(int nRanges, const vsi_l_offset *panOffsets,
297 : const size_t *panSizes) override
298 : {
299 0 : return m_nativeHandle->AdviseRead(nRanges, panOffsets, panSizes);
300 : }
301 :
302 0 : size_t GetAdviseReadTotalBytesLimit() const override
303 : {
304 0 : return m_nativeHandle->GetAdviseReadTotalBytesLimit();
305 : }
306 :
307 5800 : size_t Write(const void *pBuffer, size_t nBytes) override
308 : {
309 5800 : return m_nativeHandle->Write(pBuffer, nBytes);
310 : }
311 :
312 0 : void ClearErr() override
313 : {
314 0 : return m_nativeHandle->ClearErr();
315 : }
316 :
317 0 : int Eof() override
318 : {
319 0 : return m_nativeHandle->Eof();
320 : }
321 :
322 0 : int Error() override
323 : {
324 0 : return m_nativeHandle->Error();
325 : }
326 :
327 11 : int Flush() override
328 : {
329 11 : return m_nativeHandle->Flush();
330 : }
331 :
332 270 : int Close() override
333 : {
334 270 : return m_nativeHandle->Close();
335 : }
336 :
337 0 : int Truncate(vsi_l_offset nNewSize) override
338 : {
339 0 : return m_nativeHandle->Truncate(nNewSize);
340 : }
341 :
342 0 : void *GetNativeFileDescriptor() override
343 : {
344 0 : return m_nativeHandle->GetNativeFileDescriptor();
345 : }
346 :
347 0 : VSIRangeStatus GetRangeStatus(vsi_l_offset nOffset,
348 : vsi_l_offset nLength) override
349 : {
350 0 : return m_nativeHandle->GetRangeStatus(nOffset, nLength);
351 : }
352 :
353 0 : bool HasPRead() const override
354 : {
355 0 : return m_nativeHandle->HasPRead();
356 : }
357 :
358 0 : size_t PRead(void *pBuffer, size_t nSize,
359 : vsi_l_offset nOffset) const override
360 : {
361 0 : return m_nativeHandle->PRead(pBuffer, nSize, nOffset);
362 : }
363 :
364 0 : void Interrupt() override
365 : {
366 0 : m_nativeHandle->Interrupt();
367 0 : }
368 :
369 : void CancelCreation() override;
370 : };
371 : #endif
372 :
373 : /************************************************************************/
374 : /* VSIFilesystemHandler */
375 : /************************************************************************/
376 :
377 : #ifndef DOXYGEN_SKIP
378 : class CPL_DLL VSIFilesystemHandler
379 : {
380 :
381 : public:
382 32802 : virtual ~VSIFilesystemHandler() = default;
383 :
384 : static VSIVirtualHandleUniquePtr
385 : OpenStatic(const char *pszFilename, const char *pszAccess,
386 : bool bSetError = false, CSLConstList papszOptions = nullptr);
387 :
388 : virtual VSIVirtualHandleUniquePtr
389 : Open(const char *pszFilename, const char *pszAccess, bool bSetError = false,
390 : CSLConstList papszOptions = nullptr) = 0;
391 :
392 : virtual VSIVirtualHandleUniquePtr
393 : CreateOnlyVisibleAtCloseTime(const char *pszFilename,
394 : bool bEmulationAllowed,
395 : CSLConstList papszOptions);
396 :
397 : virtual int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
398 : int nFlags) = 0;
399 :
400 4 : virtual int Unlink(const char *pszFilename)
401 : {
402 : (void)pszFilename;
403 4 : errno = ENOENT;
404 4 : return -1;
405 : }
406 :
407 : virtual int *UnlinkBatch(CSLConstList papszFiles);
408 :
409 0 : virtual int Mkdir(const char *pszDirname, long nMode)
410 : {
411 : (void)pszDirname;
412 : (void)nMode;
413 0 : errno = ENOENT;
414 0 : return -1;
415 : }
416 :
417 0 : virtual int Rmdir(const char *pszDirname)
418 : {
419 : (void)pszDirname;
420 0 : errno = ENOENT;
421 0 : return -1;
422 : }
423 :
424 : virtual int RmdirRecursive(const char *pszDirname);
425 :
426 5 : char **ReadDir(const char *pszDirname)
427 : {
428 5 : return ReadDirEx(pszDirname, 0);
429 : }
430 :
431 4 : virtual char **ReadDirEx(const char * /*pszDirname*/, int /* nMaxFiles */)
432 : {
433 4 : return nullptr;
434 : }
435 :
436 82573 : virtual char **SiblingFiles(const char * /*pszFilename*/)
437 : {
438 82573 : return nullptr;
439 : }
440 :
441 0 : virtual int Rename(const char *oldpath, const char *newpath,
442 : GDALProgressFunc pProgressFunc, void *pProgressData)
443 : {
444 : (void)oldpath;
445 : (void)newpath;
446 : (void)pProgressFunc;
447 : (void)pProgressData;
448 0 : errno = ENOENT;
449 0 : return -1;
450 : }
451 :
452 30855 : virtual int IsCaseSensitive(const char *pszFilename)
453 : {
454 : (void)pszFilename;
455 30855 : return TRUE;
456 : }
457 :
458 0 : virtual GIntBig GetDiskFreeSpace(const char * /* pszDirname */)
459 : {
460 0 : return -1;
461 : }
462 :
463 0 : virtual int SupportsSparseFiles(const char * /* pszPath */)
464 : {
465 0 : return FALSE;
466 : }
467 :
468 15639 : virtual int HasOptimizedReadMultiRange(const char * /* pszPath */)
469 : {
470 15639 : return FALSE;
471 : }
472 :
473 1 : virtual const char *GetActualURL(const char * /*pszFilename*/)
474 : {
475 1 : return nullptr;
476 : }
477 :
478 14 : virtual const char *GetOptions()
479 : {
480 14 : return nullptr;
481 : }
482 :
483 1 : virtual char *GetSignedURL(const char * /*pszFilename*/,
484 : CSLConstList /* papszOptions */)
485 : {
486 1 : return nullptr;
487 : }
488 :
489 : virtual bool Sync(const char *pszSource, const char *pszTarget,
490 : const char *const *papszOptions,
491 : GDALProgressFunc pProgressFunc, void *pProgressData,
492 : char ***ppapszOutputs);
493 :
494 : virtual int CopyFile(const char *pszSource, const char *pszTarget,
495 : VSILFILE *fpSource, vsi_l_offset nSourceSize,
496 : const char *const *papszOptions,
497 : GDALProgressFunc pProgressFunc, void *pProgressData);
498 :
499 : virtual int
500 : CopyFileRestartable(const char *pszSource, const char *pszTarget,
501 : const char *pszInputPayload, char **ppszOutputPayload,
502 : CSLConstList papszOptions,
503 : GDALProgressFunc pProgressFunc, void *pProgressData);
504 :
505 : virtual VSIDIR *OpenDir(const char *pszPath, int nRecurseDepth,
506 : const char *const *papszOptions);
507 :
508 : virtual char **GetFileMetadata(const char *pszFilename,
509 : const char *pszDomain,
510 : CSLConstList papszOptions);
511 :
512 : virtual bool SetFileMetadata(const char *pszFilename,
513 : CSLConstList papszMetadata,
514 : const char *pszDomain,
515 : CSLConstList papszOptions);
516 :
517 : virtual bool
518 : MultipartUploadGetCapabilities(int *pbNonSequentialUploadSupported,
519 : int *pbParallelUploadSupported,
520 : int *pbAbortSupported, size_t *pnMinPartSize,
521 : size_t *pnMaxPartSize, int *pnMaxPartCount);
522 :
523 : virtual char *MultipartUploadStart(const char *pszFilename,
524 : CSLConstList papszOptions);
525 :
526 : virtual char *MultipartUploadAddPart(const char *pszFilename,
527 : const char *pszUploadId,
528 : int nPartNumber,
529 : vsi_l_offset nFileOffset,
530 : const void *pData, size_t nDataLength,
531 : CSLConstList papszOptions);
532 :
533 : virtual bool
534 : MultipartUploadEnd(const char *pszFilename, const char *pszUploadId,
535 : size_t nPartIdsCount, const char *const *apszPartIds,
536 : vsi_l_offset nTotalSize, CSLConstList papszOptions);
537 :
538 : virtual bool MultipartUploadAbort(const char *pszFilename,
539 : const char *pszUploadId,
540 : CSLConstList papszOptions);
541 :
542 0 : virtual bool AbortPendingUploads(const char * /*pszFilename*/)
543 : {
544 0 : return true;
545 : }
546 :
547 : virtual std::string
548 33199 : GetStreamingFilename(const std::string &osFilename) const
549 : {
550 33199 : return osFilename;
551 : }
552 :
553 : virtual std::string
554 2341 : GetNonStreamingFilename(const std::string &osFilename) const
555 : {
556 2341 : return osFilename;
557 : }
558 :
559 : /** Return the canonical filename.
560 : *
561 : * May be implemented by case-insensitive filesystems
562 : * (currently Win32 and MacOSX)
563 : * to return the filename with its actual case (i.e. the one that would
564 : * be used when listing the content of the directory).
565 : */
566 : virtual std::string
567 114 : GetCanonicalFilename(const std::string &osFilename) const
568 : {
569 114 : return osFilename;
570 : }
571 :
572 2254 : virtual bool IsLocal(const char * /* pszPath */) const
573 : {
574 2254 : return true;
575 : }
576 :
577 5 : virtual bool IsArchive(const char * /* pszPath */) const
578 : {
579 5 : return false;
580 : }
581 :
582 57 : virtual bool SupportsSequentialWrite(const char * /* pszPath */,
583 : bool /* bAllowLocalTempFile */)
584 : {
585 57 : return true;
586 : }
587 :
588 301 : virtual bool SupportsRandomWrite(const char * /* pszPath */,
589 : bool /* bAllowLocalTempFile */)
590 : {
591 301 : return true;
592 : }
593 :
594 43 : virtual bool SupportsRead(const char * /* pszPath */)
595 : {
596 43 : return true;
597 : }
598 :
599 2 : virtual VSIFilesystemHandler *Duplicate(const char * /* pszPrefix */)
600 : {
601 2 : CPLError(CE_Failure, CPLE_NotSupported,
602 : "Duplicate() not supported on this file "
603 : "system");
604 2 : return nullptr;
605 : }
606 :
607 : /** Return the directory separator.
608 : *
609 : * Default is forward slash. The only exception currently is the Windows
610 : * file system which returns anti-slash, unless the specified path is of the
611 : * form "{drive_letter}:/{rest_of_the_path}".
612 : */
613 960134 : virtual const char *GetDirectorySeparator(CPL_UNUSED const char *pszPath)
614 : {
615 960134 : return "/";
616 : }
617 :
618 : /** Returns a hint about the path that this file system
619 : * could (potentially) recognize given the input path.
620 : *
621 : * e.g. /vsizip/ will return "/vsizip/my.zip" if provided with "my.zip",
622 : * /vsicurl/ will return "/vsicurl/https://example.com" if provided with
623 : * "https://example.com", /vsis3/ will return "/vsis3/bucket/object" if
624 : * provided with "s3://bucket/object", etc.
625 : *
626 : * Returns an empty string if the input path cannot easily be identified
627 : * as a potential match for the file system.
628 : */
629 : virtual std::string
630 143444 : GetHintForPotentiallyRecognizedPath(const std::string &osPath)
631 : {
632 : (void)osPath;
633 143444 : return std::string();
634 : }
635 : };
636 : #endif /* #ifndef DOXYGEN_SKIP */
637 :
638 : /************************************************************************/
639 : /* VSIFileManager */
640 : /************************************************************************/
641 :
642 : #ifndef DOXYGEN_SKIP
643 2939 : class CPL_DLL VSIFileManager
644 : {
645 : private:
646 : std::shared_ptr<VSIFilesystemHandler> m_poDefaultHandler{};
647 : std::map<std::string, std::shared_ptr<VSIFilesystemHandler>>
648 : m_apoHandlers{};
649 :
650 : VSIFileManager();
651 :
652 : static VSIFileManager *Get();
653 :
654 : CPL_DISALLOW_COPY_ASSIGN(VSIFileManager)
655 :
656 : public:
657 : ~VSIFileManager();
658 :
659 : static VSIFilesystemHandler *GetHandler(const char *);
660 : static void InstallHandler(const std::string &osPrefix,
661 : const std::shared_ptr<VSIFilesystemHandler> &);
662 : static void InstallHandler(const std::string &osPrefix,
663 : VSIFilesystemHandler *)
664 : CPL_WARN_DEPRECATED("Use version with std::shared_ptr<> instead");
665 : static void RemoveHandler(const std::string &osPrefix);
666 :
667 : static char **GetPrefixes();
668 : };
669 : #endif /* #ifndef DOXYGEN_SKIP */
670 :
671 : /************************************************************************/
672 : /* ==================================================================== */
673 : /* VSIArchiveFilesystemHandler */
674 : /* ==================================================================== */
675 : /************************************************************************/
676 :
677 : #ifndef DOXYGEN_SKIP
678 :
679 1548 : class VSIArchiveEntryFileOffset
680 : {
681 : public:
682 : virtual ~VSIArchiveEntryFileOffset();
683 : };
684 :
685 : class VSIArchiveEntry
686 : {
687 : public:
688 : std::string fileName{};
689 : vsi_l_offset uncompressed_size = 0;
690 : std::unique_ptr<VSIArchiveEntryFileOffset> file_pos{};
691 : bool bIsDir = false;
692 : GIntBig nModifiedTime = 0;
693 : };
694 :
695 75 : class VSIArchiveContent
696 : {
697 : public:
698 : time_t mTime = 0;
699 : vsi_l_offset nFileSize = 0;
700 : std::vector<VSIArchiveEntry> entries{};
701 :
702 : // Store list of child indices for each directory
703 : using DirectoryChildren = std::vector<int>;
704 :
705 : std::map<std::string, DirectoryChildren> dirIndex{};
706 :
707 230 : VSIArchiveContent() = default;
708 :
709 : ~VSIArchiveContent();
710 :
711 : private:
712 : CPL_DISALLOW_COPY_ASSIGN(VSIArchiveContent)
713 : };
714 :
715 5528 : class VSIArchiveReader
716 : {
717 : public:
718 : virtual ~VSIArchiveReader();
719 :
720 : virtual int GotoFirstFile() = 0;
721 : virtual int GotoNextFile() = 0;
722 : virtual VSIArchiveEntryFileOffset *GetFileOffset() = 0;
723 : virtual GUIntBig GetFileSize() = 0;
724 : virtual CPLString GetFileName() = 0;
725 : virtual GIntBig GetModifiedTime() = 0;
726 : virtual int GotoFileOffset(VSIArchiveEntryFileOffset *pOffset) = 0;
727 : };
728 :
729 5878 : class VSIArchiveFilesystemHandler /* non final */ : public VSIFilesystemHandler
730 : {
731 : CPL_DISALLOW_COPY_ASSIGN(VSIArchiveFilesystemHandler)
732 :
733 : bool FindFileInArchive(const char *archiveFilename,
734 : const char *fileInArchiveName,
735 : const VSIArchiveEntry **archiveEntry);
736 :
737 : protected:
738 : mutable std::recursive_mutex oMutex{};
739 :
740 : /* We use a cache that contains the list of files contained in a VSIArchive
741 : * file as */
742 : /* unarchive.c is quite inefficient in listing them. This speeds up access
743 : * to VSIArchive files */
744 : /* containing ~1000 files like a CADRG product */
745 : std::map<CPLString, std::unique_ptr<VSIArchiveContent>> oFileList{};
746 :
747 : virtual const char *GetPrefix() const = 0;
748 : virtual std::vector<CPLString> GetExtensions() const = 0;
749 : virtual std::unique_ptr<VSIArchiveReader>
750 : CreateReader(const char *pszArchiveFileName) = 0;
751 :
752 : public:
753 : VSIArchiveFilesystemHandler();
754 : ~VSIArchiveFilesystemHandler() override;
755 :
756 : int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
757 : int nFlags) override;
758 : char **ReadDirEx(const char *pszDirname, int nMaxFiles) override;
759 :
760 : virtual const VSIArchiveContent *
761 : GetContentOfArchive(const char *archiveFilename,
762 : VSIArchiveReader *poReader = nullptr);
763 : virtual std::unique_ptr<char, VSIFreeReleaser>
764 : SplitFilename(const char *pszFilename, CPLString &osFileInArchive,
765 : bool bCheckMainFileExists, bool bSetError) const;
766 : virtual std::unique_ptr<VSIArchiveReader>
767 : OpenArchiveFile(const char *archiveFilename, const char *fileInArchiveName);
768 :
769 : bool IsLocal(const char *pszPath) const override;
770 :
771 : bool IsArchive(const char *pszPath) const override;
772 :
773 0 : bool SupportsSequentialWrite(const char * /* pszPath */,
774 : bool /* bAllowLocalTempFile */) override
775 : {
776 0 : return false;
777 : }
778 :
779 0 : bool SupportsRandomWrite(const char * /* pszPath */,
780 : bool /* bAllowLocalTempFile */) override
781 : {
782 0 : return false;
783 : }
784 :
785 : std::string
786 : GetHintForPotentiallyRecognizedPath(const std::string &osPath) override;
787 : };
788 :
789 : /************************************************************************/
790 : /* VSIDIR */
791 : /************************************************************************/
792 :
793 : struct CPL_DLL VSIDIR
794 : {
795 3752 : VSIDIR() = default;
796 : virtual ~VSIDIR();
797 :
798 : virtual const VSIDIREntry *NextDirEntry() = 0;
799 :
800 : private:
801 : VSIDIR(const VSIDIR &) = delete;
802 : VSIDIR &operator=(const VSIDIR &) = delete;
803 : };
804 :
805 : #endif /* #ifndef DOXYGEN_SKIP */
806 :
807 : VSIVirtualHandle CPL_DLL *
808 : VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle);
809 : VSIVirtualHandle *
810 : VSICreateBufferedReaderHandle(VSIVirtualHandle *poBaseHandle,
811 : const GByte *pabyBeginningContent,
812 : vsi_l_offset nCheatFileSize);
813 : constexpr int VSI_CACHED_DEFAULT_CHUNK_SIZE = 32768;
814 : VSIVirtualHandle CPL_DLL *
815 : VSICreateCachedFile(VSIVirtualHandle *poBaseHandle,
816 : size_t nChunkSize = VSI_CACHED_DEFAULT_CHUNK_SIZE,
817 : size_t nCacheSize = 0);
818 :
819 : const int CPL_DEFLATE_TYPE_GZIP = 0;
820 : const int CPL_DEFLATE_TYPE_ZLIB = 1;
821 : const int CPL_DEFLATE_TYPE_RAW_DEFLATE = 2;
822 : VSIVirtualHandle CPL_DLL *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
823 : int nDeflateType,
824 : int bAutoCloseBaseHandle);
825 :
826 : VSIVirtualHandle *VSICreateGZipWritable(VSIVirtualHandle *poBaseHandle,
827 : int nDeflateType,
828 : bool bAutoCloseBaseHandle, int nThreads,
829 : size_t nChunkSize,
830 : size_t nSOZIPIndexEltSize,
831 : std::vector<uint8_t> *panSOZIPIndex);
832 :
833 : VSIVirtualHandle *
834 : VSICreateUploadOnCloseFile(VSIVirtualHandleUniquePtr &&poWritableHandle,
835 : VSIVirtualHandleUniquePtr &&poTmpFile,
836 : const std::string &osTmpFilename);
837 :
838 : #endif /* ndef CPL_VSI_VIRTUAL_H_INCLUDED */
|