Coverage Report

Created: 2026-05-16 08:20

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