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 603 : static GDALDataset *OGROpenFileGDBDriverOpen(GDALOpenInfo *poOpenInfo) 37 : 38 : { 39 603 : const char *pszFilename = poOpenInfo->pszFilename; 40 : #ifdef FOR_FUSIL 41 : CPLString osOrigFilename(pszFilename); 42 : #endif 43 603 : if (OGROpenFileGDBDriverIdentify(poOpenInfo, pszFilename) == 44 : GDAL_IDENTIFY_FALSE) 45 0 : return nullptr; 46 : 47 : #ifdef FOR_FUSIL 48 : const char *pszSrcDir = CPLGetConfigOption("FUSIL_SRC_DIR", NULL); 49 : if (pszSrcDir != NULL && VSIStatL(osOrigFilename, &stat) == 0 && 50 : VSI_ISREG(stat.st_mode)) 51 : { 52 : /* Copy all files from FUSIL_SRC_DIR to directory of pszFilename */ 53 : /* except pszFilename itself */ 54 : CPLString osSave(pszFilename); 55 : char **papszFiles = VSIReadDir(pszSrcDir); 56 : for (int i = 0; papszFiles[i] != NULL; i++) 57 : { 58 : if (strcmp(papszFiles[i], CPLGetFilename(osOrigFilename)) != 0) 59 : { 60 : CPLCopyFile(CPLFormFilename(CPLGetPath(osOrigFilename), 61 : papszFiles[i], NULL), 62 : CPLFormFilename(pszSrcDir, papszFiles[i], NULL)); 63 : } 64 : } 65 : CSLDestroy(papszFiles); 66 : pszFilename = CPLFormFilename("", osSave.c_str(), NULL); 67 : } 68 : #endif 69 : 70 : #ifdef DEBUG 71 : /* For AFL, so that .cur_input is detected as the archive filename */ 72 1320 : if (poOpenInfo->fpL != nullptr && 73 717 : !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") && 74 114 : EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input")) 75 : { 76 : GDALOpenInfo oOpenInfo( 77 2 : (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(), 78 3 : poOpenInfo->nOpenFlags); 79 1 : oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions; 80 1 : return OGROpenFileGDBDriverOpen(&oOpenInfo); 81 : } 82 : #endif 83 : 84 1204 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>(); 85 602 : bool bRetryFileGDB = false; 86 602 : if (poDS->Open(poOpenInfo, bRetryFileGDB)) 87 : { 88 540 : if (poDS->GetSubdatasets().size() == 2) 89 : { 90 : // If there is a single raster dataset, open it right away. 91 : GDALOpenInfo oOpenInfo( 92 7 : poDS->GetSubdatasets().FetchNameValue("SUBDATASET_1_NAME"), 93 21 : poOpenInfo->nOpenFlags); 94 7 : poDS = std::make_unique<OGROpenFileGDBDataSource>(); 95 7 : if (poDS->Open(&oOpenInfo, bRetryFileGDB)) 96 : { 97 7 : poDS->SetDescription(poOpenInfo->pszFilename); 98 : } 99 : else 100 : { 101 0 : poDS.reset(); 102 : } 103 : } 104 540 : return poDS.release(); 105 : } 106 62 : else if (bRetryFileGDB) 107 : { 108 2 : auto poDriver = GetGDALDriverManager()->GetDriverByName("FileGDB"); 109 2 : if (poDriver) 110 : { 111 4 : GDALOpenInfo oOpenInfo(pszFilename, poOpenInfo->nOpenFlags); 112 4 : CPLStringList aosOpenOptions; 113 2 : aosOpenOptions.SetNameValue("@MAY_USE_OPENFILEGDB", "NO"); 114 2 : oOpenInfo.papszOpenOptions = aosOpenOptions.List(); 115 2 : return poDriver->Open(&oOpenInfo, false); 116 : } 117 : } 118 : 119 60 : return nullptr; 120 : } 121 : 122 : /************************************************************************/ 123 : /* Create() */ 124 : /************************************************************************/ 125 : 126 281 : static GDALDataset *OGROpenFileGDBDriverCreate(const char *pszName, int nXSize, 127 : int nYSize, int nBands, 128 : GDALDataType eType, 129 : char ** /* papszOptions*/) 130 : 131 : { 132 281 : if (!(nXSize == 0 && nYSize == 0 && nBands == 0 && eType == GDT_Unknown)) 133 : { 134 50 : CPLError(CE_Failure, CPLE_NotSupported, 135 : "OpenFileGDB::Create(): only vector datasets supported"); 136 50 : return nullptr; 137 : } 138 : 139 462 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>(); 140 231 : if (!poDS->Create(pszName)) 141 3 : return nullptr; 142 228 : return poDS.release(); 143 : } 144 : 145 : /************************************************************************/ 146 : /* OGROpenFileGDBDriverDelete() */ 147 : /************************************************************************/ 148 : 149 30 : static CPLErr OGROpenFileGDBDriverDelete(const char *pszFilename) 150 : { 151 60 : CPLStringList aosFiles(VSIReadDir(pszFilename)); 152 30 : if (aosFiles.empty()) 153 0 : return CE_Failure; 154 : 155 618 : for (int i = 0; i < aosFiles.size(); ++i) 156 : { 157 588 : if (strcmp(aosFiles[i], ".") != 0 && strcmp(aosFiles[i], "..") != 0) 158 : { 159 : const std::string osFilename( 160 586 : CPLFormFilename(pszFilename, aosFiles[i], nullptr)); 161 586 : if (VSIUnlink(osFilename.c_str()) != 0) 162 : { 163 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s", 164 : osFilename.c_str()); 165 0 : return CE_Failure; 166 : } 167 : } 168 : } 169 30 : if (VSIRmdir(pszFilename) != 0) 170 : { 171 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s", pszFilename); 172 0 : return CE_Failure; 173 : } 174 : 175 30 : return CE_None; 176 : } 177 : 178 : /***********************************************************************/ 179 : /* RegisterOGROpenFileGDB() */ 180 : /***********************************************************************/ 181 : 182 1595 : void RegisterOGROpenFileGDB() 183 : 184 : { 185 1595 : if (!GDAL_CHECK_VERSION("OGR OpenFileGDB")) 186 0 : return; 187 : 188 1595 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 189 302 : return; 190 : 191 1293 : GDALDriver *poDriver = new GDALDriver(); 192 1293 : OGROpenFileGDBDriverSetCommonMetadata(poDriver); 193 : 194 1293 : poDriver->pfnOpen = OGROpenFileGDBDriverOpen; 195 1293 : poDriver->pfnCreate = OGROpenFileGDBDriverCreate; 196 1293 : poDriver->pfnDelete = OGROpenFileGDBDriverDelete; 197 : 198 1293 : GetGDALDriverManager()->RegisterDriver(poDriver); 199 : }