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