diff --git a/autotest/ogr/ogr_dgn.py b/autotest/ogr/ogr_dgn.py index 4ee9fdfd748d..8a67c004b348 100755 --- a/autotest/ogr/ogr_dgn.py +++ b/autotest/ogr/ogr_dgn.py @@ -30,7 +30,7 @@ import ogrtest import pytest -from osgeo import ogr +from osgeo import gdal, ogr pytestmark = pytest.mark.require_driver("DGN") @@ -293,3 +293,23 @@ def test_ogr_dgn_online_1(): wkt = "LINESTRING (82.9999500717185 23.2084166997284,83.0007450788903 23.2084495986816,83.00081490524 23.2068095339824,82.9999503769036 23.2067737968078)" ogrtest.check_feature_geometry(feat, wkt) + + +############################################################################### +# Test opening a (not supported by this driver) DGNv8 file + + +def test_ogr_dgn_open_dgnv8_not_supported(): + + dgnv8_drv = gdal.GetDriverByName("DGNv8") + if dgnv8_drv: + dgnv8_drv.Deregister() + try: + with pytest.raises( + Exception, + match="recognized as a DGNv8 dataset, but the DGNv8 driver is not available in this GDAL build", + ): + ogr.Open("data/dgnv8/test_dgnv8.dgn") + finally: + if dgnv8_drv: + dgnv8_drv.Register() diff --git a/gcore/gdal.h b/gcore/gdal.h index 8ce27a5a2431..621f04c581db 100644 --- a/gcore/gdal.h +++ b/gcore/gdal.h @@ -1013,6 +1013,12 @@ GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared(const char *, GDALAccess) #define GDAL_OF_BLOCK_ACCESS_MASK 0x300 #endif +#ifndef DOXYGEN_SKIP +/** Set by GDALOpenEx() to indicate to Identify() method that they are called + * from it */ +#define GDAL_OF_FROM_GDALOPEN 0x400 +#endif + GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenEx( const char *pszFilename, unsigned int nOpenFlags, const char *const *papszAllowedDrivers, const char *const *papszOpenOptions, diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp index c69266fb2ced..e999cda3db56 100644 --- a/gcore/gdaldataset.cpp +++ b/gcore/gdaldataset.cpp @@ -3614,6 +3614,7 @@ GDALDatasetH CPL_STDCALL GDALOpenEx(const char *pszFilename, } oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned; + oOpenInfo.nOpenFlags |= GDAL_OF_FROM_GDALOPEN; #ifdef OGRAPISPY_ENABLED const bool bUpdate = (nOpenFlags & GDAL_OF_UPDATE) != 0; diff --git a/gcore/gdaldriver.cpp b/gcore/gdaldriver.cpp index 4cda88e7bc09..db79d1e18a3a 100644 --- a/gcore/gdaldriver.cpp +++ b/gcore/gdaldriver.cpp @@ -122,7 +122,7 @@ GDALDataset *GDALDriver::Open(GDALOpenInfo *poOpenInfo, bool bSetOpenOptions) if (poDS) { - poDS->nOpenFlags = poOpenInfo->nOpenFlags; + poDS->nOpenFlags = poOpenInfo->nOpenFlags & ~GDAL_OF_FROM_GDALOPEN; if (strlen(poDS->GetDescription()) == 0) poDS->SetDescription(poOpenInfo->pszFilename); diff --git a/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp b/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp index 7cd67388f03c..875e07b833f9 100644 --- a/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp +++ b/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp @@ -36,8 +36,32 @@ static int OGRDGNDriverIdentify(GDALOpenInfo *poOpenInfo) { - return poOpenInfo->fpL != nullptr && poOpenInfo->nHeaderBytes >= 512 && - DGNTestOpen(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes); + if (poOpenInfo->fpL != nullptr && poOpenInfo->nHeaderBytes >= 512 && + DGNTestOpen(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes)) + { + return TRUE; + } + + // Is this is a DGNv8 file ? If so, and if the DGNV8 driver is not + // available, and we are called from GDALError(), emit an explicit + // error. + VSIStatBuf sStat; + if ((poOpenInfo->nOpenFlags & GDAL_OF_FROM_GDALOPEN) != 0 && + poOpenInfo->papszAllowedDrivers == nullptr && + poOpenInfo->fpL != nullptr && poOpenInfo->nHeaderBytes >= 512 && + memcmp(poOpenInfo->pabyHeader, "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1", 8) == + 0 && + EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "DGN") && + VSIStat(poOpenInfo->pszFilename, &sStat) == 0 && + GDALGetDriverByName("DGNV8") == nullptr) + { + CPLError(CE_Failure, CPLE_AppDefined, + "`%s' recognized as a DGNv8 dataset, but the DGNv8 driver is " + "not available in this GDAL build. Consult " + "https://gdal.org/drivers/vector/dgnv8.html", + poOpenInfo->pszFilename); + } + return FALSE; } /************************************************************************/