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