Line data Source code
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 : * SPDX-License-Identifier: MIT
16 : ****************************************************************************/
17 :
18 : #ifndef CPL_VSI_VIRTUAL_H_INCLUDED
19 : #define CPL_VSI_VIRTUAL_H_INCLUDED
20 :
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 90 : virtual void AdviseRead(CPL_UNUSED int nRanges,
69 : CPL_UNUSED const vsi_l_offset *panOffsets,
70 : CPL_UNUSED const size_t *panSizes)
71 : {
72 90 : }
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 217 : virtual size_t GetAdviseReadTotalBytesLimit() const
87 : {
88 217 : 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 34026 : virtual int Flush()
103 : {
104 34026 : 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 296473 : virtual ~VSIVirtualHandle()
138 296473 : {
139 296473 : }
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 4505 : void operator()(VSIVirtualHandle *poHandle)
152 : {
153 4505 : if (poHandle)
154 : {
155 4487 : poHandle->Close();
156 4487 : delete poHandle;
157 : }
158 4505 : }
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 25193 : virtual ~VSIFilesystemHandler()
175 25193 : {
176 25193 : }
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 0 : virtual int Unlink(const char *pszFilename)
187 : {
188 : (void)pszFilename;
189 0 : errno = ENOENT;
190 0 : 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 4 : char **ReadDir(const char *pszDirname)
213 : {
214 4 : return ReadDirEx(pszDirname, 0);
215 : }
216 :
217 3 : virtual char **ReadDirEx(const char * /*pszDirname*/, int /* nMaxFiles */)
218 : {
219 3 : return nullptr;
220 : }
221 :
222 68999 : virtual char **SiblingFiles(const char * /*pszFilename*/)
223 : {
224 68999 : return nullptr;
225 : }
226 :
227 0 : virtual int Rename(const char *oldpath, const char *newpath)
228 : {
229 : (void)oldpath;
230 : (void)newpath;
231 0 : errno = ENOENT;
232 0 : return -1;
233 : }
234 :
235 25738 : virtual int IsCaseSensitive(const char *pszFilename)
236 : {
237 : (void)pszFilename;
238 25738 : return TRUE;
239 : }
240 :
241 0 : virtual GIntBig GetDiskFreeSpace(const char * /* pszDirname */)
242 : {
243 0 : return -1;
244 : }
245 :
246 0 : virtual int SupportsSparseFiles(const char * /* pszPath */)
247 : {
248 0 : return FALSE;
249 : }
250 :
251 12372 : virtual int HasOptimizedReadMultiRange(const char * /* pszPath */)
252 : {
253 12372 : return FALSE;
254 : }
255 :
256 1 : virtual const char *GetActualURL(const char * /*pszFilename*/)
257 : {
258 1 : return nullptr;
259 : }
260 :
261 11 : virtual const char *GetOptions()
262 : {
263 11 : return nullptr;
264 : }
265 :
266 1 : virtual char *GetSignedURL(const char * /*pszFilename*/,
267 : CSLConstList /* papszOptions */)
268 : {
269 1 : return nullptr;
270 : }
271 :
272 : virtual bool Sync(const char *pszSource, const char *pszTarget,
273 : const char *const *papszOptions,
274 : GDALProgressFunc pProgressFunc, void *pProgressData,
275 : char ***ppapszOutputs);
276 :
277 : virtual int CopyFile(const char *pszSource, const char *pszTarget,
278 : VSILFILE *fpSource, vsi_l_offset nSourceSize,
279 : const char *const *papszOptions,
280 : GDALProgressFunc pProgressFunc, void *pProgressData);
281 :
282 : virtual int
283 : CopyFileRestartable(const char *pszSource, const char *pszTarget,
284 : const char *pszInputPayload, char **ppszOutputPayload,
285 : CSLConstList papszOptions,
286 : GDALProgressFunc pProgressFunc, void *pProgressData);
287 :
288 : virtual VSIDIR *OpenDir(const char *pszPath, int nRecurseDepth,
289 : const char *const *papszOptions);
290 :
291 : virtual char **GetFileMetadata(const char *pszFilename,
292 : const char *pszDomain,
293 : CSLConstList papszOptions);
294 :
295 : virtual bool SetFileMetadata(const char *pszFilename,
296 : CSLConstList papszMetadata,
297 : const char *pszDomain,
298 : CSLConstList papszOptions);
299 :
300 : virtual bool
301 : MultipartUploadGetCapabilities(int *pbNonSequentialUploadSupported,
302 : int *pbParallelUploadSupported,
303 : int *pbAbortSupported, size_t *pnMinPartSize,
304 : size_t *pnMaxPartSize, int *pnMaxPartCount);
305 :
306 : virtual char *MultipartUploadStart(const char *pszFilename,
307 : CSLConstList papszOptions);
308 :
309 : virtual char *MultipartUploadAddPart(const char *pszFilename,
310 : const char *pszUploadId,
311 : int nPartNumber,
312 : vsi_l_offset nFileOffset,
313 : const void *pData, size_t nDataLength,
314 : CSLConstList papszOptions);
315 :
316 : virtual bool
317 : MultipartUploadEnd(const char *pszFilename, const char *pszUploadId,
318 : size_t nPartIdsCount, const char *const *apszPartIds,
319 : vsi_l_offset nTotalSize, CSLConstList papszOptions);
320 :
321 : virtual bool MultipartUploadAbort(const char *pszFilename,
322 : const char *pszUploadId,
323 : CSLConstList papszOptions);
324 :
325 0 : virtual bool AbortPendingUploads(const char * /*pszFilename*/)
326 : {
327 0 : return true;
328 : }
329 :
330 : virtual std::string
331 26585 : GetStreamingFilename(const std::string &osFilename) const
332 : {
333 26585 : return osFilename;
334 : }
335 :
336 : virtual std::string
337 1250 : GetNonStreamingFilename(const std::string &osFilename) const
338 : {
339 1250 : return osFilename;
340 : }
341 :
342 : /** Return the canonical filename.
343 : *
344 : * May be implemented by case-insensitive filesystems
345 : * (currently Win32 and MacOSX)
346 : * to return the filename with its actual case (i.e. the one that would
347 : * be used when listing the content of the directory).
348 : */
349 : virtual std::string
350 248 : GetCanonicalFilename(const std::string &osFilename) const
351 : {
352 248 : return osFilename;
353 : }
354 :
355 98 : virtual bool IsLocal(const char * /* pszPath */)
356 : {
357 98 : return true;
358 : }
359 :
360 43 : virtual bool SupportsSequentialWrite(const char * /* pszPath */,
361 : bool /* bAllowLocalTempFile */)
362 : {
363 43 : return true;
364 : }
365 :
366 285 : virtual bool SupportsRandomWrite(const char * /* pszPath */,
367 : bool /* bAllowLocalTempFile */)
368 : {
369 285 : return true;
370 : }
371 :
372 43 : virtual bool SupportsRead(const char * /* pszPath */)
373 : {
374 43 : return true;
375 : }
376 :
377 2 : virtual VSIFilesystemHandler *Duplicate(const char * /* pszPrefix */)
378 : {
379 2 : CPLError(CE_Failure, CPLE_NotSupported,
380 : "Duplicate() not supported on this file system");
381 2 : return nullptr;
382 : }
383 :
384 : /** Return the directory separator.
385 : *
386 : * Default is forward slash. The only exception currently is the Windows
387 : * file system which returns anti-slash, unless the specified path is of the
388 : * form "{drive_letter}:/{rest_of_the_path}".
389 : */
390 865904 : virtual const char *GetDirectorySeparator(CPL_UNUSED const char *pszPath)
391 : {
392 865904 : return "/";
393 : }
394 : };
395 : #endif /* #ifndef DOXYGEN_SKIP */
396 :
397 : /************************************************************************/
398 : /* VSIFileManager */
399 : /************************************************************************/
400 :
401 : #ifndef DOXYGEN_SKIP
402 : class CPL_DLL VSIFileManager
403 : {
404 : private:
405 : VSIFilesystemHandler *poDefaultHandler = nullptr;
406 : std::map<std::string, VSIFilesystemHandler *> oHandlers{};
407 :
408 : VSIFileManager();
409 :
410 : static VSIFileManager *Get();
411 :
412 : CPL_DISALLOW_COPY_ASSIGN(VSIFileManager)
413 :
414 : public:
415 : ~VSIFileManager();
416 :
417 : static VSIFilesystemHandler *GetHandler(const char *);
418 : static void InstallHandler(const std::string &osPrefix,
419 : VSIFilesystemHandler *);
420 : static void RemoveHandler(const std::string &osPrefix);
421 :
422 : static char **GetPrefixes();
423 : };
424 : #endif /* #ifndef DOXYGEN_SKIP */
425 :
426 : /************************************************************************/
427 : /* ==================================================================== */
428 : /* VSIArchiveFilesystemHandler */
429 : /* ==================================================================== */
430 : /************************************************************************/
431 :
432 : #ifndef DOXYGEN_SKIP
433 :
434 : class VSIArchiveEntryFileOffset
435 : {
436 : public:
437 : virtual ~VSIArchiveEntryFileOffset();
438 : };
439 :
440 : typedef struct
441 : {
442 : char *fileName;
443 : vsi_l_offset uncompressed_size;
444 : VSIArchiveEntryFileOffset *file_pos;
445 : int bIsDir;
446 : GIntBig nModifiedTime;
447 : } VSIArchiveEntry;
448 :
449 : class VSIArchiveContent
450 : {
451 : public:
452 : time_t mTime = 0;
453 : vsi_l_offset nFileSize = 0;
454 : int nEntries = 0;
455 : VSIArchiveEntry *entries = nullptr;
456 :
457 : ~VSIArchiveContent();
458 : };
459 :
460 : class VSIArchiveReader
461 : {
462 : public:
463 : virtual ~VSIArchiveReader();
464 :
465 : virtual int GotoFirstFile() = 0;
466 : virtual int GotoNextFile() = 0;
467 : virtual VSIArchiveEntryFileOffset *GetFileOffset() = 0;
468 : virtual GUIntBig GetFileSize() = 0;
469 : virtual CPLString GetFileName() = 0;
470 : virtual GIntBig GetModifiedTime() = 0;
471 : virtual int GotoFileOffset(VSIArchiveEntryFileOffset *pOffset) = 0;
472 : };
473 :
474 : class VSIArchiveFilesystemHandler : public VSIFilesystemHandler
475 : {
476 : CPL_DISALLOW_COPY_ASSIGN(VSIArchiveFilesystemHandler)
477 :
478 : protected:
479 : CPLMutex *hMutex = nullptr;
480 : /* We use a cache that contains the list of files contained in a VSIArchive
481 : * file as */
482 : /* unarchive.c is quite inefficient in listing them. This speeds up access
483 : * to VSIArchive files */
484 : /* containing ~1000 files like a CADRG product */
485 : std::map<CPLString, VSIArchiveContent *> oFileList{};
486 :
487 : virtual const char *GetPrefix() = 0;
488 : virtual std::vector<CPLString> GetExtensions() = 0;
489 : virtual VSIArchiveReader *CreateReader(const char *pszArchiveFileName) = 0;
490 :
491 : public:
492 : VSIArchiveFilesystemHandler();
493 : virtual ~VSIArchiveFilesystemHandler();
494 :
495 : int Stat(const char *pszFilename, VSIStatBufL *pStatBuf,
496 : int nFlags) override;
497 : int Unlink(const char *pszFilename) override;
498 : int Rename(const char *oldpath, const char *newpath) override;
499 : int Mkdir(const char *pszDirname, long nMode) override;
500 : int Rmdir(const char *pszDirname) 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 : int bCheckMainFileExists);
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 2804 : 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 */
|