Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Virtual GDAL Datasets
4 : * Purpose: Implementation of VRTRawRasterBand
5 : * Author: Frank Warmerdam <warmerdam@pobox.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
9 : * Copyright (c) 2007-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "rawdataset.h"
16 : #include "vrtdataset.h"
17 :
18 : #include <cerrno>
19 : #include <cstdio>
20 : #include <cstdlib>
21 : #include <cstring>
22 :
23 : #include "cpl_conv.h"
24 : #include "cpl_error.h"
25 : #include "cpl_hash_set.h"
26 : #include "cpl_minixml.h"
27 : #include "cpl_string.h"
28 : #include "cpl_vsi.h"
29 : #include "gdal.h"
30 : #include "gdal_priv.h"
31 :
32 : /*! @cond Doxygen_Suppress */
33 :
34 : /************************************************************************/
35 : /* ==================================================================== */
36 : /* VRTRawRasterBand */
37 : /* ==================================================================== */
38 : /************************************************************************/
39 :
40 : /************************************************************************/
41 : /* VRTRawRasterBand() */
42 : /************************************************************************/
43 :
44 38 : VRTRawRasterBand::VRTRawRasterBand(GDALDataset *poDSIn, int nBandIn,
45 38 : GDALDataType eType)
46 : : m_poRawRaster(nullptr), m_pszSourceFilename(nullptr),
47 38 : m_bRelativeToVRT(FALSE)
48 : {
49 38 : if (!VRTDataset::IsRawRasterBandEnabled())
50 : {
51 : // Safety belt. Not supposed to happen, hence CE_Fatal
52 0 : CPLError(CE_Fatal, CPLE_NotSupported,
53 : "Crashing process: VRTRawRasterBand constructor called "
54 : "whereas not authorized");
55 0 : return;
56 : }
57 :
58 38 : Initialize(poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize());
59 :
60 : // Declared in GDALRasterBand.
61 38 : poDS = poDSIn;
62 38 : nBand = nBandIn;
63 :
64 38 : if (eType != GDT_Unknown)
65 6 : eDataType = eType;
66 : }
67 :
68 : /************************************************************************/
69 : /* ~VRTRawRasterBand() */
70 : /************************************************************************/
71 :
72 76 : VRTRawRasterBand::~VRTRawRasterBand()
73 :
74 : {
75 38 : FlushCache(true);
76 38 : ClearRawLink();
77 76 : }
78 :
79 : /************************************************************************/
80 : /* IRasterIO() */
81 : /************************************************************************/
82 :
83 265 : CPLErr VRTRawRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
84 : int nXSize, int nYSize, void *pData,
85 : int nBufXSize, int nBufYSize,
86 : GDALDataType eBufType, GSpacing nPixelSpace,
87 : GSpacing nLineSpace,
88 : GDALRasterIOExtraArg *psExtraArg)
89 : {
90 265 : if (m_poRawRaster == nullptr)
91 : {
92 0 : CPLError(CE_Failure, CPLE_AppDefined,
93 : "No raw raster band configured on VRTRawRasterBand.");
94 0 : return CE_Failure;
95 : }
96 :
97 265 : if (eRWFlag == GF_Write && eAccess == GA_ReadOnly)
98 : {
99 0 : CPLError(CE_Failure, CPLE_NoWriteAccess,
100 : "Attempt to write to read only dataset in"
101 : "VRTRawRasterBand::IRasterIO().");
102 :
103 0 : return CE_Failure;
104 : }
105 :
106 : /* -------------------------------------------------------------------- */
107 : /* Do we have overviews that would be appropriate to satisfy */
108 : /* this request? */
109 : /* -------------------------------------------------------------------- */
110 265 : if ((nBufXSize < nXSize || nBufYSize < nYSize) && GetOverviewCount() > 0)
111 : {
112 0 : if (OverviewRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
113 : nBufXSize, nBufYSize, eBufType, nPixelSpace,
114 0 : nLineSpace, psExtraArg) == CE_None)
115 0 : return CE_None;
116 : }
117 :
118 265 : m_poRawRaster->SetAccess(eAccess);
119 265 : m_poRawRaster->SetTruncatedFileAllowed(eAccess == GA_Update);
120 :
121 265 : return m_poRawRaster->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
122 : nBufXSize, nBufYSize, eBufType, nPixelSpace,
123 265 : nLineSpace, psExtraArg);
124 : }
125 :
126 : /************************************************************************/
127 : /* IReadBlock() */
128 : /************************************************************************/
129 :
130 70 : CPLErr VRTRawRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
131 : void *pImage)
132 :
133 : {
134 70 : if (m_poRawRaster == nullptr)
135 : {
136 0 : CPLError(CE_Failure, CPLE_AppDefined,
137 : "No raw raster band configured on VRTRawRasterBand.");
138 0 : return CE_Failure;
139 : }
140 :
141 70 : return m_poRawRaster->ReadBlock(nBlockXOff, nBlockYOff, pImage);
142 : }
143 :
144 : /************************************************************************/
145 : /* IWriteBlock() */
146 : /************************************************************************/
147 :
148 0 : CPLErr VRTRawRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
149 : void *pImage)
150 :
151 : {
152 0 : if (m_poRawRaster == nullptr)
153 : {
154 0 : CPLError(CE_Failure, CPLE_AppDefined,
155 : "No raw raster band configured on VRTRawRasterBand.");
156 0 : return CE_Failure;
157 : }
158 :
159 0 : m_poRawRaster->SetAccess(eAccess);
160 :
161 0 : return m_poRawRaster->WriteBlock(nBlockXOff, nBlockYOff, pImage);
162 : }
163 :
164 : /************************************************************************/
165 : /* SetRawLink() */
166 : /************************************************************************/
167 :
168 38 : CPLErr VRTRawRasterBand::SetRawLink(const char *pszFilename,
169 : const char *pszVRTPath,
170 : int bRelativeToVRTIn,
171 : vsi_l_offset nImageOffset, int nPixelOffset,
172 : int nLineOffset, const char *pszByteOrder)
173 :
174 : {
175 38 : ClearRawLink();
176 :
177 38 : static_cast<VRTDataset *>(poDS)->SetNeedsFlush();
178 :
179 : /* -------------------------------------------------------------------- */
180 : /* Prepare filename. */
181 : /* -------------------------------------------------------------------- */
182 38 : if (pszFilename == nullptr)
183 : {
184 0 : CPLError(CE_Warning, CPLE_AppDefined,
185 : "Missing <SourceFilename> element in VRTRasterBand.");
186 0 : return CE_Failure;
187 : }
188 :
189 : const std::string osExpandedFilename =
190 28 : (pszVRTPath && bRelativeToVRTIn)
191 38 : ? CPLProjectRelativeFilenameSafe(pszVRTPath, pszFilename)
192 132 : : pszFilename;
193 :
194 : const char *pszAllowedPaths =
195 38 : CPLGetConfigOption("GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE", nullptr);
196 38 : if (pszAllowedPaths == nullptr ||
197 12 : EQUAL(pszAllowedPaths, "SIBLING_OR_CHILD_OF_VRT_PATH"))
198 : {
199 28 : const char *pszErrorMsgPart =
200 : pszAllowedPaths
201 28 : ? "GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE=SIBLING_OR_CHILD_OF_"
202 : "VRT_PATH"
203 : : "the GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE configuration "
204 : "option is not set (and thus defaults to "
205 : "SIBLING_OR_CHILD_OF_VRT_PATH. Consult "
206 : "https://gdal.org/drivers/raster/"
207 : "vrt.html#vrtrawrasterband_restricted_access for more "
208 : "details)";
209 28 : if (!bRelativeToVRTIn)
210 : {
211 1 : CPLError(CE_Failure, CPLE_AppDefined,
212 : "'%s' is invalid because the relativeToVRT flag is not "
213 : "set and %s",
214 : pszFilename, pszErrorMsgPart);
215 1 : return CE_Failure;
216 : }
217 27 : if (!CPLIsFilenameRelative(pszFilename))
218 : {
219 1 : CPLError(CE_Failure, CPLE_AppDefined,
220 : "'%s' is invalid because it is not relative to the VRT "
221 : "path and %s",
222 : pszFilename, pszErrorMsgPart);
223 1 : return CE_Failure;
224 : }
225 26 : if (strstr(pszFilename, "../") || strstr(pszFilename, "..\\"))
226 : {
227 1 : CPLError(CE_Failure, CPLE_AppDefined,
228 : "'%s' is invalid because it may not be a sibling or "
229 : "child of the VRT path and %s",
230 : pszFilename, pszErrorMsgPart);
231 1 : return CE_Failure;
232 25 : }
233 : }
234 10 : else if (EQUAL(pszAllowedPaths, "ALL"))
235 : {
236 : // ok
237 : }
238 6 : else if (EQUAL(pszAllowedPaths, "ONLY_REMOTE"))
239 : {
240 2 : if (VSIIsLocal(pszFilename))
241 : {
242 1 : CPLError(CE_Failure, CPLE_AppDefined,
243 : "'%s' is a local file, whereas "
244 : "GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE=ONLY_REMOTE is set",
245 : pszFilename);
246 1 : return CE_Failure;
247 : }
248 : }
249 : else
250 : {
251 4 : if (strstr(pszFilename, "../") || strstr(pszFilename, "..\\"))
252 : {
253 1 : CPLError(CE_Failure, CPLE_AppDefined,
254 : "'%s' is invalid because the presence of ../ in it may "
255 : "escape from the allowed path(s)",
256 : pszFilename);
257 3 : return CE_Failure;
258 : }
259 : #ifdef _WIN32
260 : constexpr const char *pszSep = ";";
261 : #else
262 3 : constexpr const char *pszSep = ":";
263 : #endif
264 3 : bool bOK = false;
265 : const CPLStringList aosPaths(
266 3 : CSLTokenizeString2(pszAllowedPaths, pszSep, 0));
267 4 : for (const char *pszPath : aosPaths)
268 : {
269 3 : if (CPLIsFilenameRelative(pszPath))
270 : {
271 1 : CPLError(
272 : CE_Failure, CPLE_AppDefined,
273 : "Invalid value for GDAL_VRT_RAWRASTERBAND_ALLOWED_SOURCE. "
274 : "'%s' is not an absolute path",
275 : pszPath);
276 1 : return CE_Failure;
277 : }
278 2 : if (STARTS_WITH(osExpandedFilename.c_str(), pszPath))
279 : {
280 1 : bOK = true;
281 1 : break;
282 : }
283 : }
284 2 : if (!bOK)
285 : {
286 1 : CPLError(CE_Failure, CPLE_AppDefined,
287 : "'%s' is invalid because it is not contained in one of "
288 : "the allowed path(s)",
289 : pszFilename);
290 1 : return CE_Failure;
291 : }
292 : }
293 :
294 : /* -------------------------------------------------------------------- */
295 : /* Try and open the file. We always use the large file API. */
296 : /* -------------------------------------------------------------------- */
297 31 : CPLPushErrorHandler(CPLQuietErrorHandler);
298 31 : FILE *fp = CPLOpenShared(osExpandedFilename.c_str(), "rb+", TRUE);
299 :
300 31 : if (fp == nullptr)
301 5 : fp = CPLOpenShared(osExpandedFilename.c_str(), "rb", TRUE);
302 :
303 35 : if (fp == nullptr &&
304 4 : static_cast<VRTDataset *>(poDS)->GetAccess() == GA_Update)
305 : {
306 3 : fp = CPLOpenShared(osExpandedFilename.c_str(), "wb+", TRUE);
307 : }
308 31 : CPLPopErrorHandler();
309 31 : CPLErrorReset();
310 :
311 31 : if (fp == nullptr)
312 : {
313 1 : CPLError(CE_Failure, CPLE_OpenFailed, "Unable to open %s.%s",
314 1 : osExpandedFilename.c_str(), VSIStrerror(errno));
315 :
316 1 : return CE_Failure;
317 : }
318 :
319 30 : if (!RAWDatasetCheckMemoryUsage(
320 : nRasterXSize, nRasterYSize, 1,
321 : GDALGetDataTypeSizeBytes(GetRasterDataType()), nPixelOffset,
322 : nLineOffset, nImageOffset, 0, reinterpret_cast<VSILFILE *>(fp)))
323 : {
324 2 : CPLCloseShared(fp);
325 2 : return CE_Failure;
326 : }
327 :
328 28 : m_pszSourceFilename = CPLStrdup(pszFilename);
329 28 : m_bRelativeToVRT = bRelativeToVRTIn;
330 :
331 : /* -------------------------------------------------------------------- */
332 : /* Work out if we are in native mode or not. */
333 : /* -------------------------------------------------------------------- */
334 : RawRasterBand::ByteOrder eByteOrder;
335 : if constexpr (CPL_IS_LSB)
336 28 : eByteOrder = RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN;
337 : else
338 : eByteOrder = RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN;
339 :
340 28 : if (pszByteOrder != nullptr)
341 : {
342 26 : if (EQUAL(pszByteOrder, "LSB"))
343 14 : eByteOrder = RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN;
344 12 : else if (EQUAL(pszByteOrder, "MSB"))
345 7 : eByteOrder = RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN;
346 5 : else if (EQUAL(pszByteOrder, "VAX"))
347 4 : eByteOrder = RawRasterBand::ByteOrder::ORDER_VAX;
348 : else
349 : {
350 1 : CPLError(CE_Failure, CPLE_AppDefined,
351 : "Illegal ByteOrder value '%s', should be LSB, MSB or VAX.",
352 : pszByteOrder);
353 1 : CPLCloseShared(fp);
354 1 : return CE_Failure;
355 : }
356 : }
357 :
358 : /* -------------------------------------------------------------------- */
359 : /* Create a corresponding RawRasterBand. */
360 : /* -------------------------------------------------------------------- */
361 27 : m_poRawRaster =
362 54 : RawRasterBand::Create(reinterpret_cast<VSILFILE *>(fp), nImageOffset,
363 : nPixelOffset, nLineOffset, GetRasterDataType(),
364 : eByteOrder, GetXSize(), GetYSize(),
365 : RawRasterBand::OwnFP::NO)
366 27 : .release();
367 27 : if (!m_poRawRaster)
368 : {
369 0 : CPLCloseShared(fp);
370 0 : return CE_Failure;
371 : }
372 :
373 : /* -------------------------------------------------------------------- */
374 : /* Reset block size to match the raw raster. */
375 : /* -------------------------------------------------------------------- */
376 27 : m_poRawRaster->GetBlockSize(&nBlockXSize, &nBlockYSize);
377 :
378 27 : return CE_None;
379 : }
380 :
381 : /************************************************************************/
382 : /* ClearRawLink() */
383 : /************************************************************************/
384 :
385 76 : void VRTRawRasterBand::ClearRawLink()
386 :
387 : {
388 76 : if (m_poRawRaster != nullptr)
389 : {
390 27 : VSILFILE *fp = m_poRawRaster->GetFPL();
391 27 : delete m_poRawRaster;
392 27 : m_poRawRaster = nullptr;
393 : // We close the file after deleting the raster band
394 : // since data can be flushed in the destructor.
395 27 : if (fp != nullptr)
396 : {
397 27 : CPLCloseShared(reinterpret_cast<FILE *>(fp));
398 : }
399 : }
400 76 : CPLFree(m_pszSourceFilename);
401 76 : m_pszSourceFilename = nullptr;
402 76 : }
403 :
404 : /************************************************************************/
405 : /* GetVirtualMemAuto() */
406 : /************************************************************************/
407 :
408 0 : CPLVirtualMem *VRTRawRasterBand::GetVirtualMemAuto(GDALRWFlag eRWFlag,
409 : int *pnPixelSpace,
410 : GIntBig *pnLineSpace,
411 : char **papszOptions)
412 :
413 : {
414 : // check the pointer to RawRasterBand
415 0 : if (m_poRawRaster == nullptr)
416 : {
417 : // use the super class method
418 0 : return VRTRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
419 0 : pnLineSpace, papszOptions);
420 : }
421 : // if available, use the RawRasterBand method (use mmap if available)
422 0 : return m_poRawRaster->GetVirtualMemAuto(eRWFlag, pnPixelSpace, pnLineSpace,
423 0 : papszOptions);
424 : }
425 :
426 : /************************************************************************/
427 : /* XMLInit() */
428 : /************************************************************************/
429 :
430 32 : CPLErr VRTRawRasterBand::XMLInit(const CPLXMLNode *psTree,
431 : const char *pszVRTPath,
432 : VRTMapSharedResources &oMapSharedSources)
433 :
434 : {
435 : const CPLErr eErr =
436 32 : VRTRasterBand::XMLInit(psTree, pszVRTPath, oMapSharedSources);
437 32 : if (eErr != CE_None)
438 0 : return eErr;
439 :
440 : /* -------------------------------------------------------------------- */
441 : /* Validate a bit. */
442 : /* -------------------------------------------------------------------- */
443 32 : if (psTree == nullptr || psTree->eType != CXT_Element ||
444 96 : !EQUAL(psTree->pszValue, "VRTRasterBand") ||
445 32 : !EQUAL(CPLGetXMLValue(psTree, "subClass", ""), "VRTRawRasterBand"))
446 : {
447 0 : CPLError(CE_Failure, CPLE_AppDefined,
448 : "Invalid node passed to VRTRawRasterBand::XMLInit().");
449 0 : return CE_Failure;
450 : }
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* Prepare filename. */
454 : /* -------------------------------------------------------------------- */
455 32 : const char *pszFilename = CPLGetXMLValue(psTree, "SourceFilename", nullptr);
456 :
457 32 : if (pszFilename == nullptr)
458 : {
459 0 : CPLError(CE_Warning, CPLE_AppDefined,
460 : "Missing <SourceFilename> element in VRTRasterBand.");
461 0 : return CE_Failure;
462 : }
463 :
464 32 : const bool l_bRelativeToVRT = CPLTestBool(
465 : CPLGetXMLValue(psTree, "SourceFilename.relativeToVRT", "1"));
466 :
467 : /* -------------------------------------------------------------------- */
468 : /* Collect layout information. */
469 : /* -------------------------------------------------------------------- */
470 32 : int nWordDataSize = GDALGetDataTypeSizeBytes(GetRasterDataType());
471 :
472 32 : const char *pszImageOffset = CPLGetXMLValue(psTree, "ImageOffset", "0");
473 64 : const vsi_l_offset nImageOffset = CPLScanUIntBig(
474 32 : pszImageOffset, static_cast<int>(strlen(pszImageOffset)));
475 :
476 32 : int nPixelOffset = nWordDataSize;
477 32 : const char *pszPixelOffset = CPLGetXMLValue(psTree, "PixelOffset", nullptr);
478 32 : if (pszPixelOffset != nullptr)
479 : {
480 24 : nPixelOffset = atoi(pszPixelOffset);
481 : }
482 32 : if (nPixelOffset <= 0)
483 : {
484 0 : CPLError(CE_Failure, CPLE_AppDefined,
485 : "Invalid value for <PixelOffset> element : %d", nPixelOffset);
486 0 : return CE_Failure;
487 : }
488 :
489 32 : int nLineOffset = 0;
490 32 : const char *pszLineOffset = CPLGetXMLValue(psTree, "LineOffset", nullptr);
491 32 : if (pszLineOffset == nullptr)
492 : {
493 8 : if (nPixelOffset > INT_MAX / GetXSize())
494 : {
495 0 : CPLError(CE_Failure, CPLE_AppDefined, "Int overflow");
496 0 : return CE_Failure;
497 : }
498 8 : nLineOffset = nPixelOffset * GetXSize();
499 : }
500 : else
501 24 : nLineOffset = atoi(pszLineOffset);
502 :
503 32 : const char *pszByteOrder = CPLGetXMLValue(psTree, "ByteOrder", nullptr);
504 :
505 : /* -------------------------------------------------------------------- */
506 : /* Open the file, and setup the raw layer access to the data. */
507 : /* -------------------------------------------------------------------- */
508 32 : return SetRawLink(pszFilename, pszVRTPath, l_bRelativeToVRT, nImageOffset,
509 32 : nPixelOffset, nLineOffset, pszByteOrder);
510 : }
511 :
512 : /************************************************************************/
513 : /* SerializeToXML() */
514 : /************************************************************************/
515 :
516 7 : CPLXMLNode *VRTRawRasterBand::SerializeToXML(const char *pszVRTPath,
517 : bool &bHasWarnedAboutRAMUsage,
518 : size_t &nAccRAMUsage)
519 :
520 : {
521 :
522 : /* -------------------------------------------------------------------- */
523 : /* We can't set the layout if there is no open rawband. */
524 : /* -------------------------------------------------------------------- */
525 7 : if (m_poRawRaster == nullptr)
526 : {
527 0 : CPLError(CE_Failure, CPLE_AppDefined,
528 : "VRTRawRasterBand::SerializeToXML() fails because "
529 : "m_poRawRaster is NULL.");
530 0 : return nullptr;
531 : }
532 :
533 7 : CPLXMLNode *psTree = VRTRasterBand::SerializeToXML(
534 : pszVRTPath, bHasWarnedAboutRAMUsage, nAccRAMUsage);
535 :
536 : /* -------------------------------------------------------------------- */
537 : /* Set subclass. */
538 : /* -------------------------------------------------------------------- */
539 7 : CPLCreateXMLNode(CPLCreateXMLNode(psTree, CXT_Attribute, "subClass"),
540 : CXT_Text, "VRTRawRasterBand");
541 :
542 : /* -------------------------------------------------------------------- */
543 : /* Setup the filename with relative flag. */
544 : /* -------------------------------------------------------------------- */
545 14 : CPLXMLNode *psNode = CPLCreateXMLElementAndValue(psTree, "SourceFilename",
546 7 : m_pszSourceFilename);
547 :
548 7 : CPLCreateXMLNode(CPLCreateXMLNode(psNode, CXT_Attribute, "relativeToVRT"),
549 7 : CXT_Text, m_bRelativeToVRT ? "1" : "0");
550 :
551 : /* -------------------------------------------------------------------- */
552 : /* Set other layout information. */
553 : /* -------------------------------------------------------------------- */
554 :
555 7 : CPLCreateXMLElementAndValue(
556 : psTree, "ImageOffset",
557 7 : CPLSPrintf(CPL_FRMT_GUIB, m_poRawRaster->GetImgOffset()));
558 :
559 7 : CPLCreateXMLElementAndValue(
560 : psTree, "PixelOffset",
561 7 : CPLSPrintf("%d", m_poRawRaster->GetPixelOffset()));
562 :
563 7 : CPLCreateXMLElementAndValue(
564 7 : psTree, "LineOffset", CPLSPrintf("%d", m_poRawRaster->GetLineOffset()));
565 :
566 7 : switch (m_poRawRaster->GetByteOrder())
567 : {
568 3 : case RawRasterBand::ByteOrder::ORDER_LITTLE_ENDIAN:
569 3 : CPLCreateXMLElementAndValue(psTree, "ByteOrder", "LSB");
570 3 : break;
571 4 : case RawRasterBand::ByteOrder::ORDER_BIG_ENDIAN:
572 4 : CPLCreateXMLElementAndValue(psTree, "ByteOrder", "MSB");
573 4 : break;
574 0 : case RawRasterBand::ByteOrder::ORDER_VAX:
575 0 : CPLCreateXMLElementAndValue(psTree, "ByteOrder", "VAX");
576 0 : break;
577 : }
578 :
579 7 : return psTree;
580 : }
581 :
582 : /************************************************************************/
583 : /* GetFileList() */
584 : /************************************************************************/
585 :
586 3 : void VRTRawRasterBand::GetFileList(char ***ppapszFileList, int *pnSize,
587 : int *pnMaxSize, CPLHashSet *hSetFiles)
588 : {
589 3 : if (m_pszSourceFilename == nullptr)
590 1 : return;
591 :
592 : /* -------------------------------------------------------------------- */
593 : /* Is it already in the list ? */
594 : /* -------------------------------------------------------------------- */
595 3 : CPLString osSourceFilename;
596 3 : if (m_bRelativeToVRT && strlen(poDS->GetDescription()) > 0)
597 3 : osSourceFilename = CPLFormFilenameSafe(
598 6 : CPLGetDirnameSafe(poDS->GetDescription()).c_str(),
599 6 : m_pszSourceFilename, nullptr);
600 : else
601 0 : osSourceFilename = m_pszSourceFilename;
602 :
603 3 : if (CPLHashSetLookup(hSetFiles, osSourceFilename.c_str()) != nullptr)
604 1 : return;
605 :
606 : /* -------------------------------------------------------------------- */
607 : /* Grow array if necessary */
608 : /* -------------------------------------------------------------------- */
609 2 : if (*pnSize + 1 >= *pnMaxSize)
610 : {
611 2 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
612 2 : *ppapszFileList = static_cast<char **>(
613 2 : CPLRealloc(*ppapszFileList, sizeof(char *) * (*pnMaxSize)));
614 : }
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Add the string to the list */
618 : /* -------------------------------------------------------------------- */
619 2 : (*ppapszFileList)[*pnSize] = CPLStrdup(osSourceFilename);
620 2 : (*ppapszFileList)[(*pnSize + 1)] = nullptr;
621 2 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
622 :
623 2 : (*pnSize)++;
624 :
625 2 : VRTRasterBand::GetFileList(ppapszFileList, pnSize, pnMaxSize, hSetFiles);
626 : }
627 :
628 : /*! @endcond */
|