Skip to content

Commit db0baa7

Browse files
committed
GDALOpenEx(): make it possible to exclude driver(s) by prefixing their name with dash in the allowed driver list
1 parent a8d565e commit db0baa7

File tree

4 files changed

+82
-19
lines changed

4 files changed

+82
-19
lines changed

autotest/gcore/basic_test.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,3 +1191,22 @@ def test_basic_GetDataTypeByName():
11911191

11921192
# For now, to avoid breaking backwards compatibility
11931193
assert gdal.GetDataTypeName(gdal.GDT_UInt8) == "Byte"
1194+
1195+
1196+
@gdaltest.enable_exceptions()
1197+
def test_basic_exclude_driver_at_open_time():
1198+
1199+
if gdal.GetDriverByName("LIBERTIFF"):
1200+
ds = gdal.OpenEx(
1201+
"data/gtiff/non_square_pixels.tif",
1202+
gdal.OF_RASTER,
1203+
allowed_drivers=["-GTiff", "-idonotexist"],
1204+
)
1205+
assert ds.GetDriver().GetDescription() == "LIBERTIFF"
1206+
1207+
with pytest.raises(Exception, match="not recognized"):
1208+
gdal.OpenEx(
1209+
"data/gtiff/non_square_pixels.tif",
1210+
gdal.OF_RASTER | gdal.OF_VERBOSE_ERROR,
1211+
allowed_drivers=["-GTiff", "-LIBERTIFF"],
1212+
)

gcore/gdaldataset.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4019,6 +4019,8 @@ static GDALDataset *GetSharedDS(const char *pszFilename,
40194019
* @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
40204020
* terminated list of strings with the driver short names that must be
40214021
* considered.
4022+
* Starting with GDAL 3.13, a string starting with the dash (-) character
4023+
* followed by the driver short name can be used to exclude a driver.
40224024
*
40234025
* @param papszOpenOptions NULL, or a NULL terminated list of strings with open
40244026
* options passed to candidate drivers. An option exists for all drivers,
@@ -4150,6 +4152,8 @@ GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename,
41504152
* @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
41514153
* terminated list of strings with the driver short names that must be
41524154
* considered.
4155+
* Starting with GDAL 3.13, a string starting with the dash (-) character
4156+
* followed by the driver short name can be used to exclude a driver.
41534157
*
41544158
* @param papszOpenOptions NULL, or a NULL terminated list of strings with open
41554159
* options passed to candidate drivers. An option exists for all drivers,
@@ -4264,11 +4268,33 @@ GDALDataset::Open(GDALOpenInfo *poOpenInfo,
42644268
GDALDriver *poDriver =
42654269
iPass == 1 ? poDM->GetDriver(iDriver, /*bIncludeHidden=*/true)
42664270
: apoSecondPassDrivers[iDriver];
4267-
if (papszAllowedDrivers != nullptr &&
4268-
CSLFindString(papszAllowedDrivers,
4269-
GDALGetDriverShortName(poDriver)) == -1)
4270-
{
4271-
continue;
4271+
const char *pszDriverName = GDALGetDriverShortName(poDriver);
4272+
if (pszDriverName && papszAllowedDrivers)
4273+
{
4274+
bool bDriverMatchedPositively = false;
4275+
bool bDriverMatchedNegatively = false;
4276+
bool bOnlyExcludedDrivers = true;
4277+
for (const char *pszAllowedDriver :
4278+
cpl::Iterate(papszAllowedDrivers))
4279+
{
4280+
if (pszAllowedDriver[0] != '-')
4281+
bOnlyExcludedDrivers = false;
4282+
if (EQUAL(pszAllowedDriver, pszDriverName))
4283+
{
4284+
bDriverMatchedPositively = true;
4285+
}
4286+
else if (pszAllowedDriver[0] == '-' &&
4287+
EQUAL(pszAllowedDriver + 1, pszDriverName))
4288+
{
4289+
bDriverMatchedNegatively = true;
4290+
break;
4291+
}
4292+
}
4293+
if ((!bDriverMatchedPositively && !bOnlyExcludedDrivers) ||
4294+
bDriverMatchedNegatively)
4295+
{
4296+
continue;
4297+
}
42724298
}
42734299

42744300
if (poDriver->GetMetadataItem(GDAL_DCAP_OPEN) == nullptr)

gcore/gdaldefaultoverviews.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,11 +375,14 @@ void GDALDefaultOverviews::OverviewScan()
375375
osOvrFilename = pszProxyOvrFilename;
376376
}
377377

378+
// Exclude TILEDB because reading from /vsis3/ can be really slow
379+
const char *const apszAllowedDrivers[] = {"-TILEDB", nullptr};
378380
CPLPushErrorHandler(CPLQuietErrorHandler);
379381
poODS = GDALDataset::Open(
380382
osOvrFilename,
381383
GDAL_OF_RASTER |
382-
(poDS->GetAccess() == GA_Update ? GDAL_OF_UPDATE : 0));
384+
(poDS->GetAccess() == GA_Update ? GDAL_OF_UPDATE : 0),
385+
apszAllowedDrivers);
383386
CPLPopErrorHandler();
384387
}
385388
}

gcore/gdaldrivermanager.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ GDALDriverH CPL_STDCALL GDALGetDriver(int iDriver)
484484
*
485485
* @param poDriver the driver to register.
486486
*
487-
* @return the index of the new installed driver.
487+
* @return the index of the new installed driver, or -1 in case of error
488488
*/
489489

490490
int GDALDriverManager::RegisterDriver(GDALDriver *poDriver)
@@ -496,12 +496,29 @@ int GDALDriverManager::RegisterDriver(GDALDriver *poDriver, bool bHidden)
496496
{
497497
CPLMutexHolderD(&hDMMutex);
498498

499+
const char *pszDriverName = poDriver->GetDescription();
500+
if (pszDriverName[0] == 0)
501+
{
502+
CPLError(CE_Failure, CPLE_AppDefined,
503+
"Cannot register driver with empty name");
504+
return -1;
505+
}
506+
if (pszDriverName[0] == '-')
507+
{
508+
// Because GDALDataset::Open() considers that strings in the allowed
509+
// drivers list starting with dash mean to exclude a driver.
510+
CPLError(
511+
CE_Failure, CPLE_AppDefined,
512+
"Cannot register driver whose name starts with a dash character");
513+
return -1;
514+
}
515+
499516
/* -------------------------------------------------------------------- */
500517
/* If it is already registered, just return the existing */
501518
/* index. */
502519
/* -------------------------------------------------------------------- */
503520
if (!m_bInDeferredDriverLoading &&
504-
GetDriverByName_unlocked(poDriver->GetDescription()) != nullptr)
521+
GetDriverByName_unlocked(pszDriverName) != nullptr)
505522
{
506523
for (int i = 0; i < nDrivers; ++i)
507524
{
@@ -536,39 +553,38 @@ int GDALDriverManager::RegisterDriver(GDALDriver *poDriver, bool bHidden)
536553
poDriver->GetMetadataItem(GDAL_DCAP_GNM) == nullptr)
537554
{
538555
CPLDebug("GDAL", "Assuming DCAP_RASTER for driver %s. Please fix it.",
539-
poDriver->GetDescription());
556+
pszDriverName);
540557
poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
541558
}
542559

543560
if (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) != nullptr &&
544561
poDriver->pfnIdentify == nullptr &&
545562
poDriver->pfnIdentifyEx == nullptr &&
546-
!STARTS_WITH_CI(poDriver->GetDescription(), "Interlis"))
563+
!STARTS_WITH_CI(pszDriverName, "Interlis"))
547564
{
548565
CPLDebug("GDAL",
549566
"Driver %s that defines GDAL_DMD_OPENOPTIONLIST must also "
550567
"implement Identify(), so that it can be used",
551-
poDriver->GetDescription());
568+
pszDriverName);
552569
}
553570

554571
if (poDriver->pfnVectorTranslateFrom != nullptr)
555572
poDriver->SetMetadataItem(GDAL_DCAP_VECTOR_TRANSLATE_FROM, "YES");
556573

557574
if (m_bInDeferredDriverLoading &&
558-
cpl::contains(oMapNameToDrivers,
559-
CPLString(poDriver->GetDescription()).toupper()))
575+
cpl::contains(oMapNameToDrivers, CPLString(pszDriverName).toupper()))
560576
{
561-
if (cpl::contains(m_oMapRealDrivers, poDriver->GetDescription()))
577+
if (cpl::contains(m_oMapRealDrivers, pszDriverName))
562578
{
563579
CPLError(
564580
CE_Failure, CPLE_AppDefined,
565581
"RegisterDriver() in m_bInDeferredDriverLoading: %s already "
566582
"registered!",
567-
poDriver->GetDescription());
583+
pszDriverName);
568584
delete poDriver;
569585
return -1;
570586
}
571-
m_oMapRealDrivers[poDriver->GetDescription()] =
587+
m_oMapRealDrivers[pszDriverName] =
572588
std::unique_ptr<GDALDriver>(poDriver);
573589
return -1;
574590
}
@@ -592,10 +608,9 @@ int GDALDriverManager::RegisterDriver(GDALDriver *poDriver, bool bHidden)
592608
papoDrivers[nDrivers] = poDriver;
593609
++nDrivers;
594610

595-
oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] =
596-
poDriver;
611+
oMapNameToDrivers[CPLString(pszDriverName).toupper()] = poDriver;
597612

598-
if (EQUAL(poDriver->GetDescription(), "MEM") &&
613+
if (EQUAL(pszDriverName, "MEM") &&
599614
oMapNameToDrivers.find("MEMORY") == oMapNameToDrivers.end())
600615
{
601616
// Instantiate a Memory driver, that is the same as the MEM one,

0 commit comments

Comments
 (0)