Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: OpenGIS Simple Features Reference Implementation 4 : * Purpose: Implements Open FileGDB OGR driver. 5 : * Author: Even Rouault, <even dot rouault at spatialys.com> 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "cpl_port.h" 14 : #include "ogr_openfilegdb.h" 15 : #include "ogropenfilegdbdrivercore.h" 16 : 17 : #include <cstddef> 18 : #include <cstring> 19 : 20 : #include "cpl_conv.h" 21 : #include "cpl_vsi.h" 22 : #include "gdal.h" 23 : #include "gdal_priv.h" 24 : #include "ogr_core.h" 25 : 26 : // g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp 27 : // -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts 28 : // -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/openfilegdb -L. -lgdal 29 : 30 : extern "C" void RegisterOGROpenFileGDB(); 31 : 32 : /************************************************************************/ 33 : /* Open() */ 34 : /************************************************************************/ 35 : 36 606 : static GDALDataset *OGROpenFileGDBDriverOpen(GDALOpenInfo *poOpenInfo) 37 : 38 : { 39 606 : const char *pszFilename = poOpenInfo->pszFilename; 40 606 : if (OGROpenFileGDBDriverIdentify(poOpenInfo, pszFilename) == 41 : GDAL_IDENTIFY_FALSE) 42 0 : return nullptr; 43 : 44 : #ifdef DEBUG 45 : /* For AFL, so that .cur_input is detected as the archive filename */ 46 1326 : if (poOpenInfo->fpL != nullptr && 47 720 : !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") && 48 114 : EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input")) 49 : { 50 : GDALOpenInfo oOpenInfo( 51 2 : (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(), 52 3 : poOpenInfo->nOpenFlags); 53 1 : oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions; 54 1 : return OGROpenFileGDBDriverOpen(&oOpenInfo); 55 : } 56 : #endif 57 : 58 1210 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>(); 59 605 : bool bRetryFileGDB = false; 60 605 : if (poDS->Open(poOpenInfo, bRetryFileGDB)) 61 : { 62 543 : if (poDS->GetSubdatasets().size() == 2) 63 : { 64 : // If there is a single raster dataset, open it right away. 65 : GDALOpenInfo oOpenInfo( 66 7 : poDS->GetSubdatasets().FetchNameValue("SUBDATASET_1_NAME"), 67 21 : poOpenInfo->nOpenFlags); 68 7 : poDS = std::make_unique<OGROpenFileGDBDataSource>(); 69 7 : if (poDS->Open(&oOpenInfo, bRetryFileGDB)) 70 : { 71 7 : poDS->SetDescription(poOpenInfo->pszFilename); 72 : } 73 : else 74 : { 75 0 : poDS.reset(); 76 : } 77 : } 78 543 : return poDS.release(); 79 : } 80 62 : else if (bRetryFileGDB) 81 : { 82 2 : auto poDriver = GetGDALDriverManager()->GetDriverByName("FileGDB"); 83 2 : if (poDriver) 84 : { 85 4 : GDALOpenInfo oOpenInfo(pszFilename, poOpenInfo->nOpenFlags); 86 4 : CPLStringList aosOpenOptions; 87 2 : aosOpenOptions.SetNameValue("@MAY_USE_OPENFILEGDB", "NO"); 88 2 : oOpenInfo.papszOpenOptions = aosOpenOptions.List(); 89 2 : return poDriver->Open(&oOpenInfo, false); 90 : } 91 : } 92 : 93 60 : return nullptr; 94 : } 95 : 96 : /************************************************************************/ 97 : /* Create() */ 98 : /************************************************************************/ 99 : 100 282 : static GDALDataset *OGROpenFileGDBDriverCreate(const char *pszName, int nXSize, 101 : int nYSize, int nBands, 102 : GDALDataType eType, 103 : char ** /* papszOptions*/) 104 : 105 : { 106 282 : if (!(nXSize == 0 && nYSize == 0 && nBands == 0 && eType == GDT_Unknown)) 107 : { 108 50 : CPLError(CE_Failure, CPLE_NotSupported, 109 : "OpenFileGDB::Create(): only vector datasets supported"); 110 50 : return nullptr; 111 : } 112 : 113 464 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>(); 114 232 : if (!poDS->Create(pszName)) 115 3 : return nullptr; 116 229 : return poDS.release(); 117 : } 118 : 119 : /************************************************************************/ 120 : /* OGROpenFileGDBDriverDelete() */ 121 : /************************************************************************/ 122 : 123 30 : static CPLErr OGROpenFileGDBDriverDelete(const char *pszFilename) 124 : { 125 60 : CPLStringList aosFiles(VSIReadDir(pszFilename)); 126 30 : if (aosFiles.empty()) 127 0 : return CE_Failure; 128 : 129 618 : for (int i = 0; i < aosFiles.size(); ++i) 130 : { 131 588 : if (strcmp(aosFiles[i], ".") != 0 && strcmp(aosFiles[i], "..") != 0) 132 : { 133 : const std::string osFilename( 134 586 : CPLFormFilenameSafe(pszFilename, aosFiles[i], nullptr)); 135 586 : if (VSIUnlink(osFilename.c_str()) != 0) 136 : { 137 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s", 138 : osFilename.c_str()); 139 0 : return CE_Failure; 140 : } 141 : } 142 : } 143 30 : if (VSIRmdir(pszFilename) != 0) 144 : { 145 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s", pszFilename); 146 0 : return CE_Failure; 147 : } 148 : 149 30 : return CE_None; 150 : } 151 : 152 : /***********************************************************************/ 153 : /* RegisterOGROpenFileGDB() */ 154 : /***********************************************************************/ 155 : 156 1682 : void RegisterOGROpenFileGDB() 157 : 158 : { 159 1682 : if (!GDAL_CHECK_VERSION("OGR OpenFileGDB")) 160 0 : return; 161 : 162 1682 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 163 301 : return; 164 : 165 1381 : GDALDriver *poDriver = new GDALDriver(); 166 1381 : OGROpenFileGDBDriverSetCommonMetadata(poDriver); 167 : 168 1381 : poDriver->pfnOpen = OGROpenFileGDBDriverOpen; 169 1381 : poDriver->pfnCreate = OGROpenFileGDBDriverCreate; 170 1381 : poDriver->pfnDelete = OGROpenFileGDBDriverDelete; 171 : 172 1381 : GetGDALDriverManager()->RegisterDriver(poDriver); 173 : }