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