LCOV - code coverage report
Current view: top level - gcore - gdaldriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 925 1062 87.1 %
Date: 2024-05-04 12:52:34 Functions: 37 40 92.5 %

          Line data    Source code
       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 <set>
      39             : #include <sys/stat.h>
      40             : 
      41             : #include "cpl_conv.h"
      42             : #include "cpl_error.h"
      43             : #include "cpl_minixml.h"
      44             : #include "cpl_progress.h"
      45             : #include "cpl_string.h"
      46             : #include "cpl_vsi.h"
      47             : #include "ograpispy.h"
      48             : #include "ogr_core.h"
      49             : #include "ogrsf_frmts.h"
      50             : 
      51             : /************************************************************************/
      52             : /*                             GDALDriver()                             */
      53             : /************************************************************************/
      54             : 
      55             : GDALDriver::GDALDriver() = default;
      56             : 
      57             : /************************************************************************/
      58             : /*                            ~GDALDriver()                             */
      59             : /************************************************************************/
      60             : 
      61      349912 : GDALDriver::~GDALDriver()
      62             : 
      63             : {
      64      199558 :     if (pfnUnloadDriver != nullptr)
      65        5211 :         pfnUnloadDriver(this);
      66      349912 : }
      67             : 
      68             : /************************************************************************/
      69             : /*                         GDALCreateDriver()                           */
      70             : /************************************************************************/
      71             : 
      72             : /**
      73             :  * \brief Create a GDALDriver.
      74             :  *
      75             :  * Creates a driver in the GDAL heap.
      76             :  */
      77             : 
      78         234 : GDALDriverH CPL_STDCALL GDALCreateDriver()
      79             : {
      80         234 :     return new GDALDriver();
      81             : }
      82             : 
      83             : /************************************************************************/
      84             : /*                         GDALDestroyDriver()                          */
      85             : /************************************************************************/
      86             : 
      87             : /**
      88             :  * \brief Destroy a GDALDriver.
      89             :  *
      90             :  * This is roughly equivalent to deleting the driver, but is guaranteed
      91             :  * to take place in the GDAL heap.  It is important this that function
      92             :  * not be called on a driver that is registered with the GDALDriverManager.
      93             :  *
      94             :  * @param hDriver the driver to destroy.
      95             :  */
      96             : 
      97           0 : void CPL_STDCALL GDALDestroyDriver(GDALDriverH hDriver)
      98             : 
      99             : {
     100           0 :     if (hDriver != nullptr)
     101           0 :         delete GDALDriver::FromHandle(hDriver);
     102           0 : }
     103             : 
     104             : /************************************************************************/
     105             : /*                               Open()                                 */
     106             : /************************************************************************/
     107             : 
     108             : //! @cond Doxygen_Suppress
     109             : 
     110      510543 : GDALDataset *GDALDriver::Open(GDALOpenInfo *poOpenInfo, bool bSetOpenOptions)
     111             : {
     112             : 
     113      510543 :     GDALDataset *poDS = nullptr;
     114      510543 :     pfnOpen = GetOpenCallback();
     115      510425 :     if (pfnOpen != nullptr)
     116             :     {
     117      492635 :         poDS = pfnOpen(poOpenInfo);
     118             :     }
     119       17790 :     else if (pfnOpenWithDriverArg != nullptr)
     120             :     {
     121       17823 :         poDS = pfnOpenWithDriverArg(this, poOpenInfo);
     122             :     }
     123             : 
     124      510600 :     if (poDS)
     125             :     {
     126       42790 :         poDS->nOpenFlags = poOpenInfo->nOpenFlags & ~GDAL_OF_FROM_GDALOPEN;
     127             : 
     128       42790 :         if (strlen(poDS->GetDescription()) == 0)
     129       11276 :             poDS->SetDescription(poOpenInfo->pszFilename);
     130             : 
     131       42774 :         if (poDS->poDriver == nullptr)
     132       40050 :             poDS->poDriver = this;
     133             : 
     134       42774 :         if (poDS->papszOpenOptions == nullptr && bSetOpenOptions)
     135             :         {
     136          28 :             poDS->papszOpenOptions = CSLDuplicate(poOpenInfo->papszOpenOptions);
     137             :         }
     138             : 
     139       42774 :         if (!(poOpenInfo->nOpenFlags & GDAL_OF_INTERNAL))
     140             :         {
     141       36360 :             if (CPLGetPID() != GDALGetResponsiblePIDForCurrentThread())
     142           0 :                 CPLDebug(
     143             :                     "GDAL",
     144             :                     "GDALOpen(%s, this=%p) succeeds as "
     145             :                     "%s (pid=%d, responsiblePID=%d).",
     146           0 :                     poOpenInfo->pszFilename, poDS, GetDescription(),
     147           0 :                     static_cast<int>(CPLGetPID()),
     148           0 :                     static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
     149             :             else
     150       36343 :                 CPLDebug("GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
     151       36348 :                          poOpenInfo->pszFilename, poDS, GetDescription());
     152             : 
     153       36394 :             poDS->AddToDatasetOpenList();
     154             :         }
     155             :     }
     156             : 
     157      510620 :     return poDS;
     158             : }
     159             : 
     160             : //! @endcond
     161             : 
     162             : /************************************************************************/
     163             : /*                               Create()                               */
     164             : /************************************************************************/
     165             : 
     166             : /**
     167             :  * \brief Create a new dataset with this driver.
     168             :  *
     169             :  * What argument values are legal for particular drivers is driver specific,
     170             :  * and there is no way to query in advance to establish legal values.
     171             :  *
     172             :  * That function will try to validate the creation option list passed to the
     173             :  * driver with the GDALValidateCreationOptions() method. This check can be
     174             :  * disabled by defining the configuration option
     175             :  * GDAL_VALIDATE_CREATION_OPTIONS=NO.
     176             :  *
     177             :  * After you have finished working with the returned dataset, it is
     178             :  * <b>required</b> to close it with GDALClose(). This does not only close the
     179             :  * file handle, but also ensures that all the data and metadata has been written
     180             :  * to the dataset (GDALFlushCache() is not sufficient for that purpose).
     181             :  *
     182             :  * In GDAL 2, the arguments nXSize, nYSize and nBands can be passed to 0 when
     183             :  * creating a vector-only dataset for a compatible driver.
     184             :  *
     185             :  * Equivalent of the C function GDALCreate().
     186             :  *
     187             :  * @param pszFilename the name of the dataset to create.  UTF-8 encoded.
     188             :  * @param nXSize width of created raster in pixels.
     189             :  * @param nYSize height of created raster in pixels.
     190             :  * @param nBands number of bands.
     191             :  * @param eType type of raster.
     192             :  * @param papszOptions list of driver specific control parameters.
     193             :  * The APPEND_SUBDATASET=YES option can be
     194             :  * specified to avoid prior destruction of existing dataset.
     195             :  *
     196             :  * @return NULL on failure, or a new GDALDataset.
     197             :  */
     198             : 
     199       18518 : GDALDataset *GDALDriver::Create(const char *pszFilename, int nXSize, int nYSize,
     200             :                                 int nBands, GDALDataType eType,
     201             :                                 CSLConstList papszOptions)
     202             : 
     203             : {
     204             :     /* -------------------------------------------------------------------- */
     205             :     /*      Does this format support creation.                              */
     206             :     /* -------------------------------------------------------------------- */
     207       18518 :     pfnCreate = GetCreateCallback();
     208       18518 :     if (pfnCreate == nullptr && pfnCreateEx == nullptr &&
     209         732 :         pfnCreateVectorOnly == nullptr)
     210             :     {
     211           1 :         CPLError(CE_Failure, CPLE_NotSupported,
     212             :                  "GDALDriver::Create() ... no create method implemented"
     213             :                  " for this format.");
     214             : 
     215           1 :         return nullptr;
     216             :     }
     217             :     /* -------------------------------------------------------------------- */
     218             :     /*      Do some rudimentary argument checking.                          */
     219             :     /* -------------------------------------------------------------------- */
     220       18517 :     if (nBands < 0)
     221             :     {
     222           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     223             :                  "Attempt to create dataset with %d bands is illegal,"
     224             :                  "Must be >= 0.",
     225             :                  nBands);
     226           1 :         return nullptr;
     227             :     }
     228             : 
     229       18516 :     if (GetMetadataItem(GDAL_DCAP_RASTER) != nullptr &&
     230       31663 :         GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr &&
     231       13147 :         (nXSize < 1 || nYSize < 1))
     232             :     {
     233           1 :         CPLError(CE_Failure, CPLE_AppDefined,
     234             :                  "Attempt to create %dx%d dataset is illegal,"
     235             :                  "sizes must be larger than zero.",
     236             :                  nXSize, nYSize);
     237           1 :         return nullptr;
     238             :     }
     239             : 
     240             :     /* -------------------------------------------------------------------- */
     241             :     /*      Make sure we cleanup if there is an existing dataset of this    */
     242             :     /*      name.  But even if that seems to fail we will continue since    */
     243             :     /*      it might just be a corrupt file or something.                   */
     244             :     /* -------------------------------------------------------------------- */
     245       18515 :     if (!CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false))
     246             :     {
     247             :         // Someone issuing Create("foo.tif") on a
     248             :         // memory driver doesn't expect files with those names to be deleted
     249             :         // on a file system...
     250             :         // This is somewhat messy. Ideally there should be a way for the
     251             :         // driver to overload the default behavior
     252       18499 :         if (!EQUAL(GetDescription(), "MEM") &&
     253       28994 :             !EQUAL(GetDescription(), "Memory") &&
     254             :             // ogr2ogr -f PostgreSQL might reach the Delete method of the
     255             :             // PostgisRaster driver which is undesirable
     256       10495 :             !EQUAL(GetDescription(), "PostgreSQL"))
     257             :         {
     258       10493 :             QuietDelete(pszFilename);
     259             :         }
     260             :     }
     261             : 
     262             :     /* -------------------------------------------------------------------- */
     263             :     /*      Validate creation options.                                      */
     264             :     /* -------------------------------------------------------------------- */
     265       18515 :     if (CPLTestBool(
     266             :             CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
     267       18515 :         GDALValidateCreationOptions(this, papszOptions);
     268             : 
     269             :     /* -------------------------------------------------------------------- */
     270             :     /*      Proceed with creation.                                          */
     271             :     /* -------------------------------------------------------------------- */
     272       37030 :     CPLDebug("GDAL", "GDALDriver::Create(%s,%s,%d,%d,%d,%s,%p)",
     273       18515 :              GetDescription(), pszFilename, nXSize, nYSize, nBands,
     274             :              GDALGetDataTypeName(eType), papszOptions);
     275             : 
     276       18515 :     GDALDataset *poDS = nullptr;
     277       18515 :     if (pfnCreateEx != nullptr)
     278             :     {
     279           0 :         poDS = pfnCreateEx(this, pszFilename, nXSize, nYSize, nBands, eType,
     280             :                            const_cast<char **>(papszOptions));
     281             :     }
     282       18515 :     else if (pfnCreate != nullptr)
     283             :     {
     284       17784 :         poDS = pfnCreate(pszFilename, nXSize, nYSize, nBands, eType,
     285             :                          const_cast<char **>(papszOptions));
     286             :     }
     287         731 :     else if (nBands < 1)
     288             :     {
     289         731 :         poDS = pfnCreateVectorOnly(this, pszFilename,
     290             :                                    const_cast<char **>(papszOptions));
     291             :     }
     292             : 
     293       18515 :     if (poDS != nullptr)
     294             :     {
     295       33520 :         if (poDS->GetDescription() == nullptr ||
     296       16760 :             strlen(poDS->GetDescription()) == 0)
     297       14291 :             poDS->SetDescription(pszFilename);
     298             : 
     299       16760 :         if (poDS->poDriver == nullptr)
     300       16096 :             poDS->poDriver = this;
     301             : 
     302       16760 :         poDS->AddToDatasetOpenList();
     303             :     }
     304             : 
     305       18515 :     return poDS;
     306             : }
     307             : 
     308             : /************************************************************************/
     309             : /*                             GDALCreate()                             */
     310             : /************************************************************************/
     311             : 
     312             : /**
     313             :  * \brief Create a new dataset with this driver.
     314             :  *
     315             :  * @see GDALDriver::Create()
     316             :  */
     317             : 
     318       15013 : GDALDatasetH CPL_DLL CPL_STDCALL GDALCreate(GDALDriverH hDriver,
     319             :                                             const char *pszFilename, int nXSize,
     320             :                                             int nYSize, int nBands,
     321             :                                             GDALDataType eBandType,
     322             :                                             CSLConstList papszOptions)
     323             : 
     324             : {
     325       15013 :     VALIDATE_POINTER1(hDriver, "GDALCreate", nullptr);
     326             : 
     327       15013 :     GDALDatasetH hDS = GDALDriver::FromHandle(hDriver)->Create(
     328             :         pszFilename, nXSize, nYSize, nBands, eBandType, papszOptions);
     329             : 
     330             : #ifdef OGRAPISPY_ENABLED
     331       15013 :     if (nBands < 1)
     332             :     {
     333        2638 :         OGRAPISpyCreateDataSource(hDriver, pszFilename,
     334             :                                   const_cast<char **>(papszOptions), hDS);
     335             :     }
     336             : #endif
     337             : 
     338       15013 :     return hDS;
     339             : }
     340             : 
     341             : /************************************************************************/
     342             : /*                       CreateMultiDimensional()                       */
     343             : /************************************************************************/
     344             : 
     345             : /**
     346             :  * \brief Create a new multidimensional dataset with this driver.
     347             :  *
     348             :  * Only drivers that advertise the GDAL_DCAP_MULTIDIM_RASTER capability and
     349             :  * implement the pfnCreateMultiDimensional method might return a non nullptr
     350             :  * GDALDataset.
     351             :  *
     352             :  * This is the same as the C function GDALCreateMultiDimensional().
     353             :  *
     354             :  * @param pszFilename  the name of the dataset to create.  UTF-8 encoded.
     355             :  * @param papszRootGroupOptions driver specific options regarding the creation
     356             :  *                              of the root group. Might be nullptr.
     357             :  * @param papszOptions driver specific options regarding the creation
     358             :  *                     of the dataset. Might be nullptr.
     359             :  * @return a new dataset, or nullptr in case of failure.
     360             :  *
     361             :  * @since GDAL 3.1
     362             :  */
     363             : 
     364             : GDALDataset *
     365         461 : GDALDriver::CreateMultiDimensional(const char *pszFilename,
     366             :                                    CSLConstList papszRootGroupOptions,
     367             :                                    CSLConstList papszOptions)
     368             : 
     369             : {
     370             :     /* -------------------------------------------------------------------- */
     371             :     /*      Does this format support creation.                              */
     372             :     /* -------------------------------------------------------------------- */
     373         461 :     pfnCreateMultiDimensional = GetCreateMultiDimensionalCallback();
     374         461 :     if (pfnCreateMultiDimensional == nullptr)
     375             :     {
     376           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     377             :                  "GDALDriver::CreateMultiDimensional() ... "
     378             :                  "no CreateMultiDimensional method implemented "
     379             :                  "for this format.");
     380             : 
     381           0 :         return nullptr;
     382             :     }
     383             : 
     384             :     /* -------------------------------------------------------------------- */
     385             :     /*      Validate creation options.                                      */
     386             :     /* -------------------------------------------------------------------- */
     387         461 :     if (CPLTestBool(
     388             :             CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
     389             :     {
     390             :         const char *pszOptionList =
     391         461 :             GetMetadataItem(GDAL_DMD_MULTIDIM_DATASET_CREATIONOPTIONLIST);
     392         922 :         CPLString osDriver;
     393         461 :         osDriver.Printf("driver %s", GetDescription());
     394         461 :         GDALValidateOptions(pszOptionList, papszOptions, "creation option",
     395             :                             osDriver);
     396             :     }
     397             : 
     398         461 :     auto poDstDS = pfnCreateMultiDimensional(pszFilename, papszRootGroupOptions,
     399             :                                              papszOptions);
     400             : 
     401         461 :     if (poDstDS != nullptr)
     402             :     {
     403         918 :         if (poDstDS->GetDescription() == nullptr ||
     404         459 :             strlen(poDstDS->GetDescription()) == 0)
     405          94 :             poDstDS->SetDescription(pszFilename);
     406             : 
     407         459 :         if (poDstDS->poDriver == nullptr)
     408         457 :             poDstDS->poDriver = this;
     409             :     }
     410             : 
     411         461 :     return poDstDS;
     412             : }
     413             : 
     414             : /************************************************************************/
     415             : /*                       GDALCreateMultiDimensional()                   */
     416             : /************************************************************************/
     417             : 
     418             : /** \brief Create a new multidimensional dataset with this driver.
     419             :  *
     420             :  * This is the same as the C++ method GDALDriver::CreateMultiDimensional().
     421             :  */
     422         416 : GDALDatasetH GDALCreateMultiDimensional(GDALDriverH hDriver,
     423             :                                         const char *pszName,
     424             :                                         CSLConstList papszRootGroupOptions,
     425             :                                         CSLConstList papszOptions)
     426             : {
     427         416 :     VALIDATE_POINTER1(hDriver, __func__, nullptr);
     428         416 :     VALIDATE_POINTER1(pszName, __func__, nullptr);
     429         416 :     return GDALDataset::ToHandle(
     430             :         GDALDriver::FromHandle(hDriver)->CreateMultiDimensional(
     431         416 :             pszName, papszRootGroupOptions, papszOptions));
     432             : }
     433             : 
     434             : /************************************************************************/
     435             : /*                  DefaultCreateCopyMultiDimensional()                 */
     436             : /************************************************************************/
     437             : 
     438             : //! @cond Doxygen_Suppress
     439             : 
     440          18 : CPLErr GDALDriver::DefaultCreateCopyMultiDimensional(
     441             :     GDALDataset *poSrcDS, GDALDataset *poDstDS, bool bStrict,
     442             :     CSLConstList papszOptions, GDALProgressFunc pfnProgress,
     443             :     void *pProgressData)
     444             : {
     445          18 :     if (pfnProgress == nullptr)
     446           2 :         pfnProgress = GDALDummyProgress;
     447             : 
     448          36 :     auto poSrcRG = poSrcDS->GetRootGroup();
     449          18 :     if (!poSrcRG)
     450           0 :         return CE_Failure;
     451          36 :     auto poDstRG = poDstDS->GetRootGroup();
     452          18 :     if (!poDstRG)
     453           0 :         return CE_Failure;
     454          18 :     GUInt64 nCurCost = 0;
     455          36 :     return poDstRG->CopyFrom(poDstRG, poSrcDS, poSrcRG, bStrict, nCurCost,
     456             :                              poSrcRG->GetTotalCopyCost(), pfnProgress,
     457          18 :                              pProgressData, papszOptions)
     458          18 :                ? CE_None
     459          18 :                : CE_Failure;
     460             : }
     461             : 
     462             : //! @endcond
     463             : 
     464             : /************************************************************************/
     465             : /*                          DefaultCopyMasks()                          */
     466             : /************************************************************************/
     467             : 
     468             : //! @cond Doxygen_Suppress
     469        5864 : CPLErr GDALDriver::DefaultCopyMasks(GDALDataset *poSrcDS, GDALDataset *poDstDS,
     470             :                                     int bStrict)
     471             : 
     472             : {
     473        5864 :     return DefaultCopyMasks(poSrcDS, poDstDS, bStrict, nullptr, nullptr,
     474        5864 :                             nullptr);
     475             : }
     476             : 
     477        6850 : CPLErr GDALDriver::DefaultCopyMasks(GDALDataset *poSrcDS, GDALDataset *poDstDS,
     478             :                                     int bStrict, CSLConstList /*papszOptions*/,
     479             :                                     GDALProgressFunc pfnProgress,
     480             :                                     void *pProgressData)
     481             : 
     482             : {
     483        6850 :     if (pfnProgress == nullptr)
     484        5864 :         pfnProgress = GDALDummyProgress;
     485             : 
     486        6850 :     int nBands = poSrcDS->GetRasterCount();
     487        6850 :     if (nBands == 0)
     488           0 :         return CE_None;
     489             : 
     490             :     /* -------------------------------------------------------------------- */
     491             :     /*      Try to copy mask if it seems appropriate.                       */
     492             :     /* -------------------------------------------------------------------- */
     493        6850 :     const char *papszOptions[2] = {"COMPRESSED=YES", nullptr};
     494        6850 :     CPLErr eErr = CE_None;
     495             : 
     496        6850 :     int nTotalBandsWithMask = 0;
     497       23911 :     for (int iBand = 0; iBand < nBands; ++iBand)
     498             :     {
     499       17061 :         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(iBand + 1);
     500             : 
     501       17061 :         int nMaskFlags = poSrcBand->GetMaskFlags();
     502       17061 :         if (!(nMaskFlags &
     503             :               (GMF_ALL_VALID | GMF_PER_DATASET | GMF_ALPHA | GMF_NODATA)))
     504             :         {
     505           7 :             nTotalBandsWithMask++;
     506             :         }
     507             :     }
     508             : 
     509        6850 :     int iBandWithMask = 0;
     510       23911 :     for (int iBand = 0; eErr == CE_None && iBand < nBands; ++iBand)
     511             :     {
     512       17061 :         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(iBand + 1);
     513             : 
     514       17061 :         int nMaskFlags = poSrcBand->GetMaskFlags();
     515       17061 :         if (eErr == CE_None && !(nMaskFlags & (GMF_ALL_VALID | GMF_PER_DATASET |
     516             :                                                GMF_ALPHA | GMF_NODATA)))
     517             :         {
     518           7 :             GDALRasterBand *poDstBand = poDstDS->GetRasterBand(iBand + 1);
     519           7 :             if (poDstBand != nullptr)
     520             :             {
     521           7 :                 eErr = poDstBand->CreateMaskBand(nMaskFlags);
     522           7 :                 if (eErr == CE_None)
     523             :                 {
     524             :                     // coverity[divide_by_zero]
     525          14 :                     void *pScaledData = GDALCreateScaledProgress(
     526           7 :                         double(iBandWithMask) / nTotalBandsWithMask,
     527           7 :                         double(iBandWithMask + 1) / nTotalBandsWithMask,
     528             :                         pfnProgress, pProgressData);
     529          14 :                     eErr = GDALRasterBandCopyWholeRaster(
     530           7 :                         poSrcBand->GetMaskBand(), poDstBand->GetMaskBand(),
     531             :                         papszOptions, GDALScaledProgress, pScaledData);
     532           7 :                     GDALDestroyScaledProgress(pScaledData);
     533             :                 }
     534           0 :                 else if (!bStrict)
     535             :                 {
     536           0 :                     eErr = CE_None;
     537             :                 }
     538             :             }
     539             :         }
     540             :     }
     541             : 
     542             :     /* -------------------------------------------------------------------- */
     543             :     /*      Try to copy a per-dataset mask if we have one.                  */
     544             :     /* -------------------------------------------------------------------- */
     545        6850 :     const int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
     546        6850 :     if (eErr == CE_None &&
     547        6850 :         !(nMaskFlags & (GMF_ALL_VALID | GMF_ALPHA | GMF_NODATA)) &&
     548           9 :         (nMaskFlags & GMF_PER_DATASET))
     549             :     {
     550           5 :         eErr = poDstDS->CreateMaskBand(nMaskFlags);
     551           5 :         if (eErr == CE_None)
     552             :         {
     553           5 :             eErr = GDALRasterBandCopyWholeRaster(
     554           5 :                 poSrcDS->GetRasterBand(1)->GetMaskBand(),
     555           5 :                 poDstDS->GetRasterBand(1)->GetMaskBand(), papszOptions,
     556             :                 pfnProgress, pProgressData);
     557             :         }
     558           0 :         else if (!bStrict)
     559             :         {
     560           0 :             eErr = CE_None;
     561             :         }
     562             :     }
     563             : 
     564        6850 :     return eErr;
     565             : }
     566             : 
     567             : /************************************************************************/
     568             : /*                         DefaultCreateCopy()                          */
     569             : /************************************************************************/
     570             : 
     571        1307 : GDALDataset *GDALDriver::DefaultCreateCopy(const char *pszFilename,
     572             :                                            GDALDataset *poSrcDS, int bStrict,
     573             :                                            CSLConstList papszOptions,
     574             :                                            GDALProgressFunc pfnProgress,
     575             :                                            void *pProgressData)
     576             : 
     577             : {
     578        1307 :     if (pfnProgress == nullptr)
     579           0 :         pfnProgress = GDALDummyProgress;
     580             : 
     581        1307 :     CPLErrorReset();
     582             : 
     583             :     /* -------------------------------------------------------------------- */
     584             :     /*      Use multidimensional raster API if available.                   */
     585             :     /* -------------------------------------------------------------------- */
     586        2614 :     auto poSrcGroup = poSrcDS->GetRootGroup();
     587        1307 :     if (poSrcGroup != nullptr && GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER))
     588             :     {
     589          32 :         CPLStringList aosDatasetCO;
     590          23 :         for (const char *pszOption : cpl::Iterate(papszOptions))
     591             :         {
     592           7 :             if (!STARTS_WITH_CI(pszOption, "ARRAY:"))
     593           0 :                 aosDatasetCO.AddString(pszOption);
     594             :         }
     595             :         auto poDstDS = std::unique_ptr<GDALDataset>(
     596          32 :             CreateMultiDimensional(pszFilename, nullptr, aosDatasetCO.List()));
     597          16 :         if (!poDstDS)
     598           0 :             return nullptr;
     599          32 :         auto poDstGroup = poDstDS->GetRootGroup();
     600          16 :         if (!poDstGroup)
     601           0 :             return nullptr;
     602          16 :         if (DefaultCreateCopyMultiDimensional(
     603          16 :                 poSrcDS, poDstDS.get(), CPL_TO_BOOL(bStrict), papszOptions,
     604          16 :                 pfnProgress, pProgressData) != CE_None)
     605           0 :             return nullptr;
     606          16 :         return poDstDS.release();
     607             :     }
     608             : 
     609             :     /* -------------------------------------------------------------------- */
     610             :     /*      Validate that we can create the output as requested.            */
     611             :     /* -------------------------------------------------------------------- */
     612        1291 :     const int nXSize = poSrcDS->GetRasterXSize();
     613        1291 :     const int nYSize = poSrcDS->GetRasterYSize();
     614        1291 :     const int nBands = poSrcDS->GetRasterCount();
     615             : 
     616        1291 :     CPLDebug("GDAL", "Using default GDALDriver::CreateCopy implementation.");
     617             : 
     618        1291 :     const int nLayerCount = poSrcDS->GetLayerCount();
     619        1323 :     if (nBands == 0 && nLayerCount == 0 &&
     620          32 :         GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
     621             :     {
     622          27 :         CPLError(CE_Failure, CPLE_NotSupported,
     623             :                  "GDALDriver::DefaultCreateCopy does not support zero band");
     624          27 :         return nullptr;
     625             :     }
     626        1264 :     if (poSrcDS->GetDriver() != nullptr &&
     627        1263 :         poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_RASTER) != nullptr &&
     628        1256 :         poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr &&
     629        2530 :         GetMetadataItem(GDAL_DCAP_RASTER) == nullptr &&
     630           3 :         GetMetadataItem(GDAL_DCAP_VECTOR) != nullptr)
     631             :     {
     632           3 :         CPLError(CE_Failure, CPLE_NotSupported,
     633             :                  "Source driver is raster-only whereas output driver is "
     634             :                  "vector-only");
     635           3 :         return nullptr;
     636             :     }
     637        1261 :     else if (poSrcDS->GetDriver() != nullptr &&
     638        1260 :              poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_RASTER) ==
     639           7 :                  nullptr &&
     640           7 :              poSrcDS->GetDriver()->GetMetadataItem(GDAL_DCAP_VECTOR) !=
     641           7 :                  nullptr &&
     642        2521 :              GetMetadataItem(GDAL_DCAP_RASTER) != nullptr &&
     643           0 :              GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
     644             :     {
     645           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     646             :                  "Source driver is vector-only whereas output driver is "
     647             :                  "raster-only");
     648           0 :         return nullptr;
     649             :     }
     650             : 
     651        1261 :     if (!pfnProgress(0.0, nullptr, pProgressData))
     652             :     {
     653           2 :         CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
     654           2 :         return nullptr;
     655             :     }
     656             : 
     657             :     /* -------------------------------------------------------------------- */
     658             :     /*      Propagate some specific structural metadata as options if it    */
     659             :     /*      appears to be supported by the target driver and the caller     */
     660             :     /*      didn't provide values.                                          */
     661             :     /* -------------------------------------------------------------------- */
     662        1259 :     char **papszCreateOptions = CSLDuplicate(papszOptions);
     663        1259 :     const char *const apszOptItems[] = {"NBITS", "IMAGE_STRUCTURE", "PIXELTYPE",
     664             :                                         "IMAGE_STRUCTURE", nullptr};
     665             : 
     666        3751 :     for (int iOptItem = 0; nBands > 0 && apszOptItems[iOptItem] != nullptr;
     667        2492 :          iOptItem += 2)
     668             :     {
     669             :         // does the source have this metadata item on the first band?
     670        2492 :         auto poBand = poSrcDS->GetRasterBand(1);
     671        2492 :         poBand->EnablePixelTypeSignedByteWarning(false);
     672        4984 :         const char *pszValue = poBand->GetMetadataItem(
     673        2492 :             apszOptItems[iOptItem], apszOptItems[iOptItem + 1]);
     674        2492 :         poBand->EnablePixelTypeSignedByteWarning(true);
     675             : 
     676        2492 :         if (pszValue == nullptr)
     677        2491 :             continue;
     678             : 
     679             :         // Do not override provided value.
     680           1 :         if (CSLFetchNameValue(papszCreateOptions, pszValue) != nullptr)
     681           0 :             continue;
     682             : 
     683             :         // Does this appear to be a supported creation option on this driver?
     684             :         const char *pszOptionList =
     685           1 :             GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST);
     686             : 
     687           1 :         if (pszOptionList == nullptr ||
     688           1 :             strstr(pszOptionList, apszOptItems[iOptItem]) == nullptr)
     689           0 :             continue;
     690             : 
     691           1 :         papszCreateOptions = CSLSetNameValue(papszCreateOptions,
     692           1 :                                              apszOptItems[iOptItem], pszValue);
     693             :     }
     694             : 
     695             :     /* -------------------------------------------------------------------- */
     696             :     /*      Create destination dataset.                                     */
     697             :     /* -------------------------------------------------------------------- */
     698        1259 :     GDALDataType eType = GDT_Unknown;
     699             : 
     700        1259 :     if (nBands > 0)
     701        1246 :         eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     702             :     GDALDataset *poDstDS =
     703        1259 :         Create(pszFilename, nXSize, nYSize, nBands, eType, papszCreateOptions);
     704             : 
     705        1259 :     CSLDestroy(papszCreateOptions);
     706             : 
     707        1259 :     if (poDstDS == nullptr)
     708         496 :         return nullptr;
     709             : 
     710         763 :     int nDstBands = poDstDS->GetRasterCount();
     711         763 :     CPLErr eErr = CE_None;
     712         763 :     if (nDstBands != nBands)
     713             :     {
     714           5 :         if (GetMetadataItem(GDAL_DCAP_RASTER) != nullptr)
     715             :         {
     716             :             // Should not happen for a well-behaved driver.
     717           5 :             CPLError(
     718             :                 CE_Failure, CPLE_AppDefined,
     719             :                 "Output driver created only %d bands whereas %d were expected",
     720             :                 nDstBands, nBands);
     721           5 :             eErr = CE_Failure;
     722             :         }
     723           5 :         nDstBands = 0;
     724             :     }
     725             : 
     726             :     /* -------------------------------------------------------------------- */
     727             :     /*      Try setting the projection and geotransform if it seems         */
     728             :     /*      suitable.                                                       */
     729             :     /* -------------------------------------------------------------------- */
     730         763 :     double adfGeoTransform[6] = {};
     731             : 
     732         763 :     if (nDstBands == 0 && !bStrict)
     733           4 :         CPLTurnFailureIntoWarning(true);
     734             : 
     735        1521 :     if (eErr == CE_None &&
     736         758 :         poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None
     737             :         // TODO(schwehr): The default value check should be a function.
     738        1523 :         && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0 ||
     739           2 :             adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0 ||
     740           2 :             adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0))
     741             :     {
     742         704 :         eErr = poDstDS->SetGeoTransform(adfGeoTransform);
     743         704 :         if (!bStrict)
     744         329 :             eErr = CE_None;
     745             :     }
     746             : 
     747         763 :     if (eErr == CE_None)
     748             :     {
     749         758 :         const auto poSrcSRS = poSrcDS->GetSpatialRef();
     750         758 :         if (poSrcSRS && !poSrcSRS->IsEmpty())
     751             :         {
     752         662 :             eErr = poDstDS->SetSpatialRef(poSrcSRS);
     753         662 :             if (!bStrict)
     754         309 :                 eErr = CE_None;
     755             :         }
     756             :     }
     757             : 
     758             :     /* -------------------------------------------------------------------- */
     759             :     /*      Copy GCPs.                                                      */
     760             :     /* -------------------------------------------------------------------- */
     761         763 :     if (poSrcDS->GetGCPCount() > 0 && eErr == CE_None)
     762             :     {
     763           2 :         eErr = poDstDS->SetGCPs(poSrcDS->GetGCPCount(), poSrcDS->GetGCPs(),
     764             :                                 poSrcDS->GetGCPProjection());
     765           2 :         if (!bStrict)
     766           1 :             eErr = CE_None;
     767             :     }
     768             : 
     769         763 :     if (nDstBands == 0 && !bStrict)
     770           4 :         CPLTurnFailureIntoWarning(false);
     771             : 
     772             :     /* -------------------------------------------------------------------- */
     773             :     /*      Copy metadata.                                                  */
     774             :     /* -------------------------------------------------------------------- */
     775         763 :     DefaultCopyMetadata(poSrcDS, poDstDS, papszOptions, nullptr);
     776             : 
     777             :     /* -------------------------------------------------------------------- */
     778             :     /*      Loop copying bands.                                             */
     779             :     /* -------------------------------------------------------------------- */
     780        2022 :     for (int iBand = 0; eErr == CE_None && iBand < nDstBands; ++iBand)
     781             :     {
     782        1259 :         GDALRasterBand *const poSrcBand = poSrcDS->GetRasterBand(iBand + 1);
     783        1259 :         GDALRasterBand *const poDstBand = poDstDS->GetRasterBand(iBand + 1);
     784             : 
     785             :         /* --------------------------------------------------------------------
     786             :          */
     787             :         /*      Do we need to copy a colortable. */
     788             :         /* --------------------------------------------------------------------
     789             :          */
     790        1259 :         GDALColorTable *const poCT = poSrcBand->GetColorTable();
     791        1259 :         if (poCT != nullptr)
     792          24 :             poDstBand->SetColorTable(poCT);
     793             : 
     794             :         /* --------------------------------------------------------------------
     795             :          */
     796             :         /*      Do we need to copy other metadata?  Most of this is */
     797             :         /*      non-critical, so lets not bother folks if it fails are we */
     798             :         /*      are not in strict mode. */
     799             :         /* --------------------------------------------------------------------
     800             :          */
     801        1259 :         if (!bStrict)
     802         556 :             CPLTurnFailureIntoWarning(true);
     803             : 
     804        1259 :         if (strlen(poSrcBand->GetDescription()) > 0)
     805          68 :             poDstBand->SetDescription(poSrcBand->GetDescription());
     806             : 
     807        1259 :         if (CSLCount(poSrcBand->GetMetadata()) > 0)
     808         120 :             poDstBand->SetMetadata(poSrcBand->GetMetadata());
     809             : 
     810        1259 :         int bSuccess = FALSE;
     811        1259 :         double dfValue = poSrcBand->GetOffset(&bSuccess);
     812        1259 :         if (bSuccess && dfValue != 0.0)
     813           4 :             poDstBand->SetOffset(dfValue);
     814             : 
     815        1259 :         dfValue = poSrcBand->GetScale(&bSuccess);
     816        1259 :         if (bSuccess && dfValue != 1.0)
     817           5 :             poDstBand->SetScale(dfValue);
     818             : 
     819        1259 :         GDALCopyNoDataValue(poDstBand, poSrcBand);
     820             : 
     821        1959 :         if (poSrcBand->GetColorInterpretation() != GCI_Undefined &&
     822         700 :             poSrcBand->GetColorInterpretation() !=
     823         700 :                 poDstBand->GetColorInterpretation())
     824         493 :             poDstBand->SetColorInterpretation(
     825         493 :                 poSrcBand->GetColorInterpretation());
     826             : 
     827        1259 :         char **papszCatNames = poSrcBand->GetCategoryNames();
     828        1259 :         if (nullptr != papszCatNames)
     829           1 :             poDstBand->SetCategoryNames(papszCatNames);
     830             : 
     831             :         // Only copy RAT if it is of reasonable size to fit in memory
     832        1259 :         GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
     833        1261 :         if (poRAT != nullptr && static_cast<GIntBig>(poRAT->GetColumnCount()) *
     834           2 :                                         poRAT->GetRowCount() <
     835             :                                     1024 * 1024)
     836             :         {
     837           2 :             poDstBand->SetDefaultRAT(poRAT);
     838             :         }
     839             : 
     840        1259 :         if (!bStrict)
     841             :         {
     842         556 :             CPLTurnFailureIntoWarning(false);
     843             :         }
     844             :         else
     845             :         {
     846         703 :             eErr = CPLGetLastErrorType();
     847             :         }
     848             :     }
     849             : 
     850             :     /* -------------------------------------------------------------------- */
     851             :     /*      Copy image data.                                                */
     852             :     /* -------------------------------------------------------------------- */
     853         763 :     if (eErr == CE_None && nDstBands > 0)
     854         717 :         eErr = GDALDatasetCopyWholeRaster(poSrcDS, poDstDS, nullptr,
     855             :                                           pfnProgress, pProgressData);
     856             : 
     857             :     /* -------------------------------------------------------------------- */
     858             :     /*      Should we copy some masks over?                                 */
     859             :     /* -------------------------------------------------------------------- */
     860         763 :     if (eErr == CE_None && nDstBands > 0)
     861         699 :         eErr = DefaultCopyMasks(poSrcDS, poDstDS, eErr);
     862             : 
     863             :     /* -------------------------------------------------------------------- */
     864             :     /*      Copy vector layers                                              */
     865             :     /* -------------------------------------------------------------------- */
     866         763 :     if (eErr == CE_None)
     867             :     {
     868         710 :         if (nLayerCount > 0 && poDstDS->TestCapability(ODsCCreateLayer))
     869             :         {
     870          18 :             for (int iLayer = 0; iLayer < nLayerCount; ++iLayer)
     871             :             {
     872           9 :                 OGRLayer *poLayer = poSrcDS->GetLayer(iLayer);
     873             : 
     874           9 :                 if (poLayer == nullptr)
     875           0 :                     continue;
     876             : 
     877           9 :                 poDstDS->CopyLayer(poLayer, poLayer->GetName(), nullptr);
     878             :             }
     879             :         }
     880             :     }
     881             : 
     882             :     /* -------------------------------------------------------------------- */
     883             :     /*      Try to cleanup the output dataset if the translation failed.    */
     884             :     /* -------------------------------------------------------------------- */
     885         763 :     if (eErr != CE_None)
     886             :     {
     887          53 :         delete poDstDS;
     888          53 :         if (!CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false))
     889             :         {
     890             :             // Only delete if creating a new file
     891          53 :             Delete(pszFilename);
     892             :         }
     893          53 :         return nullptr;
     894             :     }
     895             :     else
     896             :     {
     897         710 :         CPLErrorReset();
     898             :     }
     899             : 
     900         710 :     return poDstDS;
     901             : }
     902             : 
     903             : /************************************************************************/
     904             : /*                       DefaultCopyMetadata()                          */
     905             : /************************************************************************/
     906             : 
     907        5094 : void GDALDriver::DefaultCopyMetadata(GDALDataset *poSrcDS, GDALDataset *poDstDS,
     908             :                                      CSLConstList papszOptions,
     909             :                                      CSLConstList papszExcludedDomains)
     910             : {
     911             :     const char *pszCopySrcMDD =
     912        5094 :         CSLFetchNameValueDef(papszOptions, "COPY_SRC_MDD", "AUTO");
     913        5094 :     char **papszSrcMDD = CSLFetchNameValueMultiple(papszOptions, "SRC_MDD");
     914        5094 :     if (EQUAL(pszCopySrcMDD, "AUTO") || CPLTestBool(pszCopySrcMDD) ||
     915             :         papszSrcMDD)
     916             :     {
     917           4 :         if ((!papszSrcMDD || CSLFindString(papszSrcMDD, "") >= 0 ||
     918           2 :              CSLFindString(papszSrcMDD, "_DEFAULT_") >= 0) &&
     919       10031 :             CSLFindString(papszExcludedDomains, "") < 0 &&
     920        4935 :             CSLFindString(papszExcludedDomains, "_DEFAULT_") < 0)
     921             :         {
     922        4935 :             if (poSrcDS->GetMetadata() != nullptr)
     923         676 :                 poDstDS->SetMetadata(poSrcDS->GetMetadata());
     924             :         }
     925             : 
     926             :         /* -------------------------------------------------------------------- */
     927             :         /*      Copy transportable special domain metadata.                     */
     928             :         /*      It would be nice to copy geolocation, but it is pretty fragile. */
     929             :         /* -------------------------------------------------------------------- */
     930        5092 :         constexpr const char *apszDefaultDomains[] = {
     931             :             "RPC", "xml:XMP", "json:ISIS3", "json:VICAR"};
     932       25460 :         for (const char *pszDomain : apszDefaultDomains)
     933             :         {
     934       40720 :             if ((!papszSrcMDD || CSLFindString(papszSrcMDD, pszDomain) >= 0) &&
     935       20352 :                 CSLFindString(papszExcludedDomains, pszDomain) < 0)
     936             :             {
     937       20352 :                 char **papszMD = poSrcDS->GetMetadata(pszDomain);
     938       20352 :                 if (papszMD)
     939           5 :                     poDstDS->SetMetadata(papszMD, pszDomain);
     940             :             }
     941             :         }
     942             : 
     943        5092 :         if ((!EQUAL(pszCopySrcMDD, "AUTO") && CPLTestBool(pszCopySrcMDD)) ||
     944             :             papszSrcMDD)
     945             :         {
     946          24 :             for (const char *pszDomain :
     947          30 :                  CPLStringList(poSrcDS->GetMetadataDomainList()))
     948             :             {
     949          36 :                 if (pszDomain[0] != 0 &&
     950          12 :                     (!papszSrcMDD ||
     951          12 :                      CSLFindString(papszSrcMDD, pszDomain) >= 0))
     952             :                 {
     953          10 :                     bool bCanCopy = true;
     954          10 :                     if (CSLFindString(papszExcludedDomains, pszDomain) >= 0)
     955             :                     {
     956           0 :                         bCanCopy = false;
     957             :                     }
     958             :                     else
     959             :                     {
     960          50 :                         for (const char *pszOtherDomain : apszDefaultDomains)
     961             :                         {
     962          40 :                             if (EQUAL(pszDomain, pszOtherDomain))
     963             :                             {
     964           0 :                                 bCanCopy = false;
     965           0 :                                 break;
     966             :                             }
     967             :                         }
     968          10 :                         if (!papszSrcMDD)
     969             :                         {
     970           6 :                             constexpr const char *const apszReservedDomains[] =
     971             :                                 {"IMAGE_STRUCTURE", "DERIVED_SUBDATASETS"};
     972           6 :                             for (const char *pszOtherDomain :
     973          12 :                                  apszReservedDomains)
     974             :                             {
     975          10 :                                 if (EQUAL(pszDomain, pszOtherDomain))
     976             :                                 {
     977           4 :                                     bCanCopy = false;
     978           4 :                                     break;
     979             :                                 }
     980             :                             }
     981             :                         }
     982             :                     }
     983          10 :                     if (bCanCopy)
     984             :                     {
     985           6 :                         poDstDS->SetMetadata(poSrcDS->GetMetadata(pszDomain),
     986           6 :                                              pszDomain);
     987             :                     }
     988             :                 }
     989             :             }
     990             :         }
     991             :     }
     992        5094 :     CSLDestroy(papszSrcMDD);
     993        5094 : }
     994             : 
     995             : /************************************************************************/
     996             : /*                      QuietDeleteForCreateCopy()                      */
     997             : /************************************************************************/
     998             : 
     999       10132 : CPLErr GDALDriver::QuietDeleteForCreateCopy(const char *pszFilename,
    1000             :                                             GDALDataset *poSrcDS)
    1001             : {
    1002             :     // Someone issuing CreateCopy("foo.tif") on a
    1003             :     // memory driver doesn't expect files with those names to be deleted
    1004             :     // on a file system...
    1005             :     // This is somewhat messy. Ideally there should be a way for the
    1006             :     // driver to overload the default behavior
    1007       19986 :     if (!EQUAL(GetDescription(), "MEM") && !EQUAL(GetDescription(), "Memory") &&
    1008             :         // Also exclude database formats for which there's no file list
    1009             :         // and whose opening might be slow (GeoRaster in particular)
    1010       29840 :         !EQUAL(GetDescription(), "GeoRaster") &&
    1011        9854 :         !EQUAL(GetDescription(), "PostGISRaster"))
    1012             :     {
    1013             :         /* --------------------------------------------------------------------
    1014             :          */
    1015             :         /*      Establish list of files of output dataset if it already
    1016             :          * exists. */
    1017             :         /* --------------------------------------------------------------------
    1018             :          */
    1019       19672 :         std::set<std::string> oSetExistingDestFiles;
    1020             :         {
    1021        9836 :             CPLPushErrorHandler(CPLQuietErrorHandler);
    1022        9836 :             const char *const apszAllowedDrivers[] = {GetDescription(),
    1023        9836 :                                                       nullptr};
    1024             :             auto poExistingOutputDS =
    1025             :                 std::unique_ptr<GDALDataset>(GDALDataset::Open(
    1026       19672 :                     pszFilename, GDAL_OF_RASTER, apszAllowedDrivers));
    1027        9836 :             if (poExistingOutputDS)
    1028             :             {
    1029         650 :                 for (const char *pszFileInList :
    1030         619 :                      CPLStringList(poExistingOutputDS->GetFileList()))
    1031             :                 {
    1032             :                     oSetExistingDestFiles.insert(
    1033         325 :                         CPLString(pszFileInList).replaceAll('\\', '/'));
    1034             :                 }
    1035             :             }
    1036        9836 :             CPLPopErrorHandler();
    1037             :         }
    1038             : 
    1039             :         /* --------------------------------------------------------------------
    1040             :          */
    1041             :         /*      Check if the source dataset shares some files with the dest
    1042             :          * one.*/
    1043             :         /* --------------------------------------------------------------------
    1044             :          */
    1045       19672 :         std::set<std::string> oSetExistingDestFilesFoundInSource;
    1046        9836 :         if (!oSetExistingDestFiles.empty())
    1047             :         {
    1048         294 :             CPLPushErrorHandler(CPLQuietErrorHandler);
    1049             :             // We need to reopen in a temporary dataset for the particular
    1050             :             // case of overwritten a .tif.ovr file from a .tif
    1051             :             // If we probe the file list of the .tif, it will then open the
    1052             :             // .tif.ovr !
    1053         294 :             const char *const apszAllowedDrivers[] = {
    1054         294 :                 poSrcDS->GetDriver() ? poSrcDS->GetDriver()->GetDescription()
    1055             :                                      : nullptr,
    1056         294 :                 nullptr};
    1057             :             auto poSrcDSTmp = std::unique_ptr<GDALDataset>(GDALDataset::Open(
    1058         294 :                 poSrcDS->GetDescription(), GDAL_OF_RASTER, apszAllowedDrivers,
    1059         588 :                 poSrcDS->papszOpenOptions));
    1060         294 :             if (poSrcDSTmp)
    1061             :             {
    1062         191 :                 for (const char *pszFileInList :
    1063         371 :                      CPLStringList(poSrcDSTmp->GetFileList()))
    1064             :                 {
    1065         382 :                     CPLString osFilename(pszFileInList);
    1066         191 :                     osFilename.replaceAll('\\', '/');
    1067         191 :                     if (oSetExistingDestFiles.find(osFilename) !=
    1068         382 :                         oSetExistingDestFiles.end())
    1069             :                     {
    1070          14 :                         oSetExistingDestFilesFoundInSource.insert(osFilename);
    1071             :                     }
    1072             :                 }
    1073             :             }
    1074         294 :             CPLPopErrorHandler();
    1075             :         }
    1076             : 
    1077             :         // If the source file(s) and the dest one share some files in
    1078             :         // common, only remove the files that are *not* in common
    1079        9836 :         if (!oSetExistingDestFilesFoundInSource.empty())
    1080             :         {
    1081          33 :             for (const std::string &osFilename : oSetExistingDestFiles)
    1082             :             {
    1083          19 :                 if (oSetExistingDestFilesFoundInSource.find(osFilename) ==
    1084          38 :                     oSetExistingDestFilesFoundInSource.end())
    1085             :                 {
    1086           5 :                     VSIUnlink(osFilename.c_str());
    1087             :                 }
    1088             :             }
    1089             :         }
    1090             : 
    1091        9836 :         QuietDelete(pszFilename);
    1092             :     }
    1093             : 
    1094       10132 :     return CE_None;
    1095             : }
    1096             : 
    1097             : //! @endcond
    1098             : 
    1099             : /************************************************************************/
    1100             : /*                             CreateCopy()                             */
    1101             : /************************************************************************/
    1102             : 
    1103             : /**
    1104             :  * \brief Create a copy of a dataset.
    1105             :  *
    1106             :  * This method will attempt to create a copy of a raster dataset with the
    1107             :  * indicated filename, and in this drivers format.  Band number, size,
    1108             :  * type, projection, geotransform and so forth are all to be copied from
    1109             :  * the provided template dataset.
    1110             :  *
    1111             :  * Note that many sequential write once formats (such as JPEG and PNG) don't
    1112             :  * implement the Create() method but do implement this CreateCopy() method.
    1113             :  * If the driver doesn't implement CreateCopy(), but does implement Create()
    1114             :  * then the default CreateCopy() mechanism built on calling Create() will
    1115             :  * be used.
    1116             :  * So to test if CreateCopy() is available, you can test if GDAL_DCAP_CREATECOPY
    1117             :  * or GDAL_DCAP_CREATE is set in the GDAL metadata.
    1118             :  *
    1119             :  * It is intended that CreateCopy() will often be used with a source dataset
    1120             :  * which is a virtual dataset allowing configuration of band types, and other
    1121             :  * information without actually duplicating raster data (see the VRT driver).
    1122             :  * This is what is done by the gdal_translate utility for example.
    1123             :  *
    1124             :  * That function will try to validate the creation option list passed to the
    1125             :  * driver with the GDALValidateCreationOptions() method. This check can be
    1126             :  * disabled by defining the configuration option
    1127             :  * GDAL_VALIDATE_CREATION_OPTIONS=NO.
    1128             :  *
    1129             :  * This function copy all metadata from the default domain ("")
    1130             :  *
    1131             :  * Even is bStrict is TRUE, only the <b>value</b> of the data is equivalent,
    1132             :  * but the data layout (INTERLEAVE as PIXEL/LINE/BAND) of the dst dataset is
    1133             :  * controlled by the papszOptions creation options, and may differ from the
    1134             :  * poSrcDS src dataset.
    1135             :  * Starting from GDAL 3.5, if no INTERLEAVE and COMPRESS creation option has
    1136             :  * been specified in papszOptions, and if the driver supports equivalent
    1137             :  * interleaving as the src dataset, the CreateCopy() will internally add the
    1138             :  * proper creation option to get the same data interleaving.
    1139             :  *
    1140             :  * After you have finished working with the returned dataset, it is
    1141             :  * <b>required</b> to close it with GDALClose(). This does not only close the
    1142             :  * file handle, but also ensures that all the data and metadata has been written
    1143             :  * to the dataset (GDALFlushCache() is not sufficient for that purpose).
    1144             :  *
    1145             :  * For multidimensional datasets, papszOptions can contain array creation
    1146             :  * options, if they are prefixed with "ARRAY:". \see GDALGroup::CopyFrom()
    1147             :  * documentation for further details regarding such options.
    1148             :  *
    1149             :  * @param pszFilename the name for the new dataset.  UTF-8 encoded.
    1150             :  * @param poSrcDS the dataset being duplicated.
    1151             :  * @param bStrict TRUE if the copy must be strictly equivalent, or more
    1152             :  * normally FALSE indicating that the copy may adapt as needed for the
    1153             :  * output format.
    1154             :  * @param papszOptions additional format dependent options controlling
    1155             :  * creation of the output file.
    1156             :  * The APPEND_SUBDATASET=YES option can be specified to avoid prior destruction
    1157             :  * of existing dataset.
    1158             :  * Starting with GDAL 3.8.0, the following options are recognized by the
    1159             :  * GTiff, COG, VRT, PNG au JPEG drivers:
    1160             :  * <ul>
    1161             :  * <li>COPY_SRC_MDD=AUTO/YES/NO: whether metadata domains of the source dataset
    1162             :  * should be copied to the destination dataset. In the default AUTO mode, only
    1163             :  * "safe" domains will be copied, which include the default metadata domain
    1164             :  * (some drivers may include other domains such as IMD, RPC, GEOLOCATION). When
    1165             :  * setting YES, all domains will be copied (but a few reserved ones like
    1166             :  * IMAGE_STRUCTURE or DERIVED_SUBDATASETS). When setting NO, no source metadata
    1167             :  * will be copied.
    1168             :  * </li>
    1169             :  *<li>SRC_MDD=domain_name: which source metadata domain should be copied.
    1170             :  * This option restricts the list of source metadata domains to be copied
    1171             :  * (it implies COPY_SRC_MDD=YES if it is not set). This option may be specified
    1172             :  * as many times as they are source domains. The default metadata domain is the
    1173             :  * empty string "" ("_DEFAULT_") may also be used when empty string is not practical)
    1174             :  * </li>
    1175             :  * </ul>
    1176             :  * @param pfnProgress a function to be used to report progress of the copy.
    1177             :  * @param pProgressData application data passed into progress function.
    1178             :  *
    1179             :  * @return a pointer to the newly created dataset (may be read-only access).
    1180             :  */
    1181             : 
    1182        9902 : GDALDataset *GDALDriver::CreateCopy(const char *pszFilename,
    1183             :                                     GDALDataset *poSrcDS, int bStrict,
    1184             :                                     CSLConstList papszOptions,
    1185             :                                     GDALProgressFunc pfnProgress,
    1186             :                                     void *pProgressData)
    1187             : 
    1188             : {
    1189        9902 :     if (pfnProgress == nullptr)
    1190        8515 :         pfnProgress = GDALDummyProgress;
    1191             : 
    1192        9902 :     const int nBandCount = poSrcDS->GetRasterCount();
    1193             : 
    1194             :     /* -------------------------------------------------------------------- */
    1195             :     /*      If no INTERLEAVE creation option is given, we will try to add   */
    1196             :     /*      one that matches the current srcDS interleaving                 */
    1197             :     /* -------------------------------------------------------------------- */
    1198        9902 :     char **papszOptionsToDelete = nullptr;
    1199             :     const char *srcInterleave =
    1200        9902 :         poSrcDS->GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE");
    1201        5623 :     if (nBandCount > 1 && srcInterleave != nullptr &&
    1202       16113 :         CSLFetchNameValue(papszOptions, "INTERLEAVE") == nullptr &&
    1203         588 :         EQUAL(CSLFetchNameValueDef(papszOptions, "COMPRESS", "NONE"), "NONE"))
    1204             :     {
    1205             : 
    1206             :         // look for INTERLEAVE values of the driver
    1207         398 :         char **interleavesCSL = nullptr;
    1208             :         const char *pszOptionList =
    1209         398 :             this->GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST);
    1210             :         CPLXMLNode *xmlNode =
    1211         398 :             !pszOptionList ? nullptr : CPLParseXMLString(pszOptionList);
    1212         398 :         for (CPLXMLNode *child = !xmlNode ? nullptr : xmlNode->psChild;
    1213        8965 :              child != nullptr; child = child->psNext)
    1214             :         {
    1215        8567 :             if ((child->eType == CXT_Element) &&
    1216        8567 :                 EQUAL(child->pszValue, "Option"))
    1217             :             {
    1218             :                 const char *nameAttribute =
    1219        8567 :                     CPLGetXMLValue(child, "name", nullptr);
    1220        8567 :                 const bool isInterleaveAttribute =
    1221        8567 :                     nameAttribute && EQUAL(nameAttribute, "INTERLEAVE");
    1222        8567 :                 if (isInterleaveAttribute)
    1223             :                 {
    1224         156 :                     for (CPLXMLNode *optionChild = child->psChild;
    1225         948 :                          optionChild != nullptr;
    1226         792 :                          optionChild = optionChild->psNext)
    1227             :                     {
    1228         792 :                         if ((optionChild->eType == CXT_Element) &&
    1229         319 :                             EQUAL(optionChild->pszValue, "Value"))
    1230             :                         {
    1231         319 :                             CPLXMLNode *optionChildValue = optionChild->psChild;
    1232         319 :                             if (optionChildValue &&
    1233         319 :                                 (optionChildValue->eType == CXT_Text))
    1234             :                             {
    1235         319 :                                 interleavesCSL = CSLAddString(
    1236         319 :                                     interleavesCSL, optionChildValue->pszValue);
    1237             :                             }
    1238             :                         }
    1239             :                     }
    1240             :                 }
    1241             :             }
    1242             :         }
    1243         398 :         CPLDestroyXMLNode(xmlNode);
    1244             : 
    1245             :         const char *dstInterleaveBand =
    1246         646 :             (CSLFindString(interleavesCSL, "BAND") >= 0)  ? "BAND"
    1247         248 :             : (CSLFindString(interleavesCSL, "BSQ") >= 0) ? "BSQ"
    1248         398 :                                                           : nullptr;
    1249             :         const char *dstInterleaveLine =
    1250         796 :             (CSLFindString(interleavesCSL, "LINE") >= 0)  ? "LINE"
    1251         398 :             : (CSLFindString(interleavesCSL, "BIL") >= 0) ? "BIL"
    1252         398 :                                                           : nullptr;
    1253             :         const char *dstInterleavePixel =
    1254         646 :             (CSLFindString(interleavesCSL, "PIXEL") >= 0) ? "PIXEL"
    1255         248 :             : (CSLFindString(interleavesCSL, "BIP") >= 0) ? "BIP"
    1256         398 :                                                           : nullptr;
    1257         398 :         const char *dstInterleave =
    1258         647 :             EQUAL(srcInterleave, "BAND")    ? dstInterleaveBand
    1259         496 :             : EQUAL(srcInterleave, "LINE")  ? dstInterleaveLine
    1260         247 :             : EQUAL(srcInterleave, "PIXEL") ? dstInterleavePixel
    1261             :                                             : nullptr;
    1262         398 :         CSLDestroy(interleavesCSL);
    1263             : 
    1264         398 :         if (dstInterleave != nullptr)
    1265             :         {
    1266         156 :             papszOptionsToDelete = CSLDuplicate(papszOptions);
    1267         156 :             papszOptionsToDelete = CSLSetNameValue(papszOptionsToDelete,
    1268             :                                                    "INTERLEAVE", dstInterleave);
    1269         156 :             papszOptionsToDelete = CSLSetNameValue(
    1270             :                 papszOptionsToDelete, "@INTERLEAVE_ADDED_AUTOMATICALLY", "YES");
    1271         156 :             papszOptions = papszOptionsToDelete;
    1272             :         }
    1273             :     }
    1274             : 
    1275             :     /* -------------------------------------------------------------------- */
    1276             :     /*      Make sure we cleanup if there is an existing dataset of this    */
    1277             :     /*      name.  But even if that seems to fail we will continue since    */
    1278             :     /*      it might just be a corrupt file or something.                   */
    1279             :     /* -------------------------------------------------------------------- */
    1280             :     const bool bAppendSubdataset =
    1281        9902 :         CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false);
    1282             :     // Note: @QUIET_DELETE_ON_CREATE_COPY is set to NO by the KMLSuperOverlay
    1283             :     // driver when writing a .kmz file. Also by GDALTranslate() if it has
    1284             :     // already done a similar job.
    1285       19785 :     if (!bAppendSubdataset &&
    1286        9883 :         CPLFetchBool(papszOptions, "@QUIET_DELETE_ON_CREATE_COPY", true))
    1287             :     {
    1288        8799 :         QuietDeleteForCreateCopy(pszFilename, poSrcDS);
    1289             :     }
    1290             : 
    1291             :     int iIdxQuietDeleteOnCreateCopy =
    1292        9902 :         CSLPartialFindString(papszOptions, "@QUIET_DELETE_ON_CREATE_COPY=");
    1293        9902 :     if (iIdxQuietDeleteOnCreateCopy >= 0)
    1294             :     {
    1295        1084 :         if (papszOptionsToDelete == nullptr)
    1296         983 :             papszOptionsToDelete = CSLDuplicate(papszOptions);
    1297        1084 :         papszOptionsToDelete = CSLRemoveStrings(
    1298             :             papszOptionsToDelete, iIdxQuietDeleteOnCreateCopy, 1, nullptr);
    1299        1084 :         papszOptions = papszOptionsToDelete;
    1300             :     }
    1301             : 
    1302             :     /* -------------------------------------------------------------------- */
    1303             :     /*      If _INTERNAL_DATASET=YES, the returned dataset will not be      */
    1304             :     /*      registered in the global list of open datasets.                 */
    1305             :     /* -------------------------------------------------------------------- */
    1306             :     const int iIdxInternalDataset =
    1307        9902 :         CSLPartialFindString(papszOptions, "_INTERNAL_DATASET=");
    1308        9902 :     bool bInternalDataset = false;
    1309        9902 :     if (iIdxInternalDataset >= 0)
    1310             :     {
    1311             :         bInternalDataset =
    1312        4153 :             CPLFetchBool(papszOptions, "_INTERNAL_DATASET", false);
    1313        4153 :         if (papszOptionsToDelete == nullptr)
    1314        4153 :             papszOptionsToDelete = CSLDuplicate(papszOptions);
    1315        4153 :         papszOptionsToDelete = CSLRemoveStrings(
    1316             :             papszOptionsToDelete, iIdxInternalDataset, 1, nullptr);
    1317        4153 :         papszOptions = papszOptionsToDelete;
    1318             :     }
    1319             : 
    1320             :     /* -------------------------------------------------------------------- */
    1321             :     /*      Validate creation options.                                      */
    1322             :     /* -------------------------------------------------------------------- */
    1323        9902 :     if (CPLTestBool(
    1324             :             CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
    1325             :     {
    1326       19804 :         auto poSrcGroup = poSrcDS->GetRootGroup();
    1327        9902 :         if (poSrcGroup != nullptr && GetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER))
    1328             :         {
    1329         178 :             CPLStringList aosDatasetCO;
    1330          96 :             for (const char *pszOption : cpl::Iterate(papszOptions))
    1331             :             {
    1332           7 :                 if (!STARTS_WITH_CI(pszOption, "ARRAY:"))
    1333           0 :                     aosDatasetCO.AddString(pszOption);
    1334             :             }
    1335          89 :             GDALValidateCreationOptions(this, aosDatasetCO.List());
    1336             :         }
    1337             :         else
    1338             :         {
    1339        9813 :             GDALValidateCreationOptions(this, papszOptions);
    1340             :         }
    1341             :     }
    1342             : 
    1343             :     /* -------------------------------------------------------------------- */
    1344             :     /*      Advise the source raster that we are going to read it completely */
    1345             :     /* -------------------------------------------------------------------- */
    1346             : 
    1347        9902 :     const int nXSize = poSrcDS->GetRasterXSize();
    1348        9902 :     const int nYSize = poSrcDS->GetRasterYSize();
    1349        9902 :     GDALDataType eDT = GDT_Unknown;
    1350        9902 :     if (nBandCount > 0)
    1351             :     {
    1352        9684 :         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1);
    1353        9684 :         if (poSrcBand)
    1354        9684 :             eDT = poSrcBand->GetRasterDataType();
    1355             :     }
    1356        9902 :     poSrcDS->AdviseRead(0, 0, nXSize, nYSize, nXSize, nYSize, eDT, nBandCount,
    1357        9902 :                         nullptr, nullptr);
    1358             : 
    1359             :     /* -------------------------------------------------------------------- */
    1360             :     /*      If the format provides a CreateCopy() method use that,          */
    1361             :     /*      otherwise fallback to the internal implementation using the     */
    1362             :     /*      Create() method.                                                */
    1363             :     /* -------------------------------------------------------------------- */
    1364        9902 :     GDALDataset *poDstDS = nullptr;
    1365        9902 :     auto l_pfnCreateCopy = GetCreateCopyCallback();
    1366       18723 :     if (l_pfnCreateCopy != nullptr &&
    1367        8821 :         !CPLTestBool(CPLGetConfigOption("GDAL_DEFAULT_CREATE_COPY", "NO")))
    1368             :     {
    1369        8821 :         poDstDS = l_pfnCreateCopy(pszFilename, poSrcDS, bStrict,
    1370             :                                   const_cast<char **>(papszOptions),
    1371             :                                   pfnProgress, pProgressData);
    1372        8821 :         if (poDstDS != nullptr)
    1373             :         {
    1374       15242 :             if (poDstDS->GetDescription() == nullptr ||
    1375        7621 :                 strlen(poDstDS->GetDescription()) == 0)
    1376         186 :                 poDstDS->SetDescription(pszFilename);
    1377             : 
    1378        7621 :             if (poDstDS->poDriver == nullptr)
    1379        6659 :                 poDstDS->poDriver = this;
    1380             : 
    1381        7621 :             if (!bInternalDataset)
    1382        3470 :                 poDstDS->AddToDatasetOpenList();
    1383             :         }
    1384             :     }
    1385             :     else
    1386             :     {
    1387        1081 :         poDstDS = DefaultCreateCopy(pszFilename, poSrcDS, bStrict, papszOptions,
    1388             :                                     pfnProgress, pProgressData);
    1389             :     }
    1390             : 
    1391        9902 :     CSLDestroy(papszOptionsToDelete);
    1392        9902 :     return poDstDS;
    1393             : }
    1394             : 
    1395             : /************************************************************************/
    1396             : /*                           GDALCreateCopy()                           */
    1397             : /************************************************************************/
    1398             : 
    1399             : /**
    1400             :  * \brief Create a copy of a dataset.
    1401             :  *
    1402             :  * @see GDALDriver::CreateCopy()
    1403             :  */
    1404             : 
    1405        5371 : GDALDatasetH CPL_STDCALL GDALCreateCopy(GDALDriverH hDriver,
    1406             :                                         const char *pszFilename,
    1407             :                                         GDALDatasetH hSrcDS, int bStrict,
    1408             :                                         CSLConstList papszOptions,
    1409             :                                         GDALProgressFunc pfnProgress,
    1410             :                                         void *pProgressData)
    1411             : 
    1412             : {
    1413        5371 :     VALIDATE_POINTER1(hDriver, "GDALCreateCopy", nullptr);
    1414        5371 :     VALIDATE_POINTER1(hSrcDS, "GDALCreateCopy", nullptr);
    1415             : 
    1416        5371 :     return GDALDriver::FromHandle(hDriver)->CreateCopy(
    1417             :         pszFilename, GDALDataset::FromHandle(hSrcDS), bStrict, papszOptions,
    1418        5371 :         pfnProgress, pProgressData);
    1419             : }
    1420             : 
    1421             : /************************************************************************/
    1422             : /*                      CanVectorTranslateFrom()                        */
    1423             : /************************************************************************/
    1424             : 
    1425             : /** Returns whether the driver can translate from a vector dataset,
    1426             :  * using the arguments passed to GDALVectorTranslate() stored in
    1427             :  * papszVectorTranslateArguments.
    1428             :  *
    1429             :  * This is used to determine if the driver supports the VectorTranslateFrom()
    1430             :  * operation.
    1431             :  *
    1432             :  * @param pszDestName Target dataset name
    1433             :  * @param poSourceDS  Source dataset
    1434             :  * @param papszVectorTranslateArguments Non-positional arguments passed to
    1435             :  *                                      GDALVectorTranslate() (may be nullptr)
    1436             :  * @param[out] ppapszFailureReasons nullptr, or a pointer to an null-terminated
    1437             :  * array of strings to record the reason(s) for the impossibility.
    1438             :  * @return true if VectorTranslateFrom() can be called with the same arguments.
    1439             :  * @since GDAL 3.8
    1440             :  */
    1441         600 : bool GDALDriver::CanVectorTranslateFrom(
    1442             :     const char *pszDestName, GDALDataset *poSourceDS,
    1443             :     CSLConstList papszVectorTranslateArguments, char ***ppapszFailureReasons)
    1444             : 
    1445             : {
    1446         600 :     if (ppapszFailureReasons)
    1447             :     {
    1448           0 :         *ppapszFailureReasons = nullptr;
    1449             :     }
    1450             : 
    1451         600 :     if (!pfnCanVectorTranslateFrom)
    1452             :     {
    1453         597 :         if (ppapszFailureReasons)
    1454             :         {
    1455           0 :             *ppapszFailureReasons = CSLAddString(
    1456             :                 nullptr,
    1457             :                 "CanVectorTranslateFrom() not implemented for this driver");
    1458             :         }
    1459         597 :         return false;
    1460             :     }
    1461             : 
    1462           3 :     char **papszFailureReasons = nullptr;
    1463           3 :     bool bRet = pfnCanVectorTranslateFrom(
    1464             :         pszDestName, poSourceDS, papszVectorTranslateArguments,
    1465             :         ppapszFailureReasons ? ppapszFailureReasons : &papszFailureReasons);
    1466           3 :     if (!ppapszFailureReasons)
    1467             :     {
    1468           1 :         for (const char *pszReason :
    1469           5 :              cpl::Iterate(CSLConstList(papszFailureReasons)))
    1470             :         {
    1471           1 :             CPLDebug("GDAL", "%s", pszReason);
    1472             :         }
    1473           3 :         CSLDestroy(papszFailureReasons);
    1474             :     }
    1475           3 :     return bRet;
    1476             : }
    1477             : 
    1478             : /************************************************************************/
    1479             : /*                         VectorTranslateFrom()                        */
    1480             : /************************************************************************/
    1481             : 
    1482             : /** Create a copy of a vector dataset, using the arguments passed to
    1483             :  * GDALVectorTranslate() stored in papszVectorTranslateArguments.
    1484             :  *
    1485             :  * This may be implemented by some drivers that can convert from an existing
    1486             :  * dataset in an optimized way.
    1487             :  *
    1488             :  * This is for example used by the PMTiles to convert from MBTiles.
    1489             :  *
    1490             :  * @param pszDestName Target dataset name
    1491             :  * @param poSourceDS  Source dataset
    1492             :  * @param papszVectorTranslateArguments Non-positional arguments passed to
    1493             :  *                                      GDALVectorTranslate() (may be nullptr)
    1494             :  * @param pfnProgress a function to be used to report progress of the copy.
    1495             :  * @param pProgressData application data passed into progress function.
    1496             :  * @return a new dataset in case of success, or nullptr in case of error.
    1497             :  * @since GDAL 3.8
    1498             :  */
    1499           2 : GDALDataset *GDALDriver::VectorTranslateFrom(
    1500             :     const char *pszDestName, GDALDataset *poSourceDS,
    1501             :     CSLConstList papszVectorTranslateArguments, GDALProgressFunc pfnProgress,
    1502             :     void *pProgressData)
    1503             : 
    1504             : {
    1505           2 :     if (!pfnVectorTranslateFrom)
    1506             :     {
    1507           0 :         CPLError(CE_Failure, CPLE_AppDefined,
    1508             :                  "VectorTranslateFrom() not implemented for this driver");
    1509           0 :         return nullptr;
    1510             :     }
    1511             : 
    1512           2 :     return pfnVectorTranslateFrom(pszDestName, poSourceDS,
    1513             :                                   papszVectorTranslateArguments, pfnProgress,
    1514           2 :                                   pProgressData);
    1515             : }
    1516             : 
    1517             : /************************************************************************/
    1518             : /*                            QuietDelete()                             */
    1519             : /************************************************************************/
    1520             : 
    1521             : /**
    1522             :  * \brief Delete dataset if found.
    1523             :  *
    1524             :  * This is a helper method primarily used by Create() and
    1525             :  * CreateCopy() to predelete any dataset of the name soon to be
    1526             :  * created.  It will attempt to delete the named dataset if
    1527             :  * one is found, otherwise it does nothing.  An error is only
    1528             :  * returned if the dataset is found but the delete fails.
    1529             :  *
    1530             :  * This is a static method and it doesn't matter what driver instance
    1531             :  * it is invoked on.  It will attempt to discover the correct driver
    1532             :  * using Identify().
    1533             :  *
    1534             :  * @param pszName the dataset name to try and delete.
    1535             :  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
    1536             :  * terminated list of strings with the driver short names that must be
    1537             :  * considered. (Note: implemented only starting with GDAL 3.4.1)
    1538             :  * @return CE_None if the dataset does not exist, or is deleted without issues.
    1539             :  */
    1540             : 
    1541       20329 : CPLErr GDALDriver::QuietDelete(const char *pszName,
    1542             :                                CSLConstList papszAllowedDrivers)
    1543             : 
    1544             : {
    1545             :     VSIStatBufL sStat;
    1546             :     const bool bExists =
    1547       20329 :         VSIStatExL(pszName, &sStat,
    1548       20329 :                    VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0;
    1549             : 
    1550             : #ifdef S_ISFIFO
    1551       20329 :     if (bExists && S_ISFIFO(sStat.st_mode))
    1552           0 :         return CE_None;
    1553             : #endif
    1554             : 
    1555       20329 :     if (bExists && VSI_ISDIR(sStat.st_mode))
    1556             :     {
    1557             :         // It is not desirable to remove directories quietly.  Necessary to
    1558             :         // avoid ogr_mitab_12 to destroy file created at ogr_mitab_7.
    1559         103 :         return CE_None;
    1560             :     }
    1561             : 
    1562       20226 :     GDALDriver *poDriver = nullptr;
    1563       20226 :     if (papszAllowedDrivers)
    1564             :     {
    1565           0 :         GDALOpenInfo oOpenInfo(pszName, GDAL_OF_ALL);
    1566           0 :         for (const char *pszDriverName : cpl::Iterate(papszAllowedDrivers))
    1567             :         {
    1568             :             GDALDriver *poTmpDriver =
    1569           0 :                 GDALDriver::FromHandle(GDALGetDriverByName(pszDriverName));
    1570           0 :             if (poTmpDriver)
    1571             :             {
    1572             :                 const bool bIdentifyRes =
    1573           0 :                     poTmpDriver->pfnIdentifyEx
    1574           0 :                         ? poTmpDriver->pfnIdentifyEx(poTmpDriver, &oOpenInfo) >
    1575             :                               0
    1576           0 :                         : poTmpDriver->pfnIdentify &&
    1577           0 :                               poTmpDriver->pfnIdentify(&oOpenInfo) > 0;
    1578           0 :                 if (bIdentifyRes)
    1579             :                 {
    1580           0 :                     poDriver = poTmpDriver;
    1581           0 :                     break;
    1582             :                 }
    1583             :             }
    1584             :         }
    1585             :     }
    1586             :     else
    1587             :     {
    1588       40452 :         CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
    1589       20226 :         poDriver = GDALDriver::FromHandle(GDALIdentifyDriver(pszName, nullptr));
    1590             :     }
    1591             : 
    1592       20226 :     if (poDriver == nullptr)
    1593       19365 :         return CE_None;
    1594             : 
    1595         861 :     CPLDebug("GDAL", "QuietDelete(%s) invoking Delete()", pszName);
    1596             : 
    1597         861 :     poDriver->pfnDelete = poDriver->GetDeleteCallback();
    1598         907 :     const bool bQuiet = !bExists && poDriver->pfnDelete == nullptr &&
    1599          46 :                         poDriver->pfnDeleteDataSource == nullptr;
    1600         861 :     if (bQuiet)
    1601             :     {
    1602          92 :         CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
    1603          46 :         return poDriver->Delete(pszName);
    1604             :     }
    1605             :     else
    1606             :     {
    1607         815 :         return poDriver->Delete(pszName);
    1608             :     }
    1609             : }
    1610             : 
    1611             : /************************************************************************/
    1612             : /*                               Delete()                               */
    1613             : /************************************************************************/
    1614             : 
    1615             : /**
    1616             :  * \brief Delete named dataset.
    1617             :  *
    1618             :  * The driver will attempt to delete the named dataset in a driver specific
    1619             :  * fashion.  Full featured drivers will delete all associated files,
    1620             :  * database objects, or whatever is appropriate.  The default behavior when
    1621             :  * no driver specific behavior is provided is to attempt to delete all the
    1622             :  * files that are returned by GDALGetFileList() on the dataset handle.
    1623             :  *
    1624             :  * It is unwise to have open dataset handles on this dataset when it is
    1625             :  * deleted.
    1626             :  *
    1627             :  * Equivalent of the C function GDALDeleteDataset().
    1628             :  *
    1629             :  * @param pszFilename name of dataset to delete.
    1630             :  *
    1631             :  * @return CE_None on success, or CE_Failure if the operation fails.
    1632             :  */
    1633             : 
    1634        4605 : CPLErr GDALDriver::Delete(const char *pszFilename)
    1635             : 
    1636             : {
    1637        4605 :     pfnDelete = GetDeleteCallback();
    1638        4605 :     if (pfnDelete != nullptr)
    1639        1094 :         return pfnDelete(pszFilename);
    1640        3511 :     else if (pfnDeleteDataSource != nullptr)
    1641          50 :         return pfnDeleteDataSource(this, pszFilename);
    1642             : 
    1643             :     /* -------------------------------------------------------------------- */
    1644             :     /*      Collect file list.                                              */
    1645             :     /* -------------------------------------------------------------------- */
    1646        3461 :     GDALDatasetH hDS = GDALOpenEx(pszFilename, 0, nullptr, nullptr, nullptr);
    1647             : 
    1648        3461 :     if (hDS == nullptr)
    1649             :     {
    1650         234 :         if (CPLGetLastErrorNo() == 0)
    1651         207 :             CPLError(CE_Failure, CPLE_OpenFailed,
    1652             :                      "Unable to open %s to obtain file list.", pszFilename);
    1653             : 
    1654         234 :         return CE_Failure;
    1655             :     }
    1656             : 
    1657        3227 :     char **papszFileList = GDALGetFileList(hDS);
    1658             : 
    1659        3227 :     GDALClose(hDS);
    1660        3227 :     hDS = nullptr;
    1661             : 
    1662        3227 :     if (CSLCount(papszFileList) == 0)
    1663             :     {
    1664           8 :         CPLError(CE_Failure, CPLE_NotSupported,
    1665             :                  "Unable to determine files associated with %s, "
    1666             :                  "delete fails.",
    1667             :                  pszFilename);
    1668           8 :         CSLDestroy(papszFileList);
    1669           8 :         return CE_Failure;
    1670             :     }
    1671             : 
    1672             :     /* -------------------------------------------------------------------- */
    1673             :     /*      Delete all files.                                               */
    1674             :     /* -------------------------------------------------------------------- */
    1675        3219 :     CPLErr eErr = CE_None;
    1676        7135 :     for (int i = 0; papszFileList[i] != nullptr; ++i)
    1677             :     {
    1678        3916 :         if (VSIUnlink(papszFileList[i]) != 0)
    1679             :         {
    1680           0 :             CPLError(CE_Failure, CPLE_AppDefined, "Deleting %s failed:\n%s",
    1681           0 :                      papszFileList[i], VSIStrerror(errno));
    1682           0 :             eErr = CE_Failure;
    1683             :         }
    1684             :     }
    1685             : 
    1686        3219 :     CSLDestroy(papszFileList);
    1687             : 
    1688        3219 :     return eErr;
    1689             : }
    1690             : 
    1691             : /************************************************************************/
    1692             : /*                         GDALDeleteDataset()                          */
    1693             : /************************************************************************/
    1694             : 
    1695             : /**
    1696             :  * \brief Delete named dataset.
    1697             :  *
    1698             :  * @see GDALDriver::Delete()
    1699             :  */
    1700             : 
    1701        2586 : CPLErr CPL_STDCALL GDALDeleteDataset(GDALDriverH hDriver,
    1702             :                                      const char *pszFilename)
    1703             : 
    1704             : {
    1705        2586 :     if (hDriver == nullptr)
    1706           5 :         hDriver = GDALIdentifyDriver(pszFilename, nullptr);
    1707             : 
    1708        2586 :     if (hDriver == nullptr)
    1709             :     {
    1710           0 :         CPLError(CE_Failure, CPLE_AppDefined, "No identifiable driver for %s.",
    1711             :                  pszFilename);
    1712           0 :         return CE_Failure;
    1713             :     }
    1714             : 
    1715             : #ifdef OGRAPISPY_ENABLED
    1716        2586 :     if (GDALGetMetadataItem(hDriver, GDAL_DCAP_VECTOR, nullptr))
    1717             :     {
    1718         537 :         OGRAPISpyDeleteDataSource(hDriver, pszFilename);
    1719             :     }
    1720             : #endif
    1721             : 
    1722        2586 :     return GDALDriver::FromHandle(hDriver)->Delete(pszFilename);
    1723             : }
    1724             : 
    1725             : /************************************************************************/
    1726             : /*                           DefaultRename()                            */
    1727             : /*                                                                      */
    1728             : /*      The generic implementation based on the file list used when     */
    1729             : /*      there is no format specific implementation.                     */
    1730             : /************************************************************************/
    1731             : 
    1732             : //! @cond Doxygen_Suppress
    1733         171 : CPLErr GDALDriver::DefaultRename(const char *pszNewName, const char *pszOldName)
    1734             : 
    1735             : {
    1736             :     /* -------------------------------------------------------------------- */
    1737             :     /*      Collect file list.                                              */
    1738             :     /* -------------------------------------------------------------------- */
    1739         171 :     GDALDatasetH hDS = GDALOpen(pszOldName, GA_ReadOnly);
    1740             : 
    1741         171 :     if (hDS == nullptr)
    1742             :     {
    1743           0 :         if (CPLGetLastErrorNo() == 0)
    1744           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    1745             :                      "Unable to open %s to obtain file list.", pszOldName);
    1746             : 
    1747           0 :         return CE_Failure;
    1748             :     }
    1749             : 
    1750         171 :     char **papszFileList = GDALGetFileList(hDS);
    1751             : 
    1752         171 :     GDALClose(hDS);
    1753             : 
    1754         171 :     if (CSLCount(papszFileList) == 0)
    1755             :     {
    1756           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    1757             :                  "Unable to determine files associated with %s,\n"
    1758             :                  "rename fails.",
    1759             :                  pszOldName);
    1760             : 
    1761           0 :         return CE_Failure;
    1762             :     }
    1763             : 
    1764             :     /* -------------------------------------------------------------------- */
    1765             :     /*      Produce a list of new filenames that correspond to the old      */
    1766             :     /*      names.                                                          */
    1767             :     /* -------------------------------------------------------------------- */
    1768         171 :     CPLErr eErr = CE_None;
    1769             :     char **papszNewFileList =
    1770         171 :         CPLCorrespondingPaths(pszOldName, pszNewName, papszFileList);
    1771             : 
    1772         171 :     if (papszNewFileList == nullptr)
    1773           0 :         return CE_Failure;
    1774             : 
    1775         348 :     for (int i = 0; papszFileList[i] != nullptr; ++i)
    1776             :     {
    1777         177 :         if (CPLMoveFile(papszNewFileList[i], papszFileList[i]) != 0)
    1778             :         {
    1779           0 :             eErr = CE_Failure;
    1780             :             // Try to put the ones we moved back.
    1781           0 :             for (--i; i >= 0; i--)
    1782             :             {
    1783             :                 // Nothing we can do if the moving back doesn't work...
    1784           0 :                 CPL_IGNORE_RET_VAL(
    1785           0 :                     CPLMoveFile(papszFileList[i], papszNewFileList[i]));
    1786             :             }
    1787           0 :             break;
    1788             :         }
    1789             :     }
    1790             : 
    1791         171 :     CSLDestroy(papszNewFileList);
    1792         171 :     CSLDestroy(papszFileList);
    1793             : 
    1794         171 :     return eErr;
    1795             : }
    1796             : 
    1797             : //! @endcond
    1798             : 
    1799             : /************************************************************************/
    1800             : /*                               Rename()                               */
    1801             : /************************************************************************/
    1802             : 
    1803             : /**
    1804             :  * \brief Rename a dataset.
    1805             :  *
    1806             :  * Rename a dataset. This may including moving the dataset to a new directory
    1807             :  * or even a new filesystem.
    1808             :  *
    1809             :  * It is unwise to have open dataset handles on this dataset when it is
    1810             :  * being renamed.
    1811             :  *
    1812             :  * Equivalent of the C function GDALRenameDataset().
    1813             :  *
    1814             :  * @param pszNewName new name for the dataset.
    1815             :  * @param pszOldName old name for the dataset.
    1816             :  *
    1817             :  * @return CE_None on success, or CE_Failure if the operation fails.
    1818             :  */
    1819             : 
    1820         173 : CPLErr GDALDriver::Rename(const char *pszNewName, const char *pszOldName)
    1821             : 
    1822             : {
    1823         173 :     pfnRename = GetRenameCallback();
    1824         173 :     if (pfnRename != nullptr)
    1825           3 :         return pfnRename(pszNewName, pszOldName);
    1826             : 
    1827         170 :     return DefaultRename(pszNewName, pszOldName);
    1828             : }
    1829             : 
    1830             : /************************************************************************/
    1831             : /*                         GDALRenameDataset()                          */
    1832             : /************************************************************************/
    1833             : 
    1834             : /**
    1835             :  * \brief Rename a dataset.
    1836             :  *
    1837             :  * @see GDALDriver::Rename()
    1838             :  */
    1839             : 
    1840         173 : CPLErr CPL_STDCALL GDALRenameDataset(GDALDriverH hDriver,
    1841             :                                      const char *pszNewName,
    1842             :                                      const char *pszOldName)
    1843             : 
    1844             : {
    1845         173 :     if (hDriver == nullptr)
    1846           0 :         hDriver = GDALIdentifyDriver(pszOldName, nullptr);
    1847             : 
    1848         173 :     if (hDriver == nullptr)
    1849             :     {
    1850           0 :         CPLError(CE_Failure, CPLE_AppDefined, "No identifiable driver for %s.",
    1851             :                  pszOldName);
    1852           0 :         return CE_Failure;
    1853             :     }
    1854             : 
    1855         173 :     return GDALDriver::FromHandle(hDriver)->Rename(pszNewName, pszOldName);
    1856             : }
    1857             : 
    1858             : /************************************************************************/
    1859             : /*                          DefaultCopyFiles()                          */
    1860             : /*                                                                      */
    1861             : /*      The default implementation based on file lists used when        */
    1862             : /*      there is no format specific implementation.                     */
    1863             : /************************************************************************/
    1864             : 
    1865             : //! @cond Doxygen_Suppress
    1866           1 : CPLErr GDALDriver::DefaultCopyFiles(const char *pszNewName,
    1867             :                                     const char *pszOldName)
    1868             : 
    1869             : {
    1870             :     /* -------------------------------------------------------------------- */
    1871             :     /*      Collect file list.                                              */
    1872             :     /* -------------------------------------------------------------------- */
    1873           1 :     GDALDatasetH hDS = GDALOpen(pszOldName, GA_ReadOnly);
    1874             : 
    1875           1 :     if (hDS == nullptr)
    1876             :     {
    1877           0 :         if (CPLGetLastErrorNo() == 0)
    1878           0 :             CPLError(CE_Failure, CPLE_OpenFailed,
    1879             :                      "Unable to open %s to obtain file list.", pszOldName);
    1880             : 
    1881           0 :         return CE_Failure;
    1882             :     }
    1883             : 
    1884           1 :     char **papszFileList = GDALGetFileList(hDS);
    1885             : 
    1886           1 :     GDALClose(hDS);
    1887           1 :     hDS = nullptr;
    1888             : 
    1889           1 :     if (CSLCount(papszFileList) == 0)
    1890             :     {
    1891           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    1892             :                  "Unable to determine files associated with %s,\n"
    1893             :                  "rename fails.",
    1894             :                  pszOldName);
    1895             : 
    1896           0 :         return CE_Failure;
    1897             :     }
    1898             : 
    1899             :     /* -------------------------------------------------------------------- */
    1900             :     /*      Produce a list of new filenames that correspond to the old      */
    1901             :     /*      names.                                                          */
    1902             :     /* -------------------------------------------------------------------- */
    1903           1 :     CPLErr eErr = CE_None;
    1904             :     char **papszNewFileList =
    1905           1 :         CPLCorrespondingPaths(pszOldName, pszNewName, papszFileList);
    1906             : 
    1907           1 :     if (papszNewFileList == nullptr)
    1908           0 :         return CE_Failure;
    1909             : 
    1910           5 :     for (int i = 0; papszFileList[i] != nullptr; ++i)
    1911             :     {
    1912           4 :         if (CPLCopyFile(papszNewFileList[i], papszFileList[i]) != 0)
    1913             :         {
    1914           0 :             eErr = CE_Failure;
    1915             :             // Try to put the ones we moved back.
    1916           0 :             for (--i; i >= 0; --i)
    1917           0 :                 VSIUnlink(papszNewFileList[i]);
    1918           0 :             break;
    1919             :         }
    1920             :     }
    1921             : 
    1922           1 :     CSLDestroy(papszNewFileList);
    1923           1 :     CSLDestroy(papszFileList);
    1924             : 
    1925           1 :     return eErr;
    1926             : }
    1927             : 
    1928             : //! @endcond
    1929             : 
    1930             : /************************************************************************/
    1931             : /*                             CopyFiles()                              */
    1932             : /************************************************************************/
    1933             : 
    1934             : /**
    1935             :  * \brief Copy the files of a dataset.
    1936             :  *
    1937             :  * Copy all the files associated with a dataset.
    1938             :  *
    1939             :  * Equivalent of the C function GDALCopyDatasetFiles().
    1940             :  *
    1941             :  * @param pszNewName new name for the dataset.
    1942             :  * @param pszOldName old name for the dataset.
    1943             :  *
    1944             :  * @return CE_None on success, or CE_Failure if the operation fails.
    1945             :  */
    1946             : 
    1947           3 : CPLErr GDALDriver::CopyFiles(const char *pszNewName, const char *pszOldName)
    1948             : 
    1949             : {
    1950           3 :     pfnCopyFiles = GetCopyFilesCallback();
    1951           3 :     if (pfnCopyFiles != nullptr)
    1952           3 :         return pfnCopyFiles(pszNewName, pszOldName);
    1953             : 
    1954           0 :     return DefaultCopyFiles(pszNewName, pszOldName);
    1955             : }
    1956             : 
    1957             : /************************************************************************/
    1958             : /*                        GDALCopyDatasetFiles()                        */
    1959             : /************************************************************************/
    1960             : 
    1961             : /**
    1962             :  * \brief Copy the files of a dataset.
    1963             :  *
    1964             :  * @see GDALDriver::CopyFiles()
    1965             :  */
    1966             : 
    1967           3 : CPLErr CPL_STDCALL GDALCopyDatasetFiles(GDALDriverH hDriver,
    1968             :                                         const char *pszNewName,
    1969             :                                         const char *pszOldName)
    1970             : 
    1971             : {
    1972           3 :     if (hDriver == nullptr)
    1973           0 :         hDriver = GDALIdentifyDriver(pszOldName, nullptr);
    1974             : 
    1975           3 :     if (hDriver == nullptr)
    1976             :     {
    1977           0 :         CPLError(CE_Failure, CPLE_AppDefined, "No identifiable driver for %s.",
    1978             :                  pszOldName);
    1979           0 :         return CE_Failure;
    1980             :     }
    1981             : 
    1982           3 :     return GDALDriver::FromHandle(hDriver)->CopyFiles(pszNewName, pszOldName);
    1983             : }
    1984             : 
    1985             : /************************************************************************/
    1986             : /*                       GDALGetDriverShortName()                       */
    1987             : /************************************************************************/
    1988             : 
    1989             : /**
    1990             :  * \brief Return the short name of a driver
    1991             :  *
    1992             :  * This is the string that can be
    1993             :  * passed to the GDALGetDriverByName() function.
    1994             :  *
    1995             :  * For the GeoTIFF driver, this is "GTiff"
    1996             :  *
    1997             :  * @param hDriver the handle of the driver
    1998             :  * @return the short name of the driver. The
    1999             :  *         returned string should not be freed and is owned by the driver.
    2000             :  */
    2001             : 
    2002     3302620 : const char *CPL_STDCALL GDALGetDriverShortName(GDALDriverH hDriver)
    2003             : 
    2004             : {
    2005     3302620 :     VALIDATE_POINTER1(hDriver, "GDALGetDriverShortName", nullptr);
    2006             : 
    2007     3302620 :     return GDALDriver::FromHandle(hDriver)->GetDescription();
    2008             : }
    2009             : 
    2010             : /************************************************************************/
    2011             : /*                       GDALGetDriverLongName()                        */
    2012             : /************************************************************************/
    2013             : 
    2014             : /**
    2015             :  * \brief Return the long name of a driver
    2016             :  *
    2017             :  * For the GeoTIFF driver, this is "GeoTIFF"
    2018             :  *
    2019             :  * @param hDriver the handle of the driver
    2020             :  * @return the long name of the driver or empty string. The
    2021             :  *         returned string should not be freed and is owned by the driver.
    2022             :  */
    2023             : 
    2024         464 : const char *CPL_STDCALL GDALGetDriverLongName(GDALDriverH hDriver)
    2025             : 
    2026             : {
    2027         464 :     VALIDATE_POINTER1(hDriver, "GDALGetDriverLongName", nullptr);
    2028             : 
    2029             :     const char *pszLongName =
    2030         464 :         GDALDriver::FromHandle(hDriver)->GetMetadataItem(GDAL_DMD_LONGNAME);
    2031             : 
    2032         464 :     if (pszLongName == nullptr)
    2033           2 :         return "";
    2034             : 
    2035         462 :     return pszLongName;
    2036             : }
    2037             : 
    2038             : /************************************************************************/
    2039             : /*                       GDALGetDriverHelpTopic()                       */
    2040             : /************************************************************************/
    2041             : 
    2042             : /**
    2043             :  * \brief Return the URL to the help that describes the driver
    2044             :  *
    2045             :  * That URL is relative to the GDAL documentation directory.
    2046             :  *
    2047             :  * For the GeoTIFF driver, this is "frmt_gtiff.html"
    2048             :  *
    2049             :  * @param hDriver the handle of the driver
    2050             :  * @return the URL to the help that describes the driver or NULL. The
    2051             :  *         returned string should not be freed and is owned by the driver.
    2052             :  */
    2053             : 
    2054           0 : const char *CPL_STDCALL GDALGetDriverHelpTopic(GDALDriverH hDriver)
    2055             : 
    2056             : {
    2057           0 :     VALIDATE_POINTER1(hDriver, "GDALGetDriverHelpTopic", nullptr);
    2058             : 
    2059           0 :     return GDALDriver::FromHandle(hDriver)->GetMetadataItem(GDAL_DMD_HELPTOPIC);
    2060             : }
    2061             : 
    2062             : /************************************************************************/
    2063             : /*                   GDALGetDriverCreationOptionList()                  */
    2064             : /************************************************************************/
    2065             : 
    2066             : /**
    2067             :  * \brief Return the list of creation options of the driver
    2068             :  *
    2069             :  * Return the list of creation options of the driver used by Create() and
    2070             :  * CreateCopy() as an XML string
    2071             :  *
    2072             :  * @param hDriver the handle of the driver
    2073             :  * @return an XML string that describes the list of creation options or
    2074             :  *         empty string. The returned string should not be freed and is
    2075             :  *         owned by the driver.
    2076             :  */
    2077             : 
    2078           0 : const char *CPL_STDCALL GDALGetDriverCreationOptionList(GDALDriverH hDriver)
    2079             : 
    2080             : {
    2081           0 :     VALIDATE_POINTER1(hDriver, "GDALGetDriverCreationOptionList", nullptr);
    2082             : 
    2083             :     const char *pszOptionList =
    2084           0 :         GDALDriver::FromHandle(hDriver)->GetMetadataItem(
    2085           0 :             GDAL_DMD_CREATIONOPTIONLIST);
    2086             : 
    2087           0 :     if (pszOptionList == nullptr)
    2088           0 :         return "";
    2089             : 
    2090           0 :     return pszOptionList;
    2091             : }
    2092             : 
    2093             : /************************************************************************/
    2094             : /*                   GDALValidateCreationOptions()                      */
    2095             : /************************************************************************/
    2096             : 
    2097             : /**
    2098             :  * \brief Validate the list of creation options that are handled by a driver
    2099             :  *
    2100             :  * This is a helper method primarily used by Create() and
    2101             :  * CreateCopy() to validate that the passed in list of creation options
    2102             :  * is compatible with the GDAL_DMD_CREATIONOPTIONLIST metadata item defined
    2103             :  * by some drivers. @see GDALGetDriverCreationOptionList()
    2104             :  *
    2105             :  * If the GDAL_DMD_CREATIONOPTIONLIST metadata item is not defined, this
    2106             :  * function will return TRUE. Otherwise it will check that the keys and values
    2107             :  * in the list of creation options are compatible with the capabilities declared
    2108             :  * by the GDAL_DMD_CREATIONOPTIONLIST metadata item. In case of incompatibility
    2109             :  * a (non fatal) warning will be emitted and FALSE will be returned.
    2110             :  *
    2111             :  * @param hDriver the handle of the driver with whom the lists of creation
    2112             :  * option must be validated
    2113             :  * @param papszCreationOptions the list of creation options. An array of
    2114             :  * strings, whose last element is a NULL pointer
    2115             :  * @return TRUE if the list of creation options is compatible with the Create()
    2116             :  *         and CreateCopy() method of the driver, FALSE otherwise.
    2117             :  */
    2118             : 
    2119       28581 : int CPL_STDCALL GDALValidateCreationOptions(GDALDriverH hDriver,
    2120             :                                             CSLConstList papszCreationOptions)
    2121             : {
    2122       28581 :     VALIDATE_POINTER1(hDriver, "GDALValidateCreationOptions", FALSE);
    2123             :     const char *pszOptionList =
    2124       28581 :         GDALDriver::FromHandle(hDriver)->GetMetadataItem(
    2125       28581 :             GDAL_DMD_CREATIONOPTIONLIST);
    2126       28581 :     CPLString osDriver;
    2127             :     osDriver.Printf("driver %s",
    2128       28581 :                     GDALDriver::FromHandle(hDriver)->GetDescription());
    2129       28581 :     bool bFoundOptionToRemove = false;
    2130       40943 :     for (const char *pszCO : cpl::Iterate(papszCreationOptions))
    2131             :     {
    2132       37122 :         for (const char *pszExcludedOptions :
    2133       49543 :              {"APPEND_SUBDATASET", "COPY_SRC_MDD", "SRC_MDD"})
    2134             :         {
    2135       37181 :             if (STARTS_WITH_CI(pszCO, pszExcludedOptions) &&
    2136          59 :                 pszCO[strlen(pszExcludedOptions)] == '=')
    2137             :             {
    2138          59 :                 bFoundOptionToRemove = true;
    2139          59 :                 break;
    2140             :             }
    2141             :         }
    2142       12421 :         if (bFoundOptionToRemove)
    2143          59 :             break;
    2144             :     }
    2145       28581 :     CSLConstList papszOptionsToValidate = papszCreationOptions;
    2146       28581 :     char **papszOptionsToFree = nullptr;
    2147       28581 :     if (bFoundOptionToRemove)
    2148             :     {
    2149         171 :         for (const char *pszCO : cpl::Iterate(papszCreationOptions))
    2150             :         {
    2151         112 :             bool bMatch = false;
    2152         189 :             for (const char *pszExcludedOptions :
    2153         301 :                  {"APPEND_SUBDATASET", "COPY_SRC_MDD", "SRC_MDD"})
    2154             :             {
    2155         254 :                 if (STARTS_WITH_CI(pszCO, pszExcludedOptions) &&
    2156          65 :                     pszCO[strlen(pszExcludedOptions)] == '=')
    2157             :                 {
    2158          65 :                     bMatch = true;
    2159          65 :                     break;
    2160             :                 }
    2161             :             }
    2162         112 :             if (!bMatch)
    2163          47 :                 papszOptionsToFree = CSLAddString(papszOptionsToFree, pszCO);
    2164             :         }
    2165          59 :         papszOptionsToValidate = papszOptionsToFree;
    2166             :     }
    2167             : 
    2168       28581 :     const bool bRet = CPL_TO_BOOL(GDALValidateOptions(
    2169             :         pszOptionList, papszOptionsToValidate, "creation option", osDriver));
    2170       28581 :     CSLDestroy(papszOptionsToFree);
    2171       28581 :     return bRet;
    2172             : }
    2173             : 
    2174             : /************************************************************************/
    2175             : /*                     GDALValidateOpenOptions()                        */
    2176             : /************************************************************************/
    2177             : 
    2178       42947 : int GDALValidateOpenOptions(GDALDriverH hDriver,
    2179             :                             const char *const *papszOpenOptions)
    2180             : {
    2181       42947 :     VALIDATE_POINTER1(hDriver, "GDALValidateOpenOptions", FALSE);
    2182             :     const char *pszOptionList =
    2183       42947 :         GDALDriver::FromHandle(hDriver)->GetMetadataItem(
    2184       42942 :             GDAL_DMD_OPENOPTIONLIST);
    2185       85875 :     CPLString osDriver;
    2186             :     osDriver.Printf("driver %s",
    2187       42933 :                     GDALDriver::FromHandle(hDriver)->GetDescription());
    2188       42929 :     return GDALValidateOptions(pszOptionList, papszOpenOptions, "open option",
    2189       42929 :                                osDriver);
    2190             : }
    2191             : 
    2192             : /************************************************************************/
    2193             : /*                           GDALValidateOptions()                      */
    2194             : /************************************************************************/
    2195             : 
    2196       80206 : int GDALValidateOptions(const char *pszOptionList,
    2197             :                         const char *const *papszOptionsToValidate,
    2198             :                         const char *pszErrorMessageOptionType,
    2199             :                         const char *pszErrorMessageContainerName)
    2200             : {
    2201       80206 :     if (papszOptionsToValidate == nullptr || *papszOptionsToValidate == nullptr)
    2202       68492 :         return TRUE;
    2203       11714 :     if (pszOptionList == nullptr)
    2204         139 :         return TRUE;
    2205             : 
    2206       11575 :     CPLXMLNode *psNode = CPLParseXMLString(pszOptionList);
    2207       11575 :     if (psNode == nullptr)
    2208             :     {
    2209           0 :         CPLError(CE_Warning, CPLE_AppDefined,
    2210             :                  "Could not parse %s list of %s. Assuming options are valid.",
    2211             :                  pszErrorMessageOptionType, pszErrorMessageContainerName);
    2212           0 :         return TRUE;
    2213             :     }
    2214             : 
    2215       11575 :     bool bRet = true;
    2216       31182 :     while (*papszOptionsToValidate)
    2217             :     {
    2218       19607 :         char *pszKey = nullptr;
    2219             :         const char *pszValue =
    2220       19607 :             CPLParseNameValue(*papszOptionsToValidate, &pszKey);
    2221       19607 :         if (pszKey == nullptr)
    2222             :         {
    2223           1 :             CPLError(CE_Warning, CPLE_NotSupported,
    2224             :                      "%s '%s' is not formatted with the key=value format",
    2225             :                      pszErrorMessageOptionType, *papszOptionsToValidate);
    2226           1 :             bRet = false;
    2227             : 
    2228           1 :             ++papszOptionsToValidate;
    2229         568 :             continue;
    2230             :         }
    2231             : 
    2232       19606 :         if (EQUAL(pszKey, "VALIDATE_OPEN_OPTIONS"))
    2233             :         {
    2234           0 :             ++papszOptionsToValidate;
    2235           0 :             CPLFree(pszKey);
    2236           0 :             continue;
    2237             :         }
    2238             : 
    2239             :         // Must we be forgiving in case of missing option ?
    2240       19606 :         bool bWarnIfMissingKey = true;
    2241       19606 :         if (pszKey[0] == '@')
    2242             :         {
    2243         557 :             bWarnIfMissingKey = false;
    2244         557 :             memmove(pszKey, pszKey + 1, strlen(pszKey + 1) + 1);
    2245             :         }
    2246             : 
    2247       19606 :         CPLXMLNode *psChildNode = psNode->psChild;
    2248      161659 :         while (psChildNode)
    2249             :         {
    2250      161092 :             if (EQUAL(psChildNode->pszValue, "OPTION"))
    2251             :             {
    2252             :                 const char *pszOptionName =
    2253      161092 :                     CPLGetXMLValue(psChildNode, "name", "");
    2254             :                 /* For option names terminated by wildcard (NITF BLOCKA option
    2255             :                  * names for example) */
    2256      161092 :                 if (strlen(pszOptionName) > 0 &&
    2257      161092 :                     pszOptionName[strlen(pszOptionName) - 1] == '*' &&
    2258         373 :                     EQUALN(pszOptionName, pszKey, strlen(pszOptionName) - 1))
    2259             :                 {
    2260         216 :                     break;
    2261             :                 }
    2262             : 
    2263             :                 /* For option names beginning by a wildcard */
    2264      160876 :                 if (pszOptionName[0] == '*' &&
    2265          57 :                     strlen(pszKey) > strlen(pszOptionName) &&
    2266           9 :                     EQUAL(pszKey + strlen(pszKey) - strlen(pszOptionName + 1),
    2267             :                           pszOptionName + 1))
    2268             :                 {
    2269           2 :                     break;
    2270             :                 }
    2271             : 
    2272             :                 // For options names with * in the middle
    2273      160874 :                 const char *pszStarInOptionName = strchr(pszOptionName, '*');
    2274      160874 :                 if (pszStarInOptionName &&
    2275         178 :                     pszStarInOptionName != pszOptionName &&
    2276             :                     pszStarInOptionName !=
    2277         178 :                         pszOptionName + strlen(pszOptionName) - 1 &&
    2278          21 :                     strlen(pszKey) > static_cast<size_t>(pszStarInOptionName -
    2279          12 :                                                          pszOptionName) &&
    2280          12 :                     EQUALN(pszKey, pszOptionName,
    2281             :                            static_cast<size_t>(pszStarInOptionName -
    2282          12 :                                                pszOptionName)) &&
    2283          12 :                     EQUAL(pszKey +
    2284             :                               static_cast<size_t>(pszStarInOptionName -
    2285             :                                                   pszOptionName) +
    2286             :                               1,
    2287             :                           pszStarInOptionName + 1))
    2288             :                 {
    2289           6 :                     break;
    2290             :                 }
    2291             : 
    2292      160868 :                 if (EQUAL(pszOptionName, pszKey))
    2293             :                 {
    2294       18811 :                     break;
    2295             :                 }
    2296      142057 :                 const char *pszAlias = CPLGetXMLValue(
    2297             :                     psChildNode, "alias",
    2298             :                     CPLGetXMLValue(psChildNode, "deprecated_alias", ""));
    2299      142057 :                 if (EQUAL(pszAlias, pszKey))
    2300             :                 {
    2301           4 :                     CPLDebug("GDAL",
    2302             :                              "Using deprecated alias '%s'. New name is '%s'",
    2303             :                              pszAlias, pszOptionName);
    2304           4 :                     break;
    2305             :                 }
    2306             :             }
    2307      142053 :             psChildNode = psChildNode->psNext;
    2308             :         }
    2309       19606 :         if (psChildNode == nullptr)
    2310             :         {
    2311         582 :             if (bWarnIfMissingKey &&
    2312          15 :                 (!EQUAL(pszErrorMessageOptionType, "open option") ||
    2313           0 :                  CPLFetchBool(papszOptionsToValidate, "VALIDATE_OPEN_OPTIONS",
    2314             :                               true)))
    2315             :             {
    2316          15 :                 CPLError(CE_Warning, CPLE_NotSupported,
    2317             :                          "%s does not support %s %s",
    2318             :                          pszErrorMessageContainerName,
    2319             :                          pszErrorMessageOptionType, pszKey);
    2320          15 :                 bRet = false;
    2321             :             }
    2322             : 
    2323         567 :             CPLFree(pszKey);
    2324         567 :             ++papszOptionsToValidate;
    2325         567 :             continue;
    2326             :         }
    2327             : 
    2328             : #ifdef DEBUG
    2329       19039 :         CPLXMLNode *psChildSubNode = psChildNode->psChild;
    2330      114654 :         while (psChildSubNode)
    2331             :         {
    2332       95615 :             if (psChildSubNode->eType == CXT_Attribute)
    2333             :             {
    2334       65615 :                 if (!(EQUAL(psChildSubNode->pszValue, "name") ||
    2335       46576 :                       EQUAL(psChildSubNode->pszValue, "alias") ||
    2336       46545 :                       EQUAL(psChildSubNode->pszValue, "deprecated_alias") ||
    2337       46508 :                       EQUAL(psChildSubNode->pszValue, "alt_config_option") ||
    2338       46475 :                       EQUAL(psChildSubNode->pszValue, "description") ||
    2339       29939 :                       EQUAL(psChildSubNode->pszValue, "type") ||
    2340       10900 :                       EQUAL(psChildSubNode->pszValue, "min") ||
    2341       10742 :                       EQUAL(psChildSubNode->pszValue, "max") ||
    2342       10505 :                       EQUAL(psChildSubNode->pszValue, "default") ||
    2343         978 :                       EQUAL(psChildSubNode->pszValue, "maxsize") ||
    2344         955 :                       EQUAL(psChildSubNode->pszValue, "required") ||
    2345         900 :                       EQUAL(psChildSubNode->pszValue, "scope")))
    2346             :                 {
    2347             :                     /* Driver error */
    2348           0 :                     CPLError(CE_Warning, CPLE_NotSupported,
    2349             :                              "%s : unhandled attribute '%s' for %s %s.",
    2350             :                              pszErrorMessageContainerName,
    2351             :                              psChildSubNode->pszValue, pszKey,
    2352             :                              pszErrorMessageOptionType);
    2353             :                 }
    2354             :             }
    2355       95615 :             psChildSubNode = psChildSubNode->psNext;
    2356             :         }
    2357             : #endif
    2358             : 
    2359       19039 :         const char *pszType = CPLGetXMLValue(psChildNode, "type", nullptr);
    2360       19039 :         const char *pszMin = CPLGetXMLValue(psChildNode, "min", nullptr);
    2361       19039 :         const char *pszMax = CPLGetXMLValue(psChildNode, "max", nullptr);
    2362       19039 :         if (pszType != nullptr)
    2363             :         {
    2364       19039 :             if (EQUAL(pszType, "INT") || EQUAL(pszType, "INTEGER"))
    2365             :             {
    2366        8346 :                 const char *pszValueIter = pszValue;
    2367       21187 :                 while (*pszValueIter)
    2368             :                 {
    2369       12843 :                     if (!((*pszValueIter >= '0' && *pszValueIter <= '9') ||
    2370          19 :                           *pszValueIter == '+' || *pszValueIter == '-'))
    2371             :                     {
    2372           2 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2373             :                                  "'%s' is an unexpected value for %s %s of "
    2374             :                                  "type int.",
    2375             :                                  pszValue, pszKey, pszErrorMessageOptionType);
    2376           2 :                         bRet = false;
    2377           2 :                         break;
    2378             :                     }
    2379       12841 :                     ++pszValueIter;
    2380             :                 }
    2381        8346 :                 if (*pszValueIter == '\0')
    2382             :                 {
    2383        8344 :                     if (pszMin && atoi(pszValue) < atoi(pszMin))
    2384             :                     {
    2385           5 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2386             :                                  "'%s' is an unexpected value for %s %s that "
    2387             :                                  "should be >= %s.",
    2388             :                                  pszValue, pszKey, pszErrorMessageOptionType,
    2389             :                                  pszMin);
    2390           5 :                         bRet = false;
    2391             :                     }
    2392        8344 :                     if (pszMax && atoi(pszValue) > atoi(pszMax))
    2393             :                     {
    2394          12 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2395             :                                  "'%s' is an unexpected value for %s %s that "
    2396             :                                  "should be <= %s.",
    2397             :                                  pszValue, pszKey, pszErrorMessageOptionType,
    2398             :                                  pszMax);
    2399          12 :                         bRet = false;
    2400             :                     }
    2401        8346 :                 }
    2402             :             }
    2403       10693 :             else if (EQUAL(pszType, "UNSIGNED INT"))
    2404             :             {
    2405           3 :                 const char *pszValueIter = pszValue;
    2406          10 :                 while (*pszValueIter)
    2407             :                 {
    2408           7 :                     if (!((*pszValueIter >= '0' && *pszValueIter <= '9') ||
    2409           0 :                           *pszValueIter == '+'))
    2410             :                     {
    2411           0 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2412             :                                  "'%s' is an unexpected value for %s %s of "
    2413             :                                  "type unsigned int.",
    2414             :                                  pszValue, pszKey, pszErrorMessageOptionType);
    2415           0 :                         bRet = false;
    2416           0 :                         break;
    2417             :                     }
    2418           7 :                     ++pszValueIter;
    2419             :                 }
    2420           3 :                 if (*pszValueIter == '\0')
    2421             :                 {
    2422           3 :                     if (pszMin && atoi(pszValue) < atoi(pszMin))
    2423             :                     {
    2424           0 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2425             :                                  "'%s' is an unexpected value for %s %s that "
    2426             :                                  "should be >= %s.",
    2427             :                                  pszValue, pszKey, pszErrorMessageOptionType,
    2428             :                                  pszMin);
    2429           0 :                         bRet = false;
    2430             :                     }
    2431           3 :                     if (pszMax && atoi(pszValue) > atoi(pszMax))
    2432             :                     {
    2433           0 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2434             :                                  "'%s' is an unexpected value for %s %s that "
    2435             :                                  "should be <= %s.",
    2436             :                                  pszValue, pszKey, pszErrorMessageOptionType,
    2437             :                                  pszMax);
    2438           0 :                         bRet = false;
    2439             :                     }
    2440             :                 }
    2441             :             }
    2442       10690 :             else if (EQUAL(pszType, "FLOAT"))
    2443             :             {
    2444         580 :                 char *endPtr = nullptr;
    2445         580 :                 double dfVal = CPLStrtod(pszValue, &endPtr);
    2446         580 :                 if (!(endPtr == nullptr || *endPtr == '\0'))
    2447             :                 {
    2448           0 :                     CPLError(
    2449             :                         CE_Warning, CPLE_NotSupported,
    2450             :                         "'%s' is an unexpected value for %s %s of type float.",
    2451             :                         pszValue, pszKey, pszErrorMessageOptionType);
    2452           0 :                     bRet = false;
    2453             :                 }
    2454             :                 else
    2455             :                 {
    2456         580 :                     if (pszMin && dfVal < CPLAtof(pszMin))
    2457             :                     {
    2458           2 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2459             :                                  "'%s' is an unexpected value for %s %s that "
    2460             :                                  "should be >= %s.",
    2461             :                                  pszValue, pszKey, pszErrorMessageOptionType,
    2462             :                                  pszMin);
    2463           2 :                         bRet = false;
    2464             :                     }
    2465         580 :                     if (pszMax && dfVal > CPLAtof(pszMax))
    2466             :                     {
    2467           0 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2468             :                                  "'%s' is an unexpected value for %s %s that "
    2469             :                                  "should be <= %s.",
    2470             :                                  pszValue, pszKey, pszErrorMessageOptionType,
    2471             :                                  pszMax);
    2472           0 :                         bRet = false;
    2473             :                     }
    2474             :                 }
    2475             :             }
    2476       10110 :             else if (EQUAL(pszType, "BOOLEAN"))
    2477             :             {
    2478        2371 :                 if (!(EQUAL(pszValue, "ON") || EQUAL(pszValue, "TRUE") ||
    2479        2329 :                       EQUAL(pszValue, "YES") || EQUAL(pszValue, "OFF") ||
    2480         387 :                       EQUAL(pszValue, "FALSE") || EQUAL(pszValue, "NO")))
    2481             :                 {
    2482           0 :                     CPLError(CE_Warning, CPLE_NotSupported,
    2483             :                              "'%s' is an unexpected value for %s %s of type "
    2484             :                              "boolean.",
    2485             :                              pszValue, pszKey, pszErrorMessageOptionType);
    2486           0 :                     bRet = false;
    2487             :                 }
    2488             :             }
    2489        7739 :             else if (EQUAL(pszType, "STRING-SELECT"))
    2490             :             {
    2491        4459 :                 bool bMatchFound = false;
    2492        4459 :                 CPLXMLNode *psStringSelect = psChildNode->psChild;
    2493       29464 :                 while (psStringSelect)
    2494             :                 {
    2495       29432 :                     if (psStringSelect->eType == CXT_Element &&
    2496       15537 :                         EQUAL(psStringSelect->pszValue, "Value"))
    2497             :                     {
    2498       15537 :                         CPLXMLNode *psOptionNode = psStringSelect->psChild;
    2499       26859 :                         while (psOptionNode)
    2500             :                         {
    2501       15749 :                             if (psOptionNode->eType == CXT_Text &&
    2502       15535 :                                 EQUAL(psOptionNode->pszValue, pszValue))
    2503             :                             {
    2504        4425 :                                 bMatchFound = true;
    2505        4425 :                                 break;
    2506             :                             }
    2507       11324 :                             if (psOptionNode->eType == CXT_Attribute &&
    2508         214 :                                 (EQUAL(psOptionNode->pszValue, "alias") ||
    2509          13 :                                  EQUAL(psOptionNode->pszValue,
    2510         201 :                                        "deprecated_alias")) &&
    2511         201 :                                 EQUAL(psOptionNode->psChild->pszValue,
    2512             :                                       pszValue))
    2513             :                             {
    2514           2 :                                 bMatchFound = true;
    2515           2 :                                 break;
    2516             :                             }
    2517       11322 :                             psOptionNode = psOptionNode->psNext;
    2518             :                         }
    2519       15537 :                         if (bMatchFound)
    2520        4427 :                             break;
    2521             :                     }
    2522       25005 :                     psStringSelect = psStringSelect->psNext;
    2523             :                 }
    2524        4459 :                 if (!bMatchFound)
    2525             :                 {
    2526          32 :                     CPLError(CE_Warning, CPLE_NotSupported,
    2527             :                              "'%s' is an unexpected value for %s %s of type "
    2528             :                              "string-select.",
    2529             :                              pszValue, pszKey, pszErrorMessageOptionType);
    2530          32 :                     bRet = false;
    2531             :                 }
    2532             :             }
    2533        3280 :             else if (EQUAL(pszType, "STRING"))
    2534             :             {
    2535             :                 const char *pszMaxSize =
    2536        3280 :                     CPLGetXMLValue(psChildNode, "maxsize", nullptr);
    2537        3280 :                 if (pszMaxSize != nullptr)
    2538             :                 {
    2539          23 :                     if (static_cast<int>(strlen(pszValue)) > atoi(pszMaxSize))
    2540             :                     {
    2541           1 :                         CPLError(CE_Warning, CPLE_NotSupported,
    2542             :                                  "'%s' is of size %d, whereas maximum size for "
    2543             :                                  "%s %s is %d.",
    2544           1 :                                  pszValue, static_cast<int>(strlen(pszValue)),
    2545             :                                  pszKey, pszErrorMessageOptionType,
    2546             :                                  atoi(pszMaxSize));
    2547           1 :                         bRet = false;
    2548             :                     }
    2549             :                 }
    2550             :             }
    2551             :             else
    2552             :             {
    2553             :                 /* Driver error */
    2554           0 :                 CPLError(CE_Warning, CPLE_NotSupported,
    2555             :                          "%s : type '%s' for %s %s is not recognized.",
    2556             :                          pszErrorMessageContainerName, pszType, pszKey,
    2557             :                          pszErrorMessageOptionType);
    2558             :             }
    2559             :         }
    2560             :         else
    2561             :         {
    2562             :             /* Driver error */
    2563           0 :             CPLError(CE_Warning, CPLE_NotSupported, "%s : no type for %s %s.",
    2564             :                      pszErrorMessageContainerName, pszKey,
    2565             :                      pszErrorMessageOptionType);
    2566             :         }
    2567       19039 :         CPLFree(pszKey);
    2568       19039 :         ++papszOptionsToValidate;
    2569             :     }
    2570             : 
    2571       11575 :     CPLDestroyXMLNode(psNode);
    2572       11575 :     return bRet ? TRUE : FALSE;
    2573             : }
    2574             : 
    2575             : /************************************************************************/
    2576             : /*                         GDALIdentifyDriver()                         */
    2577             : /************************************************************************/
    2578             : 
    2579             : /**
    2580             :  * \brief Identify the driver that can open a dataset.
    2581             :  *
    2582             :  * This function will try to identify the driver that can open the passed file
    2583             :  * name by invoking the Identify method of each registered GDALDriver in turn.
    2584             :  * The first driver that successfully identifies the file name will be returned.
    2585             :  * If all drivers fail then NULL is returned.
    2586             :  *
    2587             :  * In order to reduce the need for such searches to touch the operating system
    2588             :  * file system machinery, it is possible to give an optional list of files.
    2589             :  * This is the list of all files at the same level in the file system as the
    2590             :  * target file, including the target file. The filenames will not include any
    2591             :  * path components, and are essentially just the output of VSIReadDir() on the
    2592             :  * parent directory. If the target object does not have filesystem semantics
    2593             :  * then the file list should be NULL.
    2594             :  *
    2595             :  * @param pszFilename the name of the file to access.  In the case of
    2596             :  * exotic drivers this may not refer to a physical file, but instead contain
    2597             :  * information for the driver on how to access a dataset.
    2598             :  *
    2599             :  * @param papszFileList an array of strings, whose last element is the NULL
    2600             :  * pointer.  These strings are filenames that are auxiliary to the main
    2601             :  * filename. The passed value may be NULL.
    2602             :  *
    2603             :  * @return A GDALDriverH handle or NULL on failure.  For C++ applications
    2604             :  * this handle can be cast to a GDALDriver *.
    2605             :  */
    2606             : 
    2607       20385 : GDALDriverH CPL_STDCALL GDALIdentifyDriver(const char *pszFilename,
    2608             :                                            CSLConstList papszFileList)
    2609             : 
    2610             : {
    2611       20385 :     return GDALIdentifyDriverEx(pszFilename, 0, nullptr, papszFileList);
    2612             : }
    2613             : 
    2614             : /************************************************************************/
    2615             : /*                         GDALIdentifyDriverEx()                       */
    2616             : /************************************************************************/
    2617             : 
    2618             : /**
    2619             :  * \brief Identify the driver that can open a dataset.
    2620             :  *
    2621             :  * This function will try to identify the driver that can open the passed file
    2622             :  * name by invoking the Identify method of each registered GDALDriver in turn.
    2623             :  * The first driver that successfully identifies the file name will be returned.
    2624             :  * If all drivers fail then NULL is returned.
    2625             :  *
    2626             :  * In order to reduce the need for such searches to touch the operating system
    2627             :  * file system machinery, it is possible to give an optional list of files.
    2628             :  * This is the list of all files at the same level in the file system as the
    2629             :  * target file, including the target file. The filenames will not include any
    2630             :  * path components, and are essentially just the output of VSIReadDir() on the
    2631             :  * parent directory. If the target object does not have filesystem semantics
    2632             :  * then the file list should be NULL.
    2633             :  *
    2634             :  * @param pszFilename the name of the file to access.  In the case of
    2635             :  * exotic drivers this may not refer to a physical file, but instead contain
    2636             :  * information for the driver on how to access a dataset.
    2637             :  *
    2638             :  * @param nIdentifyFlags a combination of GDAL_OF_RASTER for raster drivers
    2639             :  * or GDAL_OF_VECTOR for vector drivers. If none of the value is specified,
    2640             :  * both kinds are implied.
    2641             :  *
    2642             :  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
    2643             :  * terminated list of strings with the driver short names that must be
    2644             :  * considered.
    2645             :  *
    2646             :  * @param papszFileList an array of strings, whose last element is the NULL
    2647             :  * pointer.  These strings are filenames that are auxiliary to the main
    2648             :  * filename. The passed value may be NULL.
    2649             :  *
    2650             :  * @return A GDALDriverH handle or NULL on failure.  For C++ applications
    2651             :  * this handle can be cast to a GDALDriver *.
    2652             :  *
    2653             :  * @since GDAL 2.2
    2654             :  */
    2655             : 
    2656       20431 : GDALDriverH CPL_STDCALL GDALIdentifyDriverEx(
    2657             :     const char *pszFilename, unsigned int nIdentifyFlags,
    2658             :     const char *const *papszAllowedDrivers, const char *const *papszFileList)
    2659             : {
    2660       20431 :     GDALDriverManager *poDM = GetGDALDriverManager();
    2661       20431 :     CPLAssert(nullptr != poDM);
    2662       40862 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly, papszFileList);
    2663             : 
    2664       40862 :     CPLErrorStateBackuper oBackuper;
    2665       20431 :     CPLErrorSetState(CE_None, CPLE_AppDefined, "");
    2666             : 
    2667       20431 :     const int nDriverCount = poDM->GetDriverCount();
    2668             : 
    2669             :     // First pass: only use drivers that have a pfnIdentify implementation.
    2670       40862 :     std::vector<GDALDriver *> apoSecondPassDrivers;
    2671     4638510 :     for (int iDriver = 0; iDriver < nDriverCount; ++iDriver)
    2672             :     {
    2673     4619080 :         GDALDriver *poDriver = poDM->GetDriver(iDriver);
    2674     4619720 :         if (papszAllowedDrivers != nullptr &&
    2675         642 :             CSLFindString(papszAllowedDrivers,
    2676             :                           GDALGetDriverShortName(poDriver)) == -1)
    2677             :         {
    2678     1048730 :             continue;
    2679             :         }
    2680             : 
    2681     4619440 :         VALIDATE_POINTER1(poDriver, "GDALIdentifyDriver", nullptr);
    2682             : 
    2683     4618440 :         if (poDriver->pfnIdentify == nullptr &&
    2684     1044190 :             poDriver->pfnIdentifyEx == nullptr)
    2685             :         {
    2686     1044190 :             continue;
    2687             :         }
    2688             : 
    2689     3574250 :         if (papszAllowedDrivers != nullptr &&
    2690           3 :             CSLFindString(papszAllowedDrivers,
    2691             :                           GDALGetDriverShortName(poDriver)) == -1)
    2692           0 :             continue;
    2693     7148910 :         if ((nIdentifyFlags & GDAL_OF_RASTER) != 0 &&
    2694     3574580 :             (nIdentifyFlags & GDAL_OF_VECTOR) == 0 &&
    2695         326 :             poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
    2696          79 :             continue;
    2697     7157120 :         if ((nIdentifyFlags & GDAL_OF_VECTOR) != 0 &&
    2698     3579130 :             (nIdentifyFlags & GDAL_OF_RASTER) == 0 &&
    2699        4957 :             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
    2700        3823 :             continue;
    2701             : 
    2702     3570350 :         if (poDriver->pfnIdentifyEx)
    2703             :         {
    2704           0 :             if (poDriver->pfnIdentifyEx(poDriver, &oOpenInfo) > 0)
    2705           0 :                 return poDriver;
    2706             :         }
    2707             :         else
    2708             :         {
    2709     3570350 :             const int nIdentifyRes = poDriver->pfnIdentify(&oOpenInfo);
    2710     3570350 :             if (nIdentifyRes > 0)
    2711         999 :                 return poDriver;
    2712     3588920 :             if (nIdentifyRes < 0 &&
    2713       19573 :                 poDriver->GetMetadataItem("IS_NON_LOADED_PLUGIN"))
    2714             :             {
    2715             :                 // Not loaded plugin
    2716           6 :                 apoSecondPassDrivers.push_back(poDriver);
    2717             :             }
    2718             :         }
    2719             :     }
    2720             : 
    2721             :     // second pass: try loading plugin drivers
    2722       19435 :     for (auto poDriver : apoSecondPassDrivers)
    2723             :     {
    2724             :         // Force plugin driver loading
    2725           4 :         poDriver->GetMetadata();
    2726           4 :         if (poDriver->pfnIdentify(&oOpenInfo) > 0)
    2727           1 :             return poDriver;
    2728             :     }
    2729             : 
    2730             :     // third pass: slow method.
    2731     4562630 :     for (int iDriver = 0; iDriver < nDriverCount; ++iDriver)
    2732             :     {
    2733     4543220 :         GDALDriver *poDriver = poDM->GetDriver(iDriver);
    2734     4543690 :         if (papszAllowedDrivers != nullptr &&
    2735         467 :             CSLFindString(papszAllowedDrivers,
    2736             :                           GDALGetDriverShortName(poDriver)) == -1)
    2737             :         {
    2738         465 :             continue;
    2739             :         }
    2740             : 
    2741     4542760 :         VALIDATE_POINTER1(poDriver, "GDALIdentifyDriver", nullptr);
    2742             : 
    2743     9085820 :         if ((nIdentifyFlags & GDAL_OF_RASTER) != 0 &&
    2744     4542990 :             (nIdentifyFlags & GDAL_OF_VECTOR) == 0 &&
    2745         233 :             poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr)
    2746          73 :             continue;
    2747     9088000 :         if ((nIdentifyFlags & GDAL_OF_VECTOR) != 0 &&
    2748     4544320 :             (nIdentifyFlags & GDAL_OF_RASTER) == 0 &&
    2749        1633 :             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr)
    2750        1002 :             continue;
    2751             : 
    2752     4541680 :         if (poDriver->pfnIdentifyEx != nullptr)
    2753             :         {
    2754           0 :             if (poDriver->pfnIdentifyEx(poDriver, &oOpenInfo) == 0)
    2755           0 :                 continue;
    2756             :         }
    2757     4541680 :         else if (poDriver->pfnIdentify != nullptr)
    2758             :         {
    2759     3514260 :             if (poDriver->pfnIdentify(&oOpenInfo) == 0)
    2760     3494790 :                 continue;
    2761             :         }
    2762             : 
    2763             :         GDALDataset *poDS;
    2764     1046890 :         if (poDriver->pfnOpen != nullptr)
    2765             :         {
    2766      930395 :             poDS = poDriver->pfnOpen(&oOpenInfo);
    2767      930395 :             if (poDS != nullptr)
    2768             :             {
    2769          20 :                 delete poDS;
    2770          20 :                 return GDALDriver::ToHandle(poDriver);
    2771             :             }
    2772             : 
    2773      930375 :             if (CPLGetLastErrorType() != CE_None)
    2774           0 :                 return nullptr;
    2775             :         }
    2776      116495 :         else if (poDriver->pfnOpenWithDriverArg != nullptr)
    2777             :         {
    2778       77658 :             poDS = poDriver->pfnOpenWithDriverArg(poDriver, &oOpenInfo);
    2779       77658 :             if (poDS != nullptr)
    2780             :             {
    2781           0 :                 delete poDS;
    2782           0 :                 return GDALDriver::ToHandle(poDriver);
    2783             :             }
    2784             : 
    2785       77658 :             if (CPLGetLastErrorType() != CE_None)
    2786           0 :                 return nullptr;
    2787             :         }
    2788             :     }
    2789             : 
    2790       19411 :     return nullptr;
    2791             : }
    2792             : 
    2793             : /************************************************************************/
    2794             : /*                          SetMetadataItem()                           */
    2795             : /************************************************************************/
    2796             : 
    2797     3006470 : CPLErr GDALDriver::SetMetadataItem(const char *pszName, const char *pszValue,
    2798             :                                    const char *pszDomain)
    2799             : 
    2800             : {
    2801     3006470 :     if (pszDomain == nullptr || pszDomain[0] == '\0')
    2802             :     {
    2803             :         /* Automatically sets GDAL_DMD_EXTENSIONS from GDAL_DMD_EXTENSION */
    2804     3148470 :         if (EQUAL(pszName, GDAL_DMD_EXTENSION) &&
    2805      142007 :             GDALMajorObject::GetMetadataItem(GDAL_DMD_EXTENSIONS) == nullptr)
    2806             :         {
    2807      142007 :             GDALMajorObject::SetMetadataItem(GDAL_DMD_EXTENSIONS, pszValue);
    2808             :         }
    2809             :         /* and vice-versa if there is a single extension in GDAL_DMD_EXTENSIONS */
    2810     5780480 :         else if (EQUAL(pszName, GDAL_DMD_EXTENSIONS) &&
    2811     2868130 :                  strchr(pszValue, ' ') == nullptr &&
    2812        3666 :                  GDALMajorObject::GetMetadataItem(GDAL_DMD_EXTENSION) ==
    2813             :                      nullptr)
    2814             :         {
    2815        3666 :             GDALMajorObject::SetMetadataItem(GDAL_DMD_EXTENSION, pszValue);
    2816             :         }
    2817             :     }
    2818     3006470 :     return GDALMajorObject::SetMetadataItem(pszName, pszValue, pszDomain);
    2819             : }
    2820             : 
    2821             : /************************************************************************/
    2822             : /*                   DoesDriverHandleExtension()                        */
    2823             : /************************************************************************/
    2824             : 
    2825      107280 : static bool DoesDriverHandleExtension(GDALDriverH hDriver, const char *pszExt)
    2826             : {
    2827      107280 :     bool bRet = false;
    2828             :     const char *pszDriverExtensions =
    2829      107280 :         GDALGetMetadataItem(hDriver, GDAL_DMD_EXTENSIONS, nullptr);
    2830      107280 :     if (pszDriverExtensions)
    2831             :     {
    2832      168966 :         const CPLStringList aosTokens(CSLTokenizeString(pszDriverExtensions));
    2833       84483 :         const int nTokens = aosTokens.size();
    2834      190259 :         for (int j = 0; j < nTokens; ++j)
    2835             :         {
    2836      107965 :             if (EQUAL(pszExt, aosTokens[j]))
    2837             :             {
    2838        2189 :                 bRet = true;
    2839        2189 :                 break;
    2840             :             }
    2841             :         }
    2842             :     }
    2843      107280 :     return bRet;
    2844             : }
    2845             : 
    2846             : /************************************************************************/
    2847             : /*                  GDALGetOutputDriversForDatasetName()                */
    2848             : /************************************************************************/
    2849             : 
    2850             : /** Return a list of driver short names that are likely candidates for the
    2851             :  * provided output file name.
    2852             :  *
    2853             :  * @param pszDestDataset Output dataset name (might not exist).
    2854             :  * @param nFlagRasterVector GDAL_OF_RASTER, GDAL_OF_VECTOR or
    2855             :  *                          binary-or'ed combination of both
    2856             :  * @param bSingleMatch Whether a single match is desired, that is to say the
    2857             :  *                     returned list will contain at most one item, which will
    2858             :  *                     be the first driver in the order they are registered to
    2859             :  *                     match the output dataset name. Note that in this mode, if
    2860             :  *                     nFlagRasterVector==GDAL_OF_RASTER and pszDestDataset has
    2861             :  *                     no extension, GTiff will be selected.
    2862             :  * @param bEmitWarning Whether a warning should be emitted when bSingleMatch is
    2863             :  *                     true and there are more than 2 candidates.
    2864             :  * @return NULL terminated list of driver short names.
    2865             :  * To be freed with CSLDestroy()
    2866             :  * @since 3.9
    2867             :  */
    2868        1346 : char **GDALGetOutputDriversForDatasetName(const char *pszDestDataset,
    2869             :                                           int nFlagRasterVector,
    2870             :                                           bool bSingleMatch, bool bEmitWarning)
    2871             : {
    2872        2692 :     CPLStringList aosDriverNames;
    2873             : 
    2874        2692 :     std::string osExt = CPLGetExtension(pszDestDataset);
    2875        1346 :     if (EQUAL(osExt.c_str(), "zip"))
    2876             :     {
    2877           2 :         const CPLString osLower(CPLString(pszDestDataset).tolower());
    2878           1 :         if (osLower.endsWith(".shp.zip"))
    2879             :         {
    2880           1 :             osExt = "shp.zip";
    2881             :         }
    2882           0 :         else if (osLower.endsWith(".gpkg.zip"))
    2883             :         {
    2884           0 :             osExt = "gpkg.zip";
    2885             :         }
    2886             :     }
    2887             : 
    2888        1346 :     const int nDriverCount = GDALGetDriverCount();
    2889      315939 :     for (int i = 0; i < nDriverCount; i++)
    2890             :     {
    2891      314593 :         GDALDriverH hDriver = GDALGetDriver(i);
    2892      314593 :         bool bOk = false;
    2893      314593 :         if ((GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, nullptr) !=
    2894      177302 :                  nullptr ||
    2895      177302 :              GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY, nullptr) !=
    2896      629186 :                  nullptr) &&
    2897      180363 :             (((nFlagRasterVector & GDAL_OF_RASTER) &&
    2898      138019 :               GDALGetMetadataItem(hDriver, GDAL_DCAP_RASTER, nullptr) !=
    2899       89724 :                   nullptr) ||
    2900       89724 :              ((nFlagRasterVector & GDAL_OF_VECTOR) &&
    2901       42344 :               GDALGetMetadataItem(hDriver, GDAL_DCAP_VECTOR, nullptr) !=
    2902             :                   nullptr)))
    2903             :         {
    2904      109283 :             bOk = true;
    2905             :         }
    2906      205310 :         else if (GDALGetMetadataItem(hDriver, GDAL_DCAP_VECTOR_TRANSLATE_FROM,
    2907      206340 :                                      nullptr) &&
    2908        1030 :                  (nFlagRasterVector & GDAL_OF_VECTOR) != 0)
    2909             :         {
    2910           0 :             bOk = true;
    2911             :         }
    2912      314593 :         if (bOk)
    2913             :         {
    2914      216563 :             if (!osExt.empty() &&
    2915      107280 :                 DoesDriverHandleExtension(hDriver, osExt.c_str()))
    2916             :             {
    2917        2189 :                 aosDriverNames.AddString(GDALGetDriverShortName(hDriver));
    2918             :             }
    2919             :             else
    2920             :             {
    2921      107094 :                 const char *pszPrefix = GDALGetMetadataItem(
    2922             :                     hDriver, GDAL_DMD_CONNECTION_PREFIX, nullptr);
    2923      107094 :                 if (pszPrefix && STARTS_WITH_CI(pszDestDataset, pszPrefix))
    2924             :                 {
    2925           5 :                     aosDriverNames.AddString(GDALGetDriverShortName(hDriver));
    2926             :                 }
    2927             :             }
    2928             :         }
    2929             :     }
    2930             : 
    2931             :     // GMT is registered before netCDF for opening reasons, but we want
    2932             :     // netCDF to be used by default for output.
    2933        1348 :     if (EQUAL(osExt.c_str(), "nc") && aosDriverNames.size() == 2 &&
    2934        1348 :         EQUAL(aosDriverNames[0], "GMT") && EQUAL(aosDriverNames[1], "netCDF"))
    2935             :     {
    2936           0 :         aosDriverNames.Clear();
    2937           0 :         aosDriverNames.AddString("netCDF");
    2938           0 :         aosDriverNames.AddString("GMT");
    2939             :     }
    2940             : 
    2941        1346 :     if (bSingleMatch)
    2942             :     {
    2943        1030 :         if (nFlagRasterVector == GDAL_OF_RASTER)
    2944             :         {
    2945        1030 :             if (aosDriverNames.empty())
    2946             :             {
    2947           6 :                 if (osExt.empty())
    2948             :                 {
    2949           6 :                     aosDriverNames.AddString("GTiff");
    2950             :                 }
    2951             :             }
    2952        1024 :             else if (aosDriverNames.size() >= 2)
    2953             :             {
    2954        1746 :                 if (bEmitWarning && !(EQUAL(aosDriverNames[0], "GTiff") &&
    2955         873 :                                       EQUAL(aosDriverNames[1], "COG")))
    2956             :                 {
    2957           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
    2958             :                              "Several drivers matching %s extension. Using %s",
    2959             :                              osExt.c_str(), aosDriverNames[0]);
    2960             :                 }
    2961        1746 :                 const std::string osDrvName = aosDriverNames[0];
    2962         873 :                 aosDriverNames.Clear();
    2963         873 :                 aosDriverNames.AddString(osDrvName.c_str());
    2964             :             }
    2965             :         }
    2966           0 :         else if (aosDriverNames.size() >= 2)
    2967             :         {
    2968           0 :             if (bEmitWarning)
    2969             :             {
    2970           0 :                 CPLError(CE_Warning, CPLE_AppDefined,
    2971             :                          "Several drivers matching %s extension. Using %s",
    2972             :                          osExt.c_str(), aosDriverNames[0]);
    2973             :             }
    2974           0 :             const std::string osDrvName = aosDriverNames[0];
    2975           0 :             aosDriverNames.Clear();
    2976           0 :             aosDriverNames.AddString(osDrvName.c_str());
    2977             :         }
    2978             :     }
    2979             : 
    2980        2692 :     return aosDriverNames.StealList();
    2981             : }

Generated by: LCOV version 1.14