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