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