1 /******************************************************************************
2  *
3  * Project:  GDAL Core
4  * Purpose:  Implementation of GDALDriver class (and C wrappers)
5  * Author:   Frank Warmerdam, warmerdam@pobox.com
6  *
7  ******************************************************************************
8  * Copyright (c) 1998, 2000, Frank Warmerdam
9  * Copyright (c) 2007-2014, Even Rouault <even dot rouault at spatialys.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ****************************************************************************/
29 
30 #include "cpl_port.h"
31 #include "gdal.h"
32 #include "gdal_priv.h"
33 #include "gdal_rat.h"
34 
35 #include <cerrno>
36 #include <cstdlib>
37 #include <cstring>
38 #include <sys/stat.h>
39 
40 #include "cpl_conv.h"
41 #include "cpl_error.h"
42 #include "cpl_minixml.h"
43 #include "cpl_progress.h"
44 #include "cpl_string.h"
45 #include "cpl_vsi.h"
46 #include "ogr_core.h"
47 #include "ogrsf_frmts.h"
48 
49 CPL_CVSID("$Id: gdaldriver.cpp fa752ad6eabafaf630a704e1892a9d837d683cb3 2021-03-06 17:04:38 +0100 Even Rouault $")
50 
51 /************************************************************************/
52 /*                             GDALDriver()                             */
53 /************************************************************************/
54 
GDALDriver()55 GDALDriver::GDALDriver() :
56     pfnOpen(nullptr),
57     pfnCreate(nullptr),
58     pfnCreateEx(nullptr),
59     pfnCreateMultiDimensional(nullptr),
60     pfnDelete(nullptr),
61     pfnCreateCopy(nullptr),
62     pDriverData(nullptr),
63     pfnUnloadDriver(nullptr),
64     pfnIdentify(nullptr),
65     pfnIdentifyEx(nullptr),
66     pfnRename(nullptr),
67     pfnCopyFiles(nullptr),
68     pfnOpenWithDriverArg(nullptr),
69     pfnCreateVectorOnly(nullptr),
70     pfnDeleteDataSource(nullptr)
71 {}
72 
73 /************************************************************************/
74 /*                            ~GDALDriver()                             */
75 /************************************************************************/
76 
~GDALDriver()77 GDALDriver::~GDALDriver()
78 
79 {
80     if( pfnUnloadDriver != nullptr )
81         pfnUnloadDriver( this );
82 }
83 
84 /************************************************************************/
85 /*                         GDALCreateDriver()                           */
86 /************************************************************************/
87 
88 /**
89  * \brief Create a GDALDriver.
90  *
91  * Creates a driver in the GDAL heap.
92  */
93 
GDALCreateDriver()94 GDALDriverH CPL_STDCALL GDALCreateDriver()
95 {
96     return new GDALDriver();
97 }
98 
99 /************************************************************************/
100 /*                         GDALDestroyDriver()                          */
101 /************************************************************************/
102 
103 /**
104  * \brief Destroy a GDALDriver.
105  *
106  * This is roughly equivalent to deleting the driver, but is guaranteed
107  * to take place in the GDAL heap.  It is important this that function
108  * not be called on a driver that is registered with the GDALDriverManager.
109  *
110  * @param hDriver the driver to destroy.
111  */
112 
GDALDestroyDriver(GDALDriverH hDriver)113 void CPL_STDCALL GDALDestroyDriver( GDALDriverH hDriver )
114 
115 {
116     if( hDriver != nullptr )
117         delete GDALDriver::FromHandle(hDriver);
118 }
119 
120 /************************************************************************/
121 /*                               Create()                               */
122 /************************************************************************/
123 
124 /**
125  * \brief Create a new dataset with this driver.
126  *
127  * What argument values are legal for particular drivers is driver specific,
128  * and there is no way to query in advance to establish legal values.
129  *
130  * That function will try to validate the creation option list passed to the
131  * driver with the GDALValidateCreationOptions() method. This check can be
132  * disabled by defining the configuration option
133  * GDAL_VALIDATE_CREATION_OPTIONS=NO.
134  *
135  * After you have finished working with the returned dataset, it is
136  * <b>required</b> to close it with GDALClose(). This does not only close the
137  * file handle, but also ensures that all the data and metadata has been written
138  * to the dataset (GDALFlushCache() is not sufficient for that purpose).
139  *
140  * In GDAL 2, the arguments nXSize, nYSize and nBands can be passed to 0 when
141  * creating a vector-only dataset for a compatible driver.
142  *
143  * Equivalent of the C function GDALCreate().
144  *
145  * @param pszFilename the name of the dataset to create.  UTF-8 encoded.
146  * @param nXSize width of created raster in pixels.
147  * @param nYSize height of created raster in pixels.
148  * @param nBands number of bands.
149  * @param eType type of raster.
150  * @param papszOptions list of driver specific control parameters.
151  * The APPEND_SUBDATASET=YES option can be
152  * specified to avoid prior destruction of existing dataset.
153  *
154  * @return NULL on failure, or a new GDALDataset.
155  */
156 
Create(const char * pszFilename,int nXSize,int nYSize,int nBands,GDALDataType eType,char ** papszOptions)157 GDALDataset * GDALDriver::Create( const char * pszFilename,
158                                   int nXSize, int nYSize, int nBands,
159                                   GDALDataType eType, char ** papszOptions )
160 
161 {
162 /* -------------------------------------------------------------------- */
163 /*      Does this format support creation.                              */
164 /* -------------------------------------------------------------------- */
165     if( pfnCreate == nullptr && pfnCreateEx == nullptr && pfnCreateVectorOnly == nullptr )
166     {
167         CPLError( CE_Failure, CPLE_NotSupported,
168                   "GDALDriver::Create() ... no create method implemented"
169                   " for this format." );
170 
171         return nullptr;
172     }
173 /* -------------------------------------------------------------------- */
174 /*      Do some rudimentary argument checking.                          */
175 /* -------------------------------------------------------------------- */
176     if( nBands < 0 )
177     {
178         CPLError( CE_Failure, CPLE_AppDefined,
179                   "Attempt to create dataset with %d bands is illegal,"
180                   "Must be >= 0.",
181                   nBands );
182         return nullptr;
183     }
184 
185     if( GetMetadataItem(GDAL_DCAP_RASTER) != nullptr &&
186         GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr &&
187         (nXSize < 1 || nYSize < 1) )
188     {
189         CPLError( CE_Failure, CPLE_AppDefined,
190                   "Attempt to create %dx%d dataset is illegal,"
191                   "sizes must be larger than zero.",
192                   nXSize, nYSize );
193         return nullptr;
194     }
195 
196 /* -------------------------------------------------------------------- */
197 /*      Make sure we cleanup if there is an existing dataset of this    */
198 /*      name.  But even if that seems to fail we will continue since    */
199 /*      it might just be a corrupt file or something.                   */
200 /* -------------------------------------------------------------------- */
201     if( !CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false) )
202     {
203         // Someone issuing Create("foo.tif") on a
204         // memory driver doesn't expect files with those names to be deleted
205         // on a file system...
206         // This is somewhat messy. Ideally there should be a way for the
207         // driver to overload the default behavior
208         if( !EQUAL(GetDescription(), "MEM") &&
209             !EQUAL(GetDescription(), "Memory") &&
210             // ogr2ogr -f PostgreSQL might reach the Delete method of the
211             // PostgisRaster driver which is undesirable
212             !EQUAL(GetDescription(), "PostgreSQL") )
213         {
214             QuietDelete( pszFilename );
215         }
216     }
217 
218 /* -------------------------------------------------------------------- */
219 /*      Validate creation options.                                      */
220 /* -------------------------------------------------------------------- */
221     if( CPLTestBool(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS",
222                                        "YES")) )
223         GDALValidateCreationOptions( this, papszOptions );
224 
225 /* -------------------------------------------------------------------- */
226 /*      Proceed with creation.                                          */
227 /* -------------------------------------------------------------------- */
228     CPLDebug( "GDAL", "GDALDriver::Create(%s,%s,%d,%d,%d,%s,%p)",
229               GetDescription(), pszFilename, nXSize, nYSize, nBands,
230               GDALGetDataTypeName( eType ),
231               papszOptions );
232 
233     GDALDataset *poDS = nullptr;
234     if( pfnCreateEx != nullptr )
235     {
236         poDS = pfnCreateEx( this, pszFilename, nXSize, nYSize, nBands, eType,
237                           papszOptions );
238     }
239     else if( pfnCreate != nullptr )
240     {
241         poDS = pfnCreate( pszFilename, nXSize, nYSize, nBands, eType,
242                           papszOptions );
243     }
244     else if( nBands < 1 )
245     {
246         poDS = pfnCreateVectorOnly( this, pszFilename, papszOptions );
247     }
248 
249     if( poDS != nullptr )
250     {
251         if( poDS->GetDescription() == nullptr
252             || strlen(poDS->GetDescription()) == 0 )
253             poDS->SetDescription( pszFilename );
254 
255         if( poDS->poDriver == nullptr )
256             poDS->poDriver = this;
257 
258         poDS->AddToDatasetOpenList();
259     }
260 
261     return poDS;
262 }
263 
264 /************************************************************************/
265 /*                             GDALCreate()                             */
266 /************************************************************************/
267 
268 /**
269  * \brief Create a new dataset with this driver.
270  *
271  * @see GDALDriver::Create()
272  */
273 
274 GDALDatasetH CPL_DLL CPL_STDCALL
GDALCreate(GDALDriverH hDriver,const char * pszFilename,int nXSize,int nYSize,int nBands,GDALDataType eBandType,CSLConstList papszOptions)275 GDALCreate( GDALDriverH hDriver, const char * pszFilename,
276             int nXSize, int nYSize, int nBands, GDALDataType eBandType,
277             CSLConstList papszOptions )
278 
279 {
280     VALIDATE_POINTER1( hDriver, "GDALCreate", nullptr );
281 
282     return
283         GDALDriver::FromHandle(hDriver)->Create( pszFilename,
284                                                     nXSize, nYSize, nBands,
285                                                     eBandType,
286                                                     const_cast<char**>(papszOptions) );
287 }
288 
289 /************************************************************************/
290 /*                       CreateMultiDimensional()                       */
291 /************************************************************************/
292 
293 /**
294  * \brief Create a new multidimensional dataset with this driver.
295  *
296  * Only drivers that advertise the GDAL_DCAP_MULTIDIM_RASTER capability and
297  * implement the pfnCreateMultiDimensional method might return a non nullptr
298  * GDALDataset.
299  *
300  * This is the same as the C function GDALCreateMultiDimensional().
301  *
302  * @param pszFilename  the name of the dataset to create.  UTF-8 encoded.
303  * @param papszRootGroupOptions driver specific options regarding the creation
304  *                              of the root group. Might be nullptr.
305  * @param papszOptions driver specific options regarding the creation
306  *                     of the dataset. Might be nullptr.
307  * @return a new dataset, or nullptr in case of failure.
308  *
309  * @since GDAL 3.1
310  */
311 
CreateMultiDimensional(const char * pszFilename,CSLConstList papszRootGroupOptions,CSLConstList papszOptions)312 GDALDataset * GDALDriver::CreateMultiDimensional( const char * pszFilename,
313                                                   CSLConstList papszRootGroupOptions,
314                                                   CSLConstList papszOptions )
315 
316 {
317 /* -------------------------------------------------------------------- */
318 /*      Does this format support creation.                              */
319 /* -------------------------------------------------------------------- */
320     if( pfnCreateMultiDimensional== nullptr )
321     {
322         CPLError( CE_Failure, CPLE_NotSupported,
323                   "GDALDriver::CreateMultiDimensional() ... "
324                   "no CreateMultiDimensional method implemented "
325                   "for this format." );
326 
327         return nullptr;
328     }
329 
330 /* -------------------------------------------------------------------- */
331 /*      Validate creation options.                                      */
332 /* -------------------------------------------------------------------- */
333     if( CPLTestBool(
334             CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES") ) )
335     {
336         const char *pszOptionList = GetMetadataItem( GDAL_DMD_MULTIDIM_DATASET_CREATIONOPTIONLIST );
337         CPLString osDriver;
338         osDriver.Printf("driver %s", GetDescription());
339         GDALValidateOptions( pszOptionList, papszOptions,
340                             "creation option", osDriver );
341     }
342 
343     auto poDstDS = pfnCreateMultiDimensional(pszFilename,
344                                      papszRootGroupOptions,
345                                      papszOptions);
346 
347     if( poDstDS != nullptr )
348     {
349         if( poDstDS->GetDescription() == nullptr
350             || strlen(poDstDS->GetDescription()) == 0 )
351             poDstDS->SetDescription( pszFilename );
352 
353         if( poDstDS->poDriver == nullptr )
354             poDstDS->poDriver = this;
355     }
356 
357     return poDstDS;
358 }
359 
360 /************************************************************************/
361 /*                       GDALCreateMultiDimensional()                   */
362 /************************************************************************/
363 
364 /** \brief Create a new multidimensional dataset with this driver.
365  *
366  * This is the same as the C++ method GDALDriver::CreateMultiDimensional().
367  */
GDALCreateMultiDimensional(GDALDriverH hDriver,const char * pszName,CSLConstList papszRootGroupOptions,CSLConstList papszOptions)368 GDALDatasetH GDALCreateMultiDimensional( GDALDriverH hDriver,
369                                                  const char * pszName,
370                                                  CSLConstList papszRootGroupOptions,
371                                                  CSLConstList papszOptions )
372 {
373     VALIDATE_POINTER1( hDriver, __func__, nullptr );
374     VALIDATE_POINTER1( pszName, __func__, nullptr );
375     return GDALDataset::ToHandle(
376         GDALDriver::FromHandle(hDriver)->CreateMultiDimensional(
377             pszName, papszRootGroupOptions, papszOptions));
378 }
379 
380 /************************************************************************/
381 /*                  DefaultCreateCopyMultiDimensional()                 */
382 /************************************************************************/
383 
384 //! @cond Doxygen_Suppress
385 
DefaultCreateCopyMultiDimensional(GDALDataset * poSrcDS,GDALDataset * poDstDS,bool bStrict,CSLConstList papszOptions,GDALProgressFunc pfnProgress,void * pProgressData)386 CPLErr GDALDriver::DefaultCreateCopyMultiDimensional(
387                                      GDALDataset *poSrcDS,
388                                      GDALDataset *poDstDS,
389                                      bool bStrict,
390                                      CSLConstList papszOptions,
391                                      GDALProgressFunc pfnProgress,
392                                      void * pProgressData )
393 {
394     if( pfnProgress == nullptr )
395         pfnProgress = GDALDummyProgress;
396 
397     auto poSrcRG = poSrcDS->GetRootGroup();
398     if( !poSrcRG )
399         return CE_Failure;
400     auto poDstRG = poDstDS->GetRootGroup();
401     if( !poDstRG )
402         return CE_Failure;
403     GUInt64 nCurCost = 0;
404     return poDstRG->CopyFrom(poDstRG, poSrcDS, poSrcRG, bStrict,
405                              nCurCost, poSrcRG->GetTotalCopyCost(),
406                              pfnProgress, pProgressData, papszOptions) ?
407                 CE_None : CE_Failure;
408 }
409 //! @endcond
410 
411 
412 /************************************************************************/
413 /*                          DefaultCopyMasks()                          */
414 /************************************************************************/
415 
416 //! @cond Doxygen_Suppress
DefaultCopyMasks(GDALDataset * poSrcDS,GDALDataset * poDstDS,int bStrict)417 CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
418                                      GDALDataset *poDstDS,
419                                      int bStrict )
420 
421 {
422     return DefaultCopyMasks(poSrcDS, poDstDS, bStrict,
423                             nullptr, nullptr, nullptr);
424 }
425 
DefaultCopyMasks(GDALDataset * poSrcDS,GDALDataset * poDstDS,int bStrict,CSLConstList,GDALProgressFunc pfnProgress,void * pProgressData)426 CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
427                                      GDALDataset *poDstDS,
428                                      int bStrict,
429                                      CSLConstList /*papszOptions*/,
430                                      GDALProgressFunc pfnProgress,
431                                      void * pProgressData )
432 
433 {
434     if( pfnProgress == nullptr )
435         pfnProgress = GDALDummyProgress;
436 
437     int nBands = poSrcDS->GetRasterCount();
438     if (nBands == 0)
439         return CE_None;
440 
441 /* -------------------------------------------------------------------- */
442 /*      Try to copy mask if it seems appropriate.                       */
443 /* -------------------------------------------------------------------- */
444     const char* papszOptions[2] = { "COMPRESSED=YES", nullptr };
445     CPLErr eErr = CE_None;
446 
447     int nTotalBandsWithMask = 0;
448     for( int iBand = 0; iBand < nBands; ++iBand )
449     {
450         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
451 
452         int nMaskFlags = poSrcBand->GetMaskFlags();
453         if( !(nMaskFlags &
454                  (GMF_ALL_VALID|GMF_PER_DATASET|GMF_ALPHA|GMF_NODATA) ) )
455         {
456             nTotalBandsWithMask ++;
457         }
458     }
459 
460     int iBandWithMask = 0;
461     for( int iBand = 0;
462          eErr == CE_None && iBand < nBands;
463          ++iBand )
464     {
465         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
466 
467         int nMaskFlags = poSrcBand->GetMaskFlags();
468         if( eErr == CE_None
469             && !(nMaskFlags &
470                  (GMF_ALL_VALID|GMF_PER_DATASET|GMF_ALPHA|GMF_NODATA) ) )
471         {
472             GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
473             if (poDstBand != nullptr)
474             {
475                 eErr = poDstBand->CreateMaskBand( nMaskFlags );
476                 if( eErr == CE_None )
477                 {
478                     // coverity[divide_by_zero]
479                     void* pScaledData = GDALCreateScaledProgress(
480                         double(iBandWithMask) / nTotalBandsWithMask,
481                         double(iBandWithMask + 1) / nTotalBandsWithMask,
482                         pfnProgress, pProgressData );
483                     eErr = GDALRasterBandCopyWholeRaster(
484                         poSrcBand->GetMaskBand(),
485                         poDstBand->GetMaskBand(),
486                         papszOptions,
487                         GDALScaledProgress, pScaledData);
488                     GDALDestroyScaledProgress(pScaledData);
489                 }
490                 else if( !bStrict )
491                 {
492                     eErr = CE_None;
493                 }
494             }
495         }
496     }
497 
498 /* -------------------------------------------------------------------- */
499 /*      Try to copy a per-dataset mask if we have one.                  */
500 /* -------------------------------------------------------------------- */
501     const int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
502     if( eErr == CE_None
503         && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
504         && (nMaskFlags & GMF_PER_DATASET) )
505     {
506         eErr = poDstDS->CreateMaskBand( nMaskFlags );
507         if( eErr == CE_None )
508         {
509             eErr = GDALRasterBandCopyWholeRaster(
510                 poSrcDS->GetRasterBand(1)->GetMaskBand(),
511                 poDstDS->GetRasterBand(1)->GetMaskBand(),
512                 papszOptions,
513                 pfnProgress, pProgressData);
514         }
515         else if( !bStrict )
516         {
517             eErr = CE_None;
518         }
519     }
520 
521     return eErr;
522 }
523 
524 /************************************************************************/
525 /*                         DefaultCreateCopy()                          */
526 /************************************************************************/
527 
DefaultCreateCopy(const char * pszFilename,GDALDataset * poSrcDS,int bStrict,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressData)528 GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
529                                             GDALDataset * poSrcDS,
530                                             int bStrict, char ** papszOptions,
531                                             GDALProgressFunc pfnProgress,
532                                             void * pProgressData )
533 
534 {
535     if( pfnProgress == nullptr )
536         pfnProgress = GDALDummyProgress;
537 
538     CPLErrorReset();
539 
540 /* -------------------------------------------------------------------- */
541 /*      Use multidimensional raster API if available.                   */
542 /* -------------------------------------------------------------------- */
543     auto poSrcGroup = poSrcDS->GetRootGroup();
544     if( poSrcGroup != nullptr && GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) )
545     {
546         CPLStringList aosDatasetCO;
547         for( CSLConstList papszIter = papszOptions; papszIter && *papszIter; ++papszIter )
548         {
549             if( !STARTS_WITH_CI(*papszIter, "ARRAY:") )
550                 aosDatasetCO.AddString(*papszIter);
551         }
552         auto poDstDS = std::unique_ptr<GDALDataset>(
553             CreateMultiDimensional(pszFilename,
554                                    nullptr,
555                                    aosDatasetCO.List()));
556         if( !poDstDS )
557             return nullptr;
558         auto poDstGroup = poDstDS->GetRootGroup();
559         if( !poDstGroup )
560             return nullptr;
561         if( DefaultCreateCopyMultiDimensional(poSrcDS,
562                                               poDstDS.get(),
563                                               CPL_TO_BOOL(bStrict),
564                                               papszOptions,
565                                               pfnProgress,
566                                               pProgressData) != CE_None )
567             return nullptr;
568         return poDstDS.release();
569     }
570 
571 /* -------------------------------------------------------------------- */
572 /*      Validate that we can create the output as requested.            */
573 /* -------------------------------------------------------------------- */
574     const int nXSize = poSrcDS->GetRasterXSize();
575     const int nYSize = poSrcDS->GetRasterYSize();
576     const int nBands = poSrcDS->GetRasterCount();
577 
578     CPLDebug( "GDAL", "Using default GDALDriver::CreateCopy implementation." );
579 
580     const int nLayerCount = poSrcDS->GetLayerCount();
581     if( nBands == 0 && nLayerCount == 0 &&
582         GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr )
583     {
584         CPLError( CE_Failure, CPLE_NotSupported,
585                   "GDALDriver::DefaultCreateCopy does not support zero band" );
586         return nullptr;
587     }
588     if( poSrcDS->GetDriver() != nullptr &&
589         poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_RASTER) != nullptr &&
590         poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr &&
591         GetMetadataItem(GDAL_DCAP_RASTER) == nullptr &&
592         GetMetadataItem(GDAL_DCAP_VECTOR) != nullptr )
593     {
594         CPLError( CE_Failure, CPLE_NotSupported,
595                   "Source driver is raster-only whereas output driver is "
596                   "vector-only" );
597         return nullptr;
598     }
599     else if( poSrcDS->GetDriver() != nullptr &&
600         poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr &&
601         poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_VECTOR) != nullptr &&
602         GetMetadataItem(GDAL_DCAP_RASTER) != nullptr &&
603         GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr )
604     {
605         CPLError( CE_Failure, CPLE_NotSupported,
606                   "Source driver is vector-only whereas output driver is "
607                   "raster-only" );
608         return nullptr;
609     }
610 
611     if( !pfnProgress( 0.0, nullptr, pProgressData ) )
612     {
613         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
614         return nullptr;
615     }
616 
617 /* -------------------------------------------------------------------- */
618 /*      Propagate some specific structural metadata as options if it    */
619 /*      appears to be supported by the target driver and the caller     */
620 /*      didn't provide values.                                          */
621 /* -------------------------------------------------------------------- */
622     char **papszCreateOptions = CSLDuplicate( papszOptions );
623     const char * const apszOptItems[] = {
624         "NBITS", "IMAGE_STRUCTURE",
625         "PIXELTYPE", "IMAGE_STRUCTURE",
626         nullptr };
627 
628     for( int iOptItem = 0;
629          nBands > 0 && apszOptItems[iOptItem] != nullptr;
630          iOptItem += 2 )
631     {
632         // does the source have this metadata item on the first band?
633         const char *pszValue =
634             poSrcDS->GetRasterBand(1)->GetMetadataItem(
635                 apszOptItems[iOptItem], apszOptItems[iOptItem+1] );
636 
637         if( pszValue == nullptr )
638             continue;
639 
640         // Do not override provided value.
641         if( CSLFetchNameValue( papszCreateOptions, pszValue ) != nullptr )
642             continue;
643 
644         // Does this appear to be a supported creation option on this driver?
645         const char *pszOptionList =
646             GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
647 
648         if( pszOptionList == nullptr
649             || strstr(pszOptionList,apszOptItems[iOptItem]) == nullptr )
650             continue;
651 
652         papszCreateOptions = CSLSetNameValue( papszCreateOptions,
653                                               apszOptItems[iOptItem],
654                                               pszValue );
655     }
656 
657 /* -------------------------------------------------------------------- */
658 /*      Create destination dataset.                                     */
659 /* -------------------------------------------------------------------- */
660     GDALDataType eType = GDT_Unknown;
661 
662     if( nBands > 0 )
663         eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
664     GDALDataset  *poDstDS = Create( pszFilename, nXSize, nYSize,
665                                     nBands, eType, papszCreateOptions );
666 
667     CSLDestroy(papszCreateOptions);
668 
669     if( poDstDS == nullptr )
670         return nullptr;
671 
672     int nDstBands = poDstDS->GetRasterCount();
673     CPLErr eErr = CE_None;
674     if( nDstBands != nBands )
675     {
676         if( GetMetadataItem(GDAL_DCAP_RASTER) != nullptr )
677         {
678             // Should not happen for a well-behaved driver.
679             CPLError(
680                 CE_Failure, CPLE_AppDefined,
681                 "Output driver created only %d bands whereas %d were expected",
682                 nDstBands, nBands );
683             eErr = CE_Failure;
684         }
685         nDstBands = 0;
686     }
687 
688 /* -------------------------------------------------------------------- */
689 /*      Try setting the projection and geotransform if it seems         */
690 /*      suitable.                                                       */
691 /* -------------------------------------------------------------------- */
692     double adfGeoTransform[6] = {};
693 
694     if( nDstBands == 0 && !bStrict )
695         CPLPushErrorHandler(CPLQuietErrorHandler);
696 
697     if( eErr == CE_None
698         && poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
699         // TODO(schwehr): The default value check should be a function.
700         && (adfGeoTransform[0] != 0.0
701             || adfGeoTransform[1] != 1.0
702             || adfGeoTransform[2] != 0.0
703             || adfGeoTransform[3] != 0.0
704             || adfGeoTransform[4] != 0.0
705             || adfGeoTransform[5] != 1.0) )
706     {
707         eErr = poDstDS->SetGeoTransform( adfGeoTransform );
708         if( !bStrict )
709             eErr = CE_None;
710     }
711 
712     if( eErr == CE_None
713         && poSrcDS->GetProjectionRef() != nullptr
714         && strlen(poSrcDS->GetProjectionRef()) > 0 )
715     {
716         eErr = poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
717         if( !bStrict )
718             eErr = CE_None;
719     }
720 
721 /* -------------------------------------------------------------------- */
722 /*      Copy GCPs.                                                      */
723 /* -------------------------------------------------------------------- */
724     if( poSrcDS->GetGCPCount() > 0 && eErr == CE_None )
725     {
726         eErr = poDstDS->SetGCPs( poSrcDS->GetGCPCount(),
727                                  poSrcDS->GetGCPs(),
728                                  poSrcDS->GetGCPProjection() );
729         if( !bStrict )
730             eErr = CE_None;
731     }
732 
733     if( nDstBands == 0 && !bStrict )
734         CPLPopErrorHandler();
735 
736 /* -------------------------------------------------------------------- */
737 /*      Copy metadata.                                                  */
738 /* -------------------------------------------------------------------- */
739     if( poSrcDS->GetMetadata() != nullptr )
740         poDstDS->SetMetadata( poSrcDS->GetMetadata() );
741 
742 /* -------------------------------------------------------------------- */
743 /*      Copy transportable special domain metadata (RPCs).  It would    */
744 /*      be nice to copy geolocation, but it is pretty fragile.          */
745 /* -------------------------------------------------------------------- */
746     char **papszMD = poSrcDS->GetMetadata( "RPC" );
747     if( papszMD )
748         poDstDS->SetMetadata( papszMD, "RPC" );
749 
750 /* -------------------------------------------------------------------- */
751 /*      Copy XMPmetadata.                                               */
752 /* -------------------------------------------------------------------- */
753     char** papszXMP = poSrcDS->GetMetadata("xml:XMP");
754     if (papszXMP != nullptr && *papszXMP != nullptr)
755     {
756         poDstDS->SetMetadata(papszXMP, "xml:XMP");
757     }
758 
759 /* -------------------------------------------------------------------- */
760 /*      Loop copying bands.                                             */
761 /* -------------------------------------------------------------------- */
762     for( int iBand = 0;
763          eErr == CE_None && iBand < nDstBands;
764          ++iBand )
765     {
766         GDALRasterBand * const poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
767         GDALRasterBand * const poDstBand = poDstDS->GetRasterBand( iBand+1 );
768 
769 /* -------------------------------------------------------------------- */
770 /*      Do we need to copy a colortable.                                */
771 /* -------------------------------------------------------------------- */
772         GDALColorTable * const poCT = poSrcBand->GetColorTable();
773         if( poCT != nullptr )
774             poDstBand->SetColorTable( poCT );
775 
776 /* -------------------------------------------------------------------- */
777 /*      Do we need to copy other metadata?  Most of this is             */
778 /*      non-critical, so lets not bother folks if it fails are we       */
779 /*      are not in strict mode.                                         */
780 /* -------------------------------------------------------------------- */
781         if( !bStrict )
782             CPLPushErrorHandler( CPLQuietErrorHandler );
783 
784         if( strlen(poSrcBand->GetDescription()) > 0 )
785             poDstBand->SetDescription( poSrcBand->GetDescription() );
786 
787         if( CSLCount(poSrcBand->GetMetadata()) > 0 )
788             poDstBand->SetMetadata( poSrcBand->GetMetadata() );
789 
790         int bSuccess = FALSE;
791         double dfValue = poSrcBand->GetOffset( &bSuccess );
792         if( bSuccess && dfValue != 0.0 )
793             poDstBand->SetOffset( dfValue );
794 
795         dfValue = poSrcBand->GetScale( &bSuccess );
796         if( bSuccess && dfValue != 1.0 )
797             poDstBand->SetScale( dfValue );
798 
799         dfValue = poSrcBand->GetNoDataValue( &bSuccess );
800         if( bSuccess )
801             poDstBand->SetNoDataValue( dfValue );
802 
803         if( poSrcBand->GetColorInterpretation() != GCI_Undefined
804             && poSrcBand->GetColorInterpretation()
805             != poDstBand->GetColorInterpretation() )
806             poDstBand->SetColorInterpretation(
807                 poSrcBand->GetColorInterpretation() );
808 
809         char** papszCatNames = poSrcBand->GetCategoryNames();
810         if (nullptr != papszCatNames)
811             poDstBand->SetCategoryNames( papszCatNames );
812 
813         // Only copy RAT if it is of reasonable size to fit in memory
814         GDALRasterAttributeTable* poRAT = poSrcBand->GetDefaultRAT();
815         if( poRAT != nullptr &&
816             static_cast<GIntBig>(poRAT->GetColumnCount()) *
817                 poRAT->GetRowCount() < 1024 * 1024 )
818         {
819             poDstBand->SetDefaultRAT(poRAT);
820         }
821 
822         if( !bStrict )
823         {
824             CPLPopErrorHandler();
825             CPLErrorReset();
826         }
827         else
828         {
829             eErr = CPLGetLastErrorType();
830         }
831     }
832 
833 /* -------------------------------------------------------------------- */
834 /*      Copy image data.                                                */
835 /* -------------------------------------------------------------------- */
836     if( eErr == CE_None && nDstBands > 0 )
837         eErr = GDALDatasetCopyWholeRaster( poSrcDS, poDstDS,
838                                            nullptr, pfnProgress, pProgressData );
839 
840 /* -------------------------------------------------------------------- */
841 /*      Should we copy some masks over?                                 */
842 /* -------------------------------------------------------------------- */
843     if( eErr == CE_None && nDstBands > 0 )
844         eErr = DefaultCopyMasks( poSrcDS, poDstDS, eErr );
845 
846 /* -------------------------------------------------------------------- */
847 /*      Copy vector layers                                              */
848 /* -------------------------------------------------------------------- */
849     if( eErr == CE_None )
850     {
851         if( nLayerCount > 0 && poDstDS->TestCapability(ODsCCreateLayer) )
852         {
853             for( int iLayer = 0; iLayer < nLayerCount; ++iLayer )
854             {
855                 OGRLayer *poLayer = poSrcDS->GetLayer(iLayer);
856 
857                 if( poLayer == nullptr )
858                     continue;
859 
860                 poDstDS->CopyLayer( poLayer, poLayer->GetName(), nullptr );
861             }
862         }
863     }
864 
865 /* -------------------------------------------------------------------- */
866 /*      Try to cleanup the output dataset if the translation failed.    */
867 /* -------------------------------------------------------------------- */
868     if( eErr != CE_None )
869     {
870         delete poDstDS;
871         if( !CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false) )
872         {
873             // Only delete if creating a new file
874             Delete( pszFilename );
875         }
876         return nullptr;
877     }
878     else
879     {
880         CPLErrorReset();
881     }
882 
883     return poDstDS;
884 }
885 //! @endcond
886 
887 /************************************************************************/
888 /*                             CreateCopy()                             */
889 /************************************************************************/
890 
891 /**
892  * \brief Create a copy of a dataset.
893  *
894  * This method will attempt to create a copy of a raster dataset with the
895  * indicated filename, and in this drivers format.  Band number, size,
896  * type, projection, geotransform and so forth are all to be copied from
897  * the provided template dataset.
898  *
899  * Note that many sequential write once formats (such as JPEG and PNG) don't
900  * implement the Create() method but do implement this CreateCopy() method.
901  * If the driver doesn't implement CreateCopy(), but does implement Create()
902  * then the default CreateCopy() mechanism built on calling Create() will
903  * be used.
904  * So to test if CreateCopy() is available, you can test if GDAL_DCAP_CREATECOPY
905  * or GDAL_DCAP_CREATE is set in the GDAL metadata.
906  *
907  * It is intended that CreateCopy() will often be used with a source dataset
908  * which is a virtual dataset allowing configuration of band types, and other
909  * information without actually duplicating raster data (see the VRT driver).
910  * This is what is done by the gdal_translate utility for example.
911  *
912  * That function will try to validate the creation option list passed to the
913  * driver with the GDALValidateCreationOptions() method. This check can be
914  * disabled by defining the configuration option
915  * GDAL_VALIDATE_CREATION_OPTIONS=NO.
916  *
917  * After you have finished working with the returned dataset, it is
918  * <b>required</b> to close it with GDALClose(). This does not only close the
919  * file handle, but also ensures that all the data and metadata has been written
920  * to the dataset (GDALFlushCache() is not sufficient for that purpose).
921  *
922  * For multidimensional datasets, papszOptions can contain array creation options,
923  * if they are prefixed with "ARRAY:". \see GDALGroup::CopyFrom() documentation
924  * for further details regarding such options.
925  *
926  * @param pszFilename the name for the new dataset.  UTF-8 encoded.
927  * @param poSrcDS the dataset being duplicated.
928  * @param bStrict TRUE if the copy must be strictly equivalent, or more
929  * normally FALSE indicating that the copy may adapt as needed for the
930  * output format.
931  * @param papszOptions additional format dependent options controlling
932  * creation of the output file. The APPEND_SUBDATASET=YES option can be
933  * specified to avoid prior destruction of existing dataset.
934  * @param pfnProgress a function to be used to report progress of the copy.
935  * @param pProgressData application data passed into progress function.
936  *
937  * @return a pointer to the newly created dataset (may be read-only access).
938  */
939 
CreateCopy(const char * pszFilename,GDALDataset * poSrcDS,int bStrict,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressData)940 GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
941                                      GDALDataset * poSrcDS,
942                                      int bStrict, char ** papszOptions,
943                                      GDALProgressFunc pfnProgress,
944                                      void * pProgressData )
945 
946 {
947     if( pfnProgress == nullptr )
948         pfnProgress = GDALDummyProgress;
949 
950 /* -------------------------------------------------------------------- */
951 /*      Make sure we cleanup if there is an existing dataset of this    */
952 /*      name.  But even if that seems to fail we will continue since    */
953 /*      it might just be a corrupt file or something.                   */
954 /* -------------------------------------------------------------------- */
955     const bool bAppendSubdataset =
956         CPLFetchBool(const_cast<const char **>(papszOptions),
957                      "APPEND_SUBDATASET", false);
958     if( !bAppendSubdataset &&
959         CPLFetchBool(const_cast<const char **>(papszOptions),
960                      "QUIET_DELETE_ON_CREATE_COPY", true) )
961     {
962         // Someone issuing CreateCopy("foo.tif") on a
963         // memory driver doesn't expect files with those names to be deleted
964         // on a file system...
965         // This is somewhat messy. Ideally there should be a way for the
966         // driver to overload the default behavior
967         if( !EQUAL(GetDescription(), "MEM") &&
968             !EQUAL(GetDescription(), "Memory") )
969         {
970             QuietDelete( pszFilename );
971         }
972     }
973 
974     char** papszOptionsToDelete = nullptr;
975     int iIdxQuietDeleteOnCreateCopy =
976         CSLPartialFindString(papszOptions, "QUIET_DELETE_ON_CREATE_COPY=");
977     if( iIdxQuietDeleteOnCreateCopy >= 0 )
978     {
979         //if( papszOptionsToDelete == nullptr )
980             papszOptionsToDelete = CSLDuplicate(papszOptions);
981         papszOptions =
982             CSLRemoveStrings(papszOptionsToDelete, iIdxQuietDeleteOnCreateCopy,
983                              1, nullptr);
984         papszOptionsToDelete = papszOptions;
985     }
986 
987 /* -------------------------------------------------------------------- */
988 /*      If _INTERNAL_DATASET=YES, the returned dataset will not be      */
989 /*      registered in the global list of open datasets.                 */
990 /* -------------------------------------------------------------------- */
991     const int iIdxInternalDataset =
992         CSLPartialFindString(papszOptions, "_INTERNAL_DATASET=");
993     bool bInternalDataset = false;
994     if( iIdxInternalDataset >= 0 )
995     {
996         bInternalDataset =
997             CPLFetchBool(const_cast<const char **>(papszOptions),
998                          "_INTERNAL_DATASET", false);
999         if( papszOptionsToDelete == nullptr )
1000             papszOptionsToDelete = CSLDuplicate(papszOptions);
1001         papszOptions =
1002             CSLRemoveStrings(papszOptionsToDelete, iIdxInternalDataset,
1003                              1, nullptr);
1004         papszOptionsToDelete = papszOptions;
1005     }
1006 
1007 /* -------------------------------------------------------------------- */
1008 /*      Validate creation options.                                      */
1009 /* -------------------------------------------------------------------- */
1010     if( CPLTestBool(
1011             CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES") ) )
1012     {
1013         auto poSrcGroup = poSrcDS->GetRootGroup();
1014         if( poSrcGroup != nullptr && GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER) )
1015         {
1016             CPLStringList aosDatasetCO;
1017             for( CSLConstList papszIter = papszOptions; papszIter && *papszIter; ++papszIter )
1018             {
1019                 if( !STARTS_WITH_CI(*papszIter, "ARRAY:") )
1020                     aosDatasetCO.AddString(*papszIter);
1021             }
1022             GDALValidateCreationOptions( this, aosDatasetCO.List() );
1023         }
1024         else
1025         {
1026             GDALValidateCreationOptions( this, papszOptions );
1027         }
1028     }
1029 
1030 /* -------------------------------------------------------------------- */
1031 /*      Advise the source raster that we are going to read it completely */
1032 /* -------------------------------------------------------------------- */
1033 
1034     const int nXSize = poSrcDS->GetRasterXSize();
1035     const int nYSize = poSrcDS->GetRasterYSize();
1036     const int nBandCount = poSrcDS->GetRasterCount();
1037     GDALDataType eDT = GDT_Unknown;
1038     if( nBandCount > 0 )
1039     {
1040         GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(1);
1041         if( poSrcBand )
1042             eDT = poSrcBand->GetRasterDataType();
1043     }
1044     poSrcDS->AdviseRead( 0, 0, nXSize, nYSize, nXSize, nYSize, eDT,
1045                          nBandCount, nullptr, nullptr );
1046 
1047 /* -------------------------------------------------------------------- */
1048 /*      If the format provides a CreateCopy() method use that,          */
1049 /*      otherwise fallback to the internal implementation using the     */
1050 /*      Create() method.                                                */
1051 /* -------------------------------------------------------------------- */
1052     GDALDataset *poDstDS = nullptr;
1053     if( pfnCreateCopy != nullptr &&
1054         !CPLTestBool(CPLGetConfigOption("GDAL_DEFAULT_CREATE_COPY", "NO")) )
1055     {
1056         poDstDS = pfnCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
1057                                  pfnProgress, pProgressData );
1058         if( poDstDS != nullptr )
1059         {
1060             if( poDstDS->GetDescription() == nullptr
1061                 || strlen(poDstDS->GetDescription()) == 0 )
1062                 poDstDS->SetDescription( pszFilename );
1063 
1064             if( poDstDS->poDriver == nullptr )
1065                 poDstDS->poDriver = this;
1066 
1067             if( !bInternalDataset )
1068                 poDstDS->AddToDatasetOpenList();
1069         }
1070     }
1071     else
1072     {
1073         poDstDS = DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
1074                                   papszOptions, pfnProgress, pProgressData );
1075     }
1076 
1077     CSLDestroy(papszOptionsToDelete);
1078     return poDstDS;
1079 }
1080 
1081 /************************************************************************/
1082 /*                           GDALCreateCopy()                           */
1083 /************************************************************************/
1084 
1085 /**
1086  * \brief Create a copy of a dataset.
1087  *
1088  * @see GDALDriver::CreateCopy()
1089  */
1090 
GDALCreateCopy(GDALDriverH hDriver,const char * pszFilename,GDALDatasetH hSrcDS,int bStrict,CSLConstList papszOptions,GDALProgressFunc pfnProgress,void * pProgressData)1091 GDALDatasetH CPL_STDCALL GDALCreateCopy( GDALDriverH hDriver,
1092                                          const char * pszFilename,
1093                                          GDALDatasetH hSrcDS,
1094                                          int bStrict, CSLConstList papszOptions,
1095                                          GDALProgressFunc pfnProgress,
1096                                          void * pProgressData )
1097 
1098 {
1099     VALIDATE_POINTER1( hDriver, "GDALCreateCopy", nullptr );
1100     VALIDATE_POINTER1( hSrcDS, "GDALCreateCopy", nullptr );
1101 
1102     return GDALDriver::FromHandle(hDriver)->
1103         CreateCopy( pszFilename, GDALDataset::FromHandle(hSrcDS),
1104                     bStrict, const_cast<char**>(papszOptions),
1105                     pfnProgress, pProgressData );
1106 }
1107 
1108 /************************************************************************/
1109 /*                            QuietDelete()                             */
1110 /************************************************************************/
1111 
1112 /**
1113  * \brief Delete dataset if found.
1114  *
1115  * This is a helper method primarily used by Create() and
1116  * CreateCopy() to predelete any dataset of the name soon to be
1117  * created.  It will attempt to delete the named dataset if
1118  * one is found, otherwise it does nothing.  An error is only
1119  * returned if the dataset is found but the delete fails.
1120  *
1121  * This is a static method and it doesn't matter what driver instance
1122  * it is invoked on.  It will attempt to discover the correct driver
1123  * using Identify().
1124  *
1125  * @param pszName the dataset name to try and delete.
1126  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
1127  * terminated list of strings with the driver short names that must be
1128  * considered. (Note: functionality currently broken. Argument considered as NULL)
1129  * @return CE_None if the dataset does not exist, or is deleted without issues.
1130  */
1131 
QuietDelete(const char * pszName,const char * const * papszAllowedDrivers)1132 CPLErr GDALDriver::QuietDelete( const char *pszName,
1133                                 const char *const *papszAllowedDrivers )
1134 
1135 {
1136     // FIXME! GDALIdentifyDriver() accepts a file list, not a driver list
1137     CPL_IGNORE_RET_VAL(papszAllowedDrivers);
1138 
1139     VSIStatBufL sStat;
1140     const bool bExists =
1141         VSIStatExL(pszName, &sStat,
1142                    VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0;
1143 
1144 #ifdef S_ISFIFO
1145     if( bExists && S_ISFIFO(sStat.st_mode) )
1146         return CE_None;
1147 #endif
1148 
1149     if( bExists &&
1150         VSI_ISDIR(sStat.st_mode) )
1151     {
1152         // It is not desirable to remove directories quietly.  Necessary to
1153         // avoid ogr_mitab_12 to destroy file created at ogr_mitab_7.
1154         return CE_None;
1155     }
1156 
1157     CPLPushErrorHandler(CPLQuietErrorHandler);
1158     GDALDriver * const poDriver =
1159         GDALDriver::FromHandle( GDALIdentifyDriver( pszName, nullptr ) );
1160     CPLPopErrorHandler();
1161 
1162     if( poDriver == nullptr )
1163         return CE_None;
1164 
1165     CPLDebug( "GDAL", "QuietDelete(%s) invoking Delete()", pszName );
1166 
1167     const bool bQuiet =
1168         !bExists && poDriver->pfnDelete == nullptr &&
1169         poDriver->pfnDeleteDataSource == nullptr;
1170     if( bQuiet )
1171         CPLPushErrorHandler(CPLQuietErrorHandler);
1172     CPLErr eErr = poDriver->Delete( pszName );
1173     if( bQuiet )
1174     {
1175         CPLPopErrorHandler();
1176         CPLErrorReset();
1177         eErr = CE_None;
1178     }
1179     return eErr;
1180 }
1181 
1182 /************************************************************************/
1183 /*                               Delete()                               */
1184 /************************************************************************/
1185 
1186 /**
1187  * \brief Delete named dataset.
1188  *
1189  * The driver will attempt to delete the named dataset in a driver specific
1190  * fashion.  Full featured drivers will delete all associated files,
1191  * database objects, or whatever is appropriate.  The default behavior when
1192  * no driver specific behavior is provided is to attempt to delete all the
1193  * files that are returned by GDALGetFileList() on the dataset handle.
1194  *
1195  * It is unwise to have open dataset handles on this dataset when it is
1196  * deleted.
1197  *
1198  * Equivalent of the C function GDALDeleteDataset().
1199  *
1200  * @param pszFilename name of dataset to delete.
1201  *
1202  * @return CE_None on success, or CE_Failure if the operation fails.
1203  */
1204 
Delete(const char * pszFilename)1205 CPLErr GDALDriver::Delete( const char * pszFilename )
1206 
1207 {
1208     if( pfnDelete != nullptr )
1209         return pfnDelete( pszFilename );
1210     else if( pfnDeleteDataSource != nullptr )
1211         return pfnDeleteDataSource( this, pszFilename );
1212 
1213 /* -------------------------------------------------------------------- */
1214 /*      Collect file list.                                              */
1215 /* -------------------------------------------------------------------- */
1216     GDALDatasetH hDS = GDALOpenEx(pszFilename, 0, nullptr, nullptr, nullptr);
1217 
1218     if( hDS == nullptr )
1219     {
1220         if( CPLGetLastErrorNo() == 0 )
1221             CPLError( CE_Failure, CPLE_OpenFailed,
1222                       "Unable to open %s to obtain file list.", pszFilename );
1223 
1224         return CE_Failure;
1225     }
1226 
1227     char **papszFileList = GDALGetFileList( hDS );
1228 
1229     GDALClose( hDS );
1230     hDS = nullptr;
1231 
1232     if( CSLCount( papszFileList ) == 0 )
1233     {
1234         CPLError( CE_Failure, CPLE_NotSupported,
1235                   "Unable to determine files associated with %s, "
1236                   "delete fails.", pszFilename );
1237         CSLDestroy( papszFileList );
1238         return CE_Failure;
1239     }
1240 
1241 /* -------------------------------------------------------------------- */
1242 /*      Delete all files.                                               */
1243 /* -------------------------------------------------------------------- */
1244     CPLErr eErr = CE_None;
1245     for( int i = 0; papszFileList[i] != nullptr; ++i )
1246     {
1247         if( VSIUnlink( papszFileList[i] ) != 0 )
1248         {
1249             CPLError( CE_Failure, CPLE_AppDefined,
1250                       "Deleting %s failed:\n%s",
1251                       papszFileList[i],
1252                       VSIStrerror(errno) );
1253             eErr = CE_Failure;
1254         }
1255     }
1256 
1257     CSLDestroy( papszFileList );
1258 
1259     return eErr;
1260 }
1261 
1262 /************************************************************************/
1263 /*                         GDALDeleteDataset()                          */
1264 /************************************************************************/
1265 
1266 /**
1267  * \brief Delete named dataset.
1268  *
1269  * @see GDALDriver::Delete()
1270  */
1271 
GDALDeleteDataset(GDALDriverH hDriver,const char * pszFilename)1272 CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver,
1273                                       const char * pszFilename )
1274 
1275 {
1276     if( hDriver == nullptr )
1277         hDriver = GDALIdentifyDriver( pszFilename, nullptr );
1278 
1279     if( hDriver == nullptr )
1280     {
1281         CPLError( CE_Failure, CPLE_AppDefined,
1282                   "No identifiable driver for %s.",
1283                   pszFilename );
1284         return CE_Failure;
1285     }
1286 
1287     return GDALDriver::FromHandle(hDriver)->Delete( pszFilename );
1288 }
1289 
1290 /************************************************************************/
1291 /*                           DefaultRename()                            */
1292 /*                                                                      */
1293 /*      The generic implementation based on the file list used when     */
1294 /*      there is no format specific implementation.                     */
1295 /************************************************************************/
1296 
1297 //! @cond Doxygen_Suppress
DefaultRename(const char * pszNewName,const char * pszOldName)1298 CPLErr GDALDriver::DefaultRename( const char * pszNewName,
1299                                   const char *pszOldName )
1300 
1301 {
1302 /* -------------------------------------------------------------------- */
1303 /*      Collect file list.                                              */
1304 /* -------------------------------------------------------------------- */
1305     GDALDatasetH hDS = GDALOpen(pszOldName, GA_ReadOnly);
1306 
1307     if( hDS == nullptr )
1308     {
1309         if( CPLGetLastErrorNo() == 0 )
1310             CPLError( CE_Failure, CPLE_OpenFailed,
1311                       "Unable to open %s to obtain file list.", pszOldName );
1312 
1313         return CE_Failure;
1314     }
1315 
1316     char **papszFileList = GDALGetFileList( hDS );
1317 
1318     GDALClose( hDS );
1319 
1320     if( CSLCount( papszFileList ) == 0 )
1321     {
1322         CPLError( CE_Failure, CPLE_NotSupported,
1323                   "Unable to determine files associated with %s,\n"
1324                   "rename fails.", pszOldName );
1325 
1326         return CE_Failure;
1327     }
1328 
1329 /* -------------------------------------------------------------------- */
1330 /*      Produce a list of new filenames that correspond to the old      */
1331 /*      names.                                                          */
1332 /* -------------------------------------------------------------------- */
1333     CPLErr eErr = CE_None;
1334     char **papszNewFileList =
1335         CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
1336 
1337     if( papszNewFileList == nullptr )
1338         return CE_Failure;
1339 
1340     for( int i = 0; papszFileList[i] != nullptr; ++i )
1341     {
1342         if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
1343         {
1344             eErr = CE_Failure;
1345             // Try to put the ones we moved back.
1346             for( --i; i >= 0; i-- )
1347                 CPLMoveFile( papszFileList[i], papszNewFileList[i] );
1348             break;
1349         }
1350     }
1351 
1352     CSLDestroy( papszNewFileList );
1353     CSLDestroy( papszFileList );
1354 
1355     return eErr;
1356 }
1357 //! @endcond
1358 
1359 /************************************************************************/
1360 /*                               Rename()                               */
1361 /************************************************************************/
1362 
1363 /**
1364  * \brief Rename a dataset.
1365  *
1366  * Rename a dataset. This may including moving the dataset to a new directory
1367  * or even a new filesystem.
1368  *
1369  * It is unwise to have open dataset handles on this dataset when it is
1370  * being renamed.
1371  *
1372  * Equivalent of the C function GDALRenameDataset().
1373  *
1374  * @param pszNewName new name for the dataset.
1375  * @param pszOldName old name for the dataset.
1376  *
1377  * @return CE_None on success, or CE_Failure if the operation fails.
1378  */
1379 
Rename(const char * pszNewName,const char * pszOldName)1380 CPLErr GDALDriver::Rename( const char * pszNewName, const char *pszOldName )
1381 
1382 {
1383     if( pfnRename != nullptr )
1384         return pfnRename( pszNewName, pszOldName );
1385 
1386     return DefaultRename( pszNewName, pszOldName );
1387 }
1388 
1389 /************************************************************************/
1390 /*                         GDALRenameDataset()                          */
1391 /************************************************************************/
1392 
1393 /**
1394  * \brief Rename a dataset.
1395  *
1396  * @see GDALDriver::Rename()
1397  */
1398 
GDALRenameDataset(GDALDriverH hDriver,const char * pszNewName,const char * pszOldName)1399 CPLErr CPL_STDCALL GDALRenameDataset( GDALDriverH hDriver,
1400                                       const char * pszNewName,
1401                                       const char * pszOldName )
1402 
1403 {
1404     if( hDriver == nullptr )
1405         hDriver = GDALIdentifyDriver( pszOldName, nullptr );
1406 
1407     if( hDriver == nullptr )
1408     {
1409         CPLError( CE_Failure, CPLE_AppDefined,
1410                   "No identifiable driver for %s.",
1411                   pszOldName );
1412         return CE_Failure;
1413     }
1414 
1415     return GDALDriver::FromHandle(hDriver)->Rename( pszNewName, pszOldName );
1416 }
1417 
1418 /************************************************************************/
1419 /*                          DefaultCopyFiles()                          */
1420 /*                                                                      */
1421 /*      The default implementation based on file lists used when        */
1422 /*      there is no format specific implementation.                     */
1423 /************************************************************************/
1424 
1425 //! @cond Doxygen_Suppress
DefaultCopyFiles(const char * pszNewName,const char * pszOldName)1426 CPLErr GDALDriver::DefaultCopyFiles( const char *pszNewName,
1427                                      const char *pszOldName )
1428 
1429 {
1430 /* -------------------------------------------------------------------- */
1431 /*      Collect file list.                                              */
1432 /* -------------------------------------------------------------------- */
1433     GDALDatasetH hDS = GDALOpen(pszOldName,GA_ReadOnly);
1434 
1435     if( hDS == nullptr )
1436     {
1437         if( CPLGetLastErrorNo() == 0 )
1438             CPLError( CE_Failure, CPLE_OpenFailed,
1439                       "Unable to open %s to obtain file list.", pszOldName );
1440 
1441         return CE_Failure;
1442     }
1443 
1444     char **papszFileList = GDALGetFileList( hDS );
1445 
1446     GDALClose( hDS );
1447     hDS = nullptr;
1448 
1449     if( CSLCount( papszFileList ) == 0 )
1450     {
1451         CPLError( CE_Failure, CPLE_NotSupported,
1452                   "Unable to determine files associated with %s,\n"
1453                   "rename fails.", pszOldName );
1454 
1455         return CE_Failure;
1456     }
1457 
1458 /* -------------------------------------------------------------------- */
1459 /*      Produce a list of new filenames that correspond to the old      */
1460 /*      names.                                                          */
1461 /* -------------------------------------------------------------------- */
1462     CPLErr eErr = CE_None;
1463     char **papszNewFileList =
1464         CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
1465 
1466     if( papszNewFileList == nullptr )
1467         return CE_Failure;
1468 
1469     for( int i = 0; papszFileList[i] != nullptr; ++i )
1470     {
1471         if( CPLCopyFile( papszNewFileList[i], papszFileList[i] ) != 0 )
1472         {
1473             eErr = CE_Failure;
1474             // Try to put the ones we moved back.
1475             for( --i; i >= 0; --i )
1476                 VSIUnlink( papszNewFileList[i] );
1477             break;
1478         }
1479     }
1480 
1481     CSLDestroy( papszNewFileList );
1482     CSLDestroy( papszFileList );
1483 
1484     return eErr;
1485 }
1486 //! @endcond
1487 
1488 /************************************************************************/
1489 /*                             CopyFiles()                              */
1490 /************************************************************************/
1491 
1492 /**
1493  * \brief Copy the files of a dataset.
1494  *
1495  * Copy all the files associated with a dataset.
1496  *
1497  * Equivalent of the C function GDALCopyDatasetFiles().
1498  *
1499  * @param pszNewName new name for the dataset.
1500  * @param pszOldName old name for the dataset.
1501  *
1502  * @return CE_None on success, or CE_Failure if the operation fails.
1503  */
1504 
CopyFiles(const char * pszNewName,const char * pszOldName)1505 CPLErr GDALDriver::CopyFiles( const char *pszNewName, const char *pszOldName )
1506 
1507 {
1508     if( pfnCopyFiles != nullptr )
1509         return pfnCopyFiles( pszNewName, pszOldName );
1510 
1511     return DefaultCopyFiles( pszNewName, pszOldName );
1512 }
1513 
1514 /************************************************************************/
1515 /*                        GDALCopyDatasetFiles()                        */
1516 /************************************************************************/
1517 
1518 /**
1519  * \brief Copy the files of a dataset.
1520  *
1521  * @see GDALDriver::CopyFiles()
1522  */
1523 
GDALCopyDatasetFiles(GDALDriverH hDriver,const char * pszNewName,const char * pszOldName)1524 CPLErr CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH hDriver,
1525                                          const char *pszNewName,
1526                                          const char *pszOldName )
1527 
1528 {
1529     if( hDriver == nullptr )
1530         hDriver = GDALIdentifyDriver( pszOldName, nullptr );
1531 
1532     if( hDriver == nullptr )
1533     {
1534         CPLError( CE_Failure, CPLE_AppDefined,
1535                   "No identifiable driver for %s.",
1536                   pszOldName );
1537         return CE_Failure;
1538     }
1539 
1540     return GDALDriver::FromHandle(hDriver)->
1541         CopyFiles( pszNewName, pszOldName );
1542 }
1543 
1544 /************************************************************************/
1545 /*                       GDALGetDriverShortName()                       */
1546 /************************************************************************/
1547 
1548 /**
1549  * \brief Return the short name of a driver
1550  *
1551  * This is the string that can be
1552  * passed to the GDALGetDriverByName() function.
1553  *
1554  * For the GeoTIFF driver, this is "GTiff"
1555  *
1556  * @param hDriver the handle of the driver
1557  * @return the short name of the driver. The
1558  *         returned string should not be freed and is owned by the driver.
1559  */
1560 
GDALGetDriverShortName(GDALDriverH hDriver)1561 const char * CPL_STDCALL GDALGetDriverShortName( GDALDriverH hDriver )
1562 
1563 {
1564     VALIDATE_POINTER1( hDriver, "GDALGetDriverShortName", nullptr );
1565 
1566     return GDALDriver::FromHandle(hDriver)->GetDescription();
1567 }
1568 
1569 /************************************************************************/
1570 /*                       GDALGetDriverLongName()                        */
1571 /************************************************************************/
1572 
1573 /**
1574  * \brief Return the long name of a driver
1575  *
1576  * For the GeoTIFF driver, this is "GeoTIFF"
1577  *
1578  * @param hDriver the handle of the driver
1579  * @return the long name of the driver or empty string. The
1580  *         returned string should not be freed and is owned by the driver.
1581  */
1582 
GDALGetDriverLongName(GDALDriverH hDriver)1583 const char * CPL_STDCALL GDALGetDriverLongName( GDALDriverH hDriver )
1584 
1585 {
1586     VALIDATE_POINTER1( hDriver, "GDALGetDriverLongName", nullptr );
1587 
1588     const char *pszLongName =
1589         GDALDriver::FromHandle(hDriver)->
1590             GetMetadataItem( GDAL_DMD_LONGNAME );
1591 
1592     if( pszLongName == nullptr )
1593         return "";
1594 
1595     return pszLongName;
1596 }
1597 
1598 /************************************************************************/
1599 /*                       GDALGetDriverHelpTopic()                       */
1600 /************************************************************************/
1601 
1602 /**
1603  * \brief Return the URL to the help that describes the driver
1604  *
1605  * That URL is relative to the GDAL documentation directory.
1606  *
1607  * For the GeoTIFF driver, this is "frmt_gtiff.html"
1608  *
1609  * @param hDriver the handle of the driver
1610  * @return the URL to the help that describes the driver or NULL. The
1611  *         returned string should not be freed and is owned by the driver.
1612  */
1613 
GDALGetDriverHelpTopic(GDALDriverH hDriver)1614 const char * CPL_STDCALL GDALGetDriverHelpTopic( GDALDriverH hDriver )
1615 
1616 {
1617     VALIDATE_POINTER1( hDriver, "GDALGetDriverHelpTopic", nullptr );
1618 
1619     return GDALDriver::FromHandle(hDriver)->
1620         GetMetadataItem( GDAL_DMD_HELPTOPIC );
1621 }
1622 
1623 /************************************************************************/
1624 /*                   GDALGetDriverCreationOptionList()                  */
1625 /************************************************************************/
1626 
1627 /**
1628  * \brief Return the list of creation options of the driver
1629  *
1630  * Return the list of creation options of the driver used by Create() and
1631  * CreateCopy() as an XML string
1632  *
1633  * @param hDriver the handle of the driver
1634  * @return an XML string that describes the list of creation options or
1635  *         empty string. The returned string should not be freed and is
1636  *         owned by the driver.
1637  */
1638 
GDALGetDriverCreationOptionList(GDALDriverH hDriver)1639 const char * CPL_STDCALL GDALGetDriverCreationOptionList( GDALDriverH hDriver )
1640 
1641 {
1642     VALIDATE_POINTER1( hDriver, "GDALGetDriverCreationOptionList", nullptr );
1643 
1644     const char *pszOptionList =
1645         GDALDriver::FromHandle(hDriver)->
1646             GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
1647 
1648     if( pszOptionList == nullptr )
1649         return "";
1650 
1651     return pszOptionList;
1652 }
1653 
1654 /************************************************************************/
1655 /*                   GDALValidateCreationOptions()                      */
1656 /************************************************************************/
1657 
1658 /**
1659  * \brief Validate the list of creation options that are handled by a driver
1660  *
1661  * This is a helper method primarily used by Create() and
1662  * CreateCopy() to validate that the passed in list of creation options
1663  * is compatible with the GDAL_DMD_CREATIONOPTIONLIST metadata item defined
1664  * by some drivers. @see GDALGetDriverCreationOptionList()
1665  *
1666  * If the GDAL_DMD_CREATIONOPTIONLIST metadata item is not defined, this
1667  * function will return TRUE. Otherwise it will check that the keys and values
1668  * in the list of creation options are compatible with the capabilities declared
1669  * by the GDAL_DMD_CREATIONOPTIONLIST metadata item. In case of incompatibility
1670  * a (non fatal) warning will be emitted and FALSE will be returned.
1671  *
1672  * @param hDriver the handle of the driver with whom the lists of creation option
1673  *                must be validated
1674  * @param papszCreationOptions the list of creation options. An array of strings,
1675  *                             whose last element is a NULL pointer
1676  * @return TRUE if the list of creation options is compatible with the Create()
1677  *         and CreateCopy() method of the driver, FALSE otherwise.
1678  */
1679 
GDALValidateCreationOptions(GDALDriverH hDriver,CSLConstList papszCreationOptions)1680 int CPL_STDCALL GDALValidateCreationOptions( GDALDriverH hDriver,
1681                                              CSLConstList papszCreationOptions )
1682 {
1683     VALIDATE_POINTER1( hDriver, "GDALValidateCreationOptions", FALSE );
1684     const char *pszOptionList =
1685         GDALDriver::FromHandle(hDriver)->GetMetadataItem(
1686             GDAL_DMD_CREATIONOPTIONLIST );
1687     CPLString osDriver;
1688     osDriver.Printf("driver %s",
1689                     GDALDriver::FromHandle(hDriver)->GetDescription());
1690     CSLConstList papszOptionsToValidate = papszCreationOptions;
1691     char** papszOptionsToFree = nullptr;
1692     if( CSLFetchNameValue( papszCreationOptions, "APPEND_SUBDATASET") )
1693     {
1694         papszOptionsToFree =
1695             CSLSetNameValue(CSLDuplicate(papszCreationOptions),
1696                             "APPEND_SUBDATASET", nullptr);
1697         papszOptionsToValidate = papszOptionsToFree;
1698     }
1699     const bool bRet = CPL_TO_BOOL(
1700         GDALValidateOptions(
1701             pszOptionList,
1702             papszOptionsToValidate,
1703             "creation option",
1704             osDriver ) );
1705     CSLDestroy(papszOptionsToFree);
1706     return bRet;
1707 }
1708 
1709 /************************************************************************/
1710 /*                     GDALValidateOpenOptions()                        */
1711 /************************************************************************/
1712 
GDALValidateOpenOptions(GDALDriverH hDriver,const char * const * papszOpenOptions)1713 int GDALValidateOpenOptions( GDALDriverH hDriver,
1714                              const char* const* papszOpenOptions)
1715 {
1716     VALIDATE_POINTER1( hDriver, "GDALValidateOpenOptions", FALSE );
1717     const char *pszOptionList = GDALDriver::FromHandle(hDriver)->
1718         GetMetadataItem( GDAL_DMD_OPENOPTIONLIST );
1719     CPLString osDriver;
1720     osDriver.Printf("driver %s",
1721                     GDALDriver::FromHandle(hDriver)->GetDescription());
1722     return GDALValidateOptions( pszOptionList, papszOpenOptions,
1723                                 "open option",
1724                                 osDriver );
1725 }
1726 
1727 /************************************************************************/
1728 /*                           GDALValidateOptions()                      */
1729 /************************************************************************/
1730 
GDALValidateOptions(const char * pszOptionList,const char * const * papszOptionsToValidate,const char * pszErrorMessageOptionType,const char * pszErrorMessageContainerName)1731 int GDALValidateOptions( const char* pszOptionList,
1732                          const char* const* papszOptionsToValidate,
1733                          const char* pszErrorMessageOptionType,
1734                          const char* pszErrorMessageContainerName)
1735 {
1736     if( papszOptionsToValidate == nullptr || *papszOptionsToValidate == nullptr)
1737         return TRUE;
1738     if( pszOptionList == nullptr )
1739         return TRUE;
1740 
1741     CPLXMLNode* psNode = CPLParseXMLString(pszOptionList);
1742     if (psNode == nullptr)
1743     {
1744         CPLError(CE_Warning, CPLE_AppDefined,
1745                  "Could not parse %s list of %s. Assuming options are valid.",
1746                  pszErrorMessageOptionType, pszErrorMessageContainerName);
1747         return TRUE;
1748     }
1749 
1750     bool bRet = true;
1751     while(*papszOptionsToValidate)
1752     {
1753         char* pszKey = nullptr;
1754         const char* pszValue = CPLParseNameValue(*papszOptionsToValidate, &pszKey);
1755         if (pszKey == nullptr)
1756         {
1757             CPLError(CE_Warning, CPLE_NotSupported,
1758                      "%s '%s' is not formatted with the key=value format",
1759                      pszErrorMessageOptionType,
1760                      *papszOptionsToValidate);
1761             bRet = false;
1762 
1763             ++papszOptionsToValidate;
1764             continue;
1765         }
1766 
1767         if( EQUAL(pszKey, "VALIDATE_OPEN_OPTIONS") )
1768         {
1769             ++papszOptionsToValidate;
1770             CPLFree(pszKey);
1771             continue;
1772         }
1773 
1774         // Must we be forgiving in case of missing option ?
1775         bool bWarnIfMissingKey = true;
1776         if( pszKey[0] == '@' )
1777         {
1778             bWarnIfMissingKey = false;
1779             memmove(pszKey, pszKey + 1, strlen(pszKey+1)+1);
1780         }
1781 
1782         CPLXMLNode* psChildNode = psNode->psChild;
1783         while(psChildNode)
1784         {
1785             if (EQUAL(psChildNode->pszValue, "OPTION"))
1786             {
1787                 const char* pszOptionName = CPLGetXMLValue(psChildNode, "name", "");
1788                 /* For option names terminated by wildcard (NITF BLOCKA option names for example) */
1789                 if (strlen(pszOptionName) > 0 &&
1790                     pszOptionName[strlen(pszOptionName) - 1] == '*' &&
1791                     EQUALN(pszOptionName, pszKey, strlen(pszOptionName) - 1))
1792                 {
1793                     break;
1794                 }
1795 
1796                 /* For option names beginning by a wildcard */
1797                 if( pszOptionName[0] == '*' &&
1798                     strlen(pszKey) > strlen(pszOptionName) &&
1799                     EQUAL( pszKey + strlen(pszKey) - strlen(pszOptionName + 1), pszOptionName + 1 ) )
1800                 {
1801                     break;
1802                 }
1803 
1804                 if (EQUAL(pszOptionName, pszKey) )
1805                 {
1806                     break;
1807                 }
1808                 const char* pszAlias = CPLGetXMLValue(psChildNode, "alias",
1809                             CPLGetXMLValue(psChildNode, "deprecated_alias", ""));
1810                 if (EQUAL(pszAlias, pszKey) )
1811                 {
1812                     CPLDebug("GDAL", "Using deprecated alias '%s'. New name is '%s'",
1813                              pszAlias, pszOptionName);
1814                     break;
1815                 }
1816             }
1817             psChildNode = psChildNode->psNext;
1818         }
1819         if (psChildNode == nullptr)
1820         {
1821             if( bWarnIfMissingKey &&
1822                 (!EQUAL(pszErrorMessageOptionType, "open option") ||
1823                  CPLFetchBool(papszOptionsToValidate,
1824                               "VALIDATE_OPEN_OPTIONS", true)) )
1825             {
1826                 CPLError(CE_Warning, CPLE_NotSupported,
1827                         "%s does not support %s %s",
1828                         pszErrorMessageContainerName,
1829                         pszErrorMessageOptionType,
1830                         pszKey);
1831                 bRet = false;
1832             }
1833 
1834             CPLFree(pszKey);
1835             ++papszOptionsToValidate;
1836             continue;
1837         }
1838 
1839 #ifdef DEBUG
1840         CPLXMLNode* psChildSubNode = psChildNode->psChild;
1841         while(psChildSubNode)
1842         {
1843             if( psChildSubNode->eType == CXT_Attribute )
1844             {
1845                 if( !(EQUAL(psChildSubNode->pszValue, "name") ||
1846                       EQUAL(psChildSubNode->pszValue, "alias") ||
1847                       EQUAL(psChildSubNode->pszValue, "deprecated_alias") ||
1848                       EQUAL(psChildSubNode->pszValue, "alt_config_option") ||
1849                       EQUAL(psChildSubNode->pszValue, "description") ||
1850                       EQUAL(psChildSubNode->pszValue, "type") ||
1851                       EQUAL(psChildSubNode->pszValue, "min") ||
1852                       EQUAL(psChildSubNode->pszValue, "max") ||
1853                       EQUAL(psChildSubNode->pszValue, "default") ||
1854                       EQUAL(psChildSubNode->pszValue, "maxsize") ||
1855                       EQUAL(psChildSubNode->pszValue, "required") ||
1856                       EQUAL(psChildSubNode->pszValue, "scope")) )
1857                 {
1858                     /* Driver error */
1859                     CPLError(CE_Warning, CPLE_NotSupported,
1860                              "%s : unhandled attribute '%s' for %s %s.",
1861                              pszErrorMessageContainerName,
1862                              psChildSubNode->pszValue,
1863                              pszKey,
1864                              pszErrorMessageOptionType);
1865                 }
1866             }
1867             psChildSubNode = psChildSubNode->psNext;
1868         }
1869 #endif
1870 
1871         const char* pszType = CPLGetXMLValue(psChildNode, "type", nullptr);
1872         const char* pszMin = CPLGetXMLValue(psChildNode, "min", nullptr);
1873         const char* pszMax = CPLGetXMLValue(psChildNode, "max", nullptr);
1874         if (pszType != nullptr)
1875         {
1876             if (EQUAL(pszType, "INT") || EQUAL(pszType, "INTEGER"))
1877             {
1878                 const char* pszValueIter = pszValue;
1879                 while (*pszValueIter)
1880                 {
1881                     if (!((*pszValueIter >= '0' && *pszValueIter <= '9') ||
1882                            *pszValueIter == '+' || *pszValueIter == '-'))
1883                     {
1884                         CPLError(CE_Warning, CPLE_NotSupported,
1885                              "'%s' is an unexpected value for %s %s of type int.",
1886                              pszValue, pszKey, pszErrorMessageOptionType);
1887                         bRet = false;
1888                         break;
1889                     }
1890                     ++pszValueIter;
1891                 }
1892                 if( *pszValueIter == '\0' )
1893                 {
1894                     if( pszMin && atoi(pszValue) < atoi(pszMin) )
1895                     {
1896                         CPLError(CE_Warning, CPLE_NotSupported,
1897                              "'%s' is an unexpected value for %s %s that should be >= %s.",
1898                              pszValue, pszKey, pszErrorMessageOptionType, pszMin);
1899                         bRet = false;
1900                     }
1901                     if( pszMax && atoi(pszValue) > atoi(pszMax) )
1902                     {
1903                         CPLError(CE_Warning, CPLE_NotSupported,
1904                              "'%s' is an unexpected value for %s %s that should be <= %s.",
1905                              pszValue, pszKey, pszErrorMessageOptionType, pszMax);
1906                         bRet = false;
1907                     }
1908                 }
1909             }
1910             else if (EQUAL(pszType, "UNSIGNED INT"))
1911             {
1912                 const char* pszValueIter = pszValue;
1913                 while (*pszValueIter)
1914                 {
1915                     if (!((*pszValueIter >= '0' && *pszValueIter <= '9') ||
1916                            *pszValueIter == '+'))
1917                     {
1918                         CPLError(CE_Warning, CPLE_NotSupported,
1919                              "'%s' is an unexpected value for %s %s of type unsigned int.",
1920                              pszValue, pszKey, pszErrorMessageOptionType);
1921                         bRet = false;
1922                         break;
1923                     }
1924                     ++pszValueIter;
1925                 }
1926                 if( *pszValueIter == '\0' )
1927                 {
1928                     if( pszMin && atoi(pszValue) < atoi(pszMin) )
1929                     {
1930                         CPLError(CE_Warning, CPLE_NotSupported,
1931                             "'%s' is an unexpected value for %s %s that should be >= %s.",
1932                             pszValue, pszKey, pszErrorMessageOptionType, pszMin);
1933                         bRet = false;
1934                     }
1935                     if( pszMax && atoi(pszValue) > atoi(pszMax) )
1936                     {
1937                         CPLError(CE_Warning, CPLE_NotSupported,
1938                             "'%s' is an unexpected value for %s %s that should be <= %s.",
1939                             pszValue, pszKey, pszErrorMessageOptionType, pszMax);
1940                         bRet = false;
1941                     }
1942                 }
1943             }
1944             else if (EQUAL(pszType, "FLOAT"))
1945             {
1946                 char* endPtr = nullptr;
1947                 double dfVal = CPLStrtod(pszValue, &endPtr);
1948                 if ( !(endPtr == nullptr || *endPtr == '\0') )
1949                 {
1950                     CPLError(CE_Warning, CPLE_NotSupported,
1951                              "'%s' is an unexpected value for %s %s of type float.",
1952                              pszValue, pszKey, pszErrorMessageOptionType);
1953                     bRet = false;
1954                 }
1955                 else
1956                 {
1957                     if( pszMin && dfVal < CPLAtof(pszMin) )
1958                     {
1959                         CPLError(CE_Warning, CPLE_NotSupported,
1960                              "'%s' is an unexpected value for %s %s that should be >= %s.",
1961                              pszValue, pszKey, pszErrorMessageOptionType, pszMin);
1962                         bRet = false;
1963                     }
1964                     if( pszMax && dfVal > CPLAtof(pszMax) )
1965                     {
1966                         CPLError(CE_Warning, CPLE_NotSupported,
1967                              "'%s' is an unexpected value for %s %s that should be <= %s.",
1968                              pszValue, pszKey, pszErrorMessageOptionType, pszMax);
1969                         bRet = false;
1970                     }
1971                 }
1972             }
1973             else if (EQUAL(pszType, "BOOLEAN"))
1974             {
1975                 if (!(EQUAL(pszValue, "ON") || EQUAL(pszValue, "TRUE") || EQUAL(pszValue, "YES") ||
1976                       EQUAL(pszValue, "OFF") || EQUAL(pszValue, "FALSE") || EQUAL(pszValue, "NO")))
1977                 {
1978                     CPLError(CE_Warning, CPLE_NotSupported,
1979                              "'%s' is an unexpected value for %s %s of type boolean.",
1980                              pszValue, pszKey, pszErrorMessageOptionType);
1981                     bRet = false;
1982                 }
1983             }
1984             else if (EQUAL(pszType, "STRING-SELECT"))
1985             {
1986                 bool bMatchFound = false;
1987                 CPLXMLNode* psStringSelect = psChildNode->psChild;
1988                 while(psStringSelect)
1989                 {
1990                     if (psStringSelect->eType == CXT_Element &&
1991                         EQUAL(psStringSelect->pszValue, "Value"))
1992                     {
1993                         CPLXMLNode* psOptionNode = psStringSelect->psChild;
1994                         while(psOptionNode)
1995                         {
1996                             if (psOptionNode->eType == CXT_Text &&
1997                                 EQUAL(psOptionNode->pszValue, pszValue))
1998                             {
1999                                 bMatchFound = true;
2000                                 break;
2001                             }
2002                             if( psOptionNode->eType == CXT_Attribute &&
2003                                 (EQUAL(psOptionNode->pszValue, "alias") ||
2004                                  EQUAL(psOptionNode->pszValue, "deprecated_alias") ) &&
2005                                  EQUAL(psOptionNode->psChild->pszValue, pszValue) )
2006                             {
2007                                 bMatchFound = true;
2008                                 break;
2009                             }
2010                             psOptionNode = psOptionNode->psNext;
2011                         }
2012                         if (bMatchFound)
2013                             break;
2014                     }
2015                     psStringSelect = psStringSelect->psNext;
2016                 }
2017                 if (!bMatchFound)
2018                 {
2019                     CPLError(CE_Warning, CPLE_NotSupported,
2020                              "'%s' is an unexpected value for %s %s of type string-select.",
2021                              pszValue, pszKey, pszErrorMessageOptionType);
2022                     bRet = false;
2023                 }
2024             }
2025             else if (EQUAL(pszType, "STRING"))
2026             {
2027                 const char* pszMaxSize = CPLGetXMLValue(psChildNode, "maxsize", nullptr);
2028                 if (pszMaxSize != nullptr)
2029                 {
2030                     if (static_cast<int>(strlen(pszValue)) > atoi(pszMaxSize))
2031                     {
2032                         CPLError(CE_Warning, CPLE_NotSupported,
2033                              "'%s' is of size %d, whereas maximum size for %s %s is %d.",
2034                              pszValue, static_cast<int>(strlen(pszValue)), pszKey,
2035                                  pszErrorMessageOptionType, atoi(pszMaxSize));
2036                         bRet = false;
2037                     }
2038                 }
2039             }
2040             else
2041             {
2042                 /* Driver error */
2043                 CPLError(CE_Warning, CPLE_NotSupported,
2044                          "%s : type '%s' for %s %s is not recognized.",
2045                          pszErrorMessageContainerName,
2046                          pszType,
2047                          pszKey,
2048                          pszErrorMessageOptionType);
2049             }
2050         }
2051         else
2052         {
2053             /* Driver error */
2054             CPLError(CE_Warning, CPLE_NotSupported,
2055                      "%s : no type for %s %s.",
2056                      pszErrorMessageContainerName,
2057                      pszKey,
2058                      pszErrorMessageOptionType);
2059         }
2060         CPLFree(pszKey);
2061         ++papszOptionsToValidate;
2062     }
2063 
2064     CPLDestroyXMLNode(psNode);
2065     return bRet ? TRUE : FALSE;
2066 }
2067 
2068 /************************************************************************/
2069 /*                         GDALIdentifyDriver()                         */
2070 /************************************************************************/
2071 
2072 /**
2073  * \brief Identify the driver that can open a raster file.
2074  *
2075  * This function will try to identify the driver that can open the passed file
2076  * name by invoking the Identify method of each registered GDALDriver in turn.
2077  * The first driver that successful identifies the file name will be returned.
2078  * If all drivers fail then NULL is returned.
2079  *
2080  * In order to reduce the need for such searches touch the operating system
2081  * file system machinery, it is possible to give an optional list of files.
2082  * This is the list of all files at the same level in the file system as the
2083  * target file, including the target file. The filenames will not include any
2084  * path components, are essentially just the output of VSIReadDir() on the
2085  * parent directory. If the target object does not have filesystem semantics
2086  * then the file list should be NULL.
2087  *
2088  * @param pszFilename the name of the file to access.  In the case of
2089  * exotic drivers this may not refer to a physical file, but instead contain
2090  * information for the driver on how to access a dataset.
2091  *
2092  * @param papszFileList an array of strings, whose last element is the NULL
2093  * pointer.  These strings are filenames that are auxiliary to the main
2094  * filename. The passed value may be NULL.
2095  *
2096  * @return A GDALDriverH handle or NULL on failure.  For C++ applications
2097  * this handle can be cast to a GDALDriver *.
2098  */
2099 
2100 GDALDriverH CPL_STDCALL
GDALIdentifyDriver(const char * pszFilename,CSLConstList papszFileList)2101 GDALIdentifyDriver( const char * pszFilename,
2102                     CSLConstList papszFileList )
2103 
2104 {
2105     return GDALIdentifyDriverEx( pszFilename, 0, nullptr, papszFileList );
2106 }
2107 
2108 /************************************************************************/
2109 /*                         GDALIdentifyDriverEx()                       */
2110 /************************************************************************/
2111 
2112 /**
2113  * \brief Identify the driver that can open a raster file.
2114  *
2115  * This function will try to identify the driver that can open the passed file
2116  * name by invoking the Identify method of each registered GDALDriver in turn.
2117  * The first driver that successful identifies the file name will be returned.
2118  * If all drivers fail then NULL is returned.
2119  *
2120  * In order to reduce the need for such searches touch the operating system
2121  * file system machinery, it is possible to give an optional list of files.
2122  * This is the list of all files at the same level in the file system as the
2123  * target file, including the target file. The filenames will not include any
2124  * path components, are essentially just the output of VSIReadDir() on the
2125  * parent directory. If the target object does not have filesystem semantics
2126  * then the file list should be NULL.
2127  *
2128  * @param pszFilename the name of the file to access.  In the case of
2129  * exotic drivers this may not refer to a physical file, but instead contain
2130  * information for the driver on how to access a dataset.
2131  *
2132  * @param nIdentifyFlags a combination of GDAL_OF_RASTER for raster drivers
2133  * or GDAL_OF_VECTOR for vector drivers. If none of the value is specified,
2134  * both kinds are implied.
2135  *
2136  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
2137  * terminated list of strings with the driver short names that must be considered.
2138  *
2139  * @param papszFileList an array of strings, whose last element is the NULL
2140  * pointer.  These strings are filenames that are auxiliary to the main
2141  * filename. The passed value may be NULL.
2142  *
2143  * @return A GDALDriverH handle or NULL on failure.  For C++ applications
2144  * this handle can be cast to a GDALDriver *.
2145  *
2146  * @since GDAL 2.2
2147  */
2148 
2149 GDALDriverH CPL_STDCALL
GDALIdentifyDriverEx(const char * pszFilename,unsigned int nIdentifyFlags,const char * const * papszAllowedDrivers,const char * const * papszFileList)2150 GDALIdentifyDriverEx( const char* pszFilename,
2151                       unsigned int nIdentifyFlags,
2152                       const char* const* papszAllowedDrivers,
2153                       const char* const* papszFileList )
2154 {
2155     GDALDriverManager  *poDM = GetGDALDriverManager();
2156     CPLAssert( nullptr != poDM );
2157     GDALOpenInfo oOpenInfo( pszFilename, GA_ReadOnly, papszFileList );
2158 
2159     CPLErrorReset();
2160 
2161     const int nDriverCount = poDM->GetDriverCount();
2162 
2163     // First pass: only use drivers that have a pfnIdentify implementation.
2164     for( int iDriver = 0; iDriver < nDriverCount; ++iDriver )
2165     {
2166         GDALDriver* poDriver = poDM->GetDriver( iDriver );
2167         if (papszAllowedDrivers != nullptr &&
2168             CSLFindString(papszAllowedDrivers,
2169                             GDALGetDriverShortName(poDriver)) == -1)
2170         {
2171             continue;
2172         }
2173 
2174         VALIDATE_POINTER1( poDriver, "GDALIdentifyDriver", nullptr );
2175 
2176         if( poDriver->pfnIdentify == nullptr && poDriver->pfnIdentifyEx == nullptr)
2177         {
2178             continue;
2179         }
2180 
2181         if (papszAllowedDrivers != nullptr &&
2182             CSLFindString(papszAllowedDrivers,
2183                           GDALGetDriverShortName(poDriver)) == -1)
2184             continue;
2185         if( (nIdentifyFlags & GDAL_OF_RASTER) != 0 &&
2186             (nIdentifyFlags & GDAL_OF_VECTOR) == 0 &&
2187             poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr )
2188             continue;
2189         if( (nIdentifyFlags & GDAL_OF_VECTOR) != 0 &&
2190             (nIdentifyFlags & GDAL_OF_RASTER) == 0 &&
2191             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr )
2192             continue;
2193 
2194         if( poDriver->pfnIdentifyEx )
2195         {
2196             if( poDriver->pfnIdentifyEx( poDriver, &oOpenInfo ) > 0 )
2197                 return poDriver;
2198         }
2199         else
2200         {
2201             if( poDriver->pfnIdentify( &oOpenInfo ) > 0 )
2202                 return poDriver;
2203         }
2204     }
2205 
2206     // Second pass: slow method.
2207     for( int iDriver = 0; iDriver < nDriverCount; ++iDriver )
2208     {
2209         GDALDriver* poDriver = poDM->GetDriver( iDriver );
2210         if (papszAllowedDrivers != nullptr &&
2211             CSLFindString(papszAllowedDrivers,
2212                             GDALGetDriverShortName(poDriver)) == -1)
2213         {
2214                 continue;
2215         }
2216 
2217         VALIDATE_POINTER1( poDriver, "GDALIdentifyDriver", nullptr );
2218 
2219         if( (nIdentifyFlags & GDAL_OF_RASTER) != 0 &&
2220             (nIdentifyFlags & GDAL_OF_VECTOR) == 0 &&
2221             poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr )
2222             continue;
2223         if( (nIdentifyFlags & GDAL_OF_VECTOR) != 0 &&
2224             (nIdentifyFlags & GDAL_OF_RASTER) == 0 &&
2225             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr )
2226             continue;
2227 
2228         if( poDriver->pfnIdentifyEx != nullptr )
2229         {
2230             if( poDriver->pfnIdentifyEx( poDriver, &oOpenInfo ) == 0 )
2231                 continue;
2232         }
2233         else if( poDriver->pfnIdentify != nullptr )
2234         {
2235             if( poDriver->pfnIdentify( &oOpenInfo ) == 0 )
2236                 continue;
2237         }
2238 
2239         GDALDataset     *poDS;
2240         if( poDriver->pfnOpen != nullptr )
2241         {
2242             poDS = poDriver->pfnOpen( &oOpenInfo );
2243             if( poDS != nullptr )
2244             {
2245                 delete poDS;
2246                 return GDALDriver::ToHandle(poDriver);
2247             }
2248 
2249             if( CPLGetLastErrorNo() != 0 )
2250                 return nullptr;
2251         }
2252         else if( poDriver->pfnOpenWithDriverArg != nullptr )
2253         {
2254             poDS = poDriver->pfnOpenWithDriverArg( poDriver, &oOpenInfo );
2255             if( poDS != nullptr )
2256             {
2257                 delete poDS;
2258                 return GDALDriver::ToHandle(poDriver);
2259             }
2260 
2261             if( CPLGetLastErrorNo() != 0 )
2262                 return nullptr;
2263         }
2264     }
2265 
2266     return nullptr;
2267 }
2268 
2269 /************************************************************************/
2270 /*                          SetMetadataItem()                           */
2271 /************************************************************************/
2272 
SetMetadataItem(const char * pszName,const char * pszValue,const char * pszDomain)2273 CPLErr GDALDriver::SetMetadataItem( const char *pszName,
2274                                     const char *pszValue,
2275                                     const char *pszDomain )
2276 
2277 {
2278     if( pszDomain == nullptr || pszDomain[0] == '\0' )
2279     {
2280         /* Automatically sets GDAL_DMD_EXTENSIONS from GDAL_DMD_EXTENSION */
2281         if( EQUAL(pszName, GDAL_DMD_EXTENSION) &&
2282             GDALMajorObject::GetMetadataItem(GDAL_DMD_EXTENSIONS) == nullptr )
2283         {
2284             GDALMajorObject::SetMetadataItem(GDAL_DMD_EXTENSIONS, pszValue);
2285         }
2286     }
2287     return GDALMajorObject::SetMetadataItem(pszName, pszValue, pszDomain);
2288 }
2289