EVOLUTION-MANAGER
Edit File: ogropenfilegdbdriver.cpp
/****************************************************************************** * * Project: OpenGIS Simple Features Reference Implementation * Purpose: Implements Open FileGDB OGR driver. * Author: Even Rouault, <even dot rouault at mines-dash paris dot org> * ****************************************************************************** * Copyright (c) 2014, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "ogr_openfilegdb.h" CPL_CVSID("$Id: ogropenfilegdbdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $"); // g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp // -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts // -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/openfilegdb -L. -lgdal extern "C" void RegisterOGROpenFileGDB(); #define ENDS_WITH(str, strLen, end) \ (strLen >= strlen(end) && EQUAL(str + strLen - strlen(end), end)) /************************************************************************/ /* OGROpenFileGDBDriverIdentify() */ /************************************************************************/ static GDALIdentifyEnum OGROpenFileGDBDriverIdentifyInternal( GDALOpenInfo* poOpenInfo, const char*& pszFilename ) { // FUSIL is a fuzzer #ifdef FOR_FUSIL CPLString osOrigFilename(pszFilename); #endif // First check if we have to do any work. size_t nLen = strlen(pszFilename); if( ENDS_WITH(pszFilename, nLen, ".gdb") || ENDS_WITH(pszFilename, nLen, ".gdb/") ) { // Check that the filename is really a directory, to avoid confusion // with Garmin MapSource - gdb format which can be a problem when the // driver is loaded as a plugin, and loaded before the GPSBabel driver // (http://trac.osgeo.org/osgeo4w/ticket/245) if( STARTS_WITH(pszFilename, "/vsicurl/https://github.com/") || !poOpenInfo->bStatOK || !poOpenInfo->bIsDirectory ) { // In case we do not manage to list the directory, try to stat one // file. VSIStatBufL stat; if( !(STARTS_WITH(pszFilename, "/vsicurl/") && VSIStatL( CPLFormFilename( pszFilename, "a00000001", "gdbtable"), &stat ) == 0) ) { return GDAL_IDENTIFY_FALSE; } } return GDAL_IDENTIFY_TRUE; } /* We also accept zipped GDB */ else if( ENDS_WITH(pszFilename, nLen, ".gdb.zip") || ENDS_WITH(pszFilename, nLen, ".gdb.tar") || /* Canvec GBs */ (ENDS_WITH(pszFilename, nLen, ".zip") && (strstr(pszFilename, "_gdb") != NULL || strstr(pszFilename, "_GDB") != NULL)) ) { return GDAL_IDENTIFY_TRUE; } /* We also accept tables themselves */ else if( ENDS_WITH(pszFilename, nLen, ".gdbtable") ) { return GDAL_IDENTIFY_TRUE; } #ifdef FOR_FUSIL /* To be able to test fuzzer on any auxiliary files used (indexes, etc.) */ else if( strlen(CPLGetBasename(pszFilename)) == 9 && CPLGetBasename(pszFilename)[0] == 'a' ) { pszFilename = CPLFormFilename(CPLGetPath(pszFilename), CPLGetBasename(pszFilename), "gdbtable"); return GDAL_IDENTIFY_TRUE; } else if( strlen(CPLGetBasename(CPLGetBasename(pszFilename))) == 9 && CPLGetBasename(CPLGetBasename(pszFilename))[0] == 'a' ) { pszFilename = CPLFormFilename( CPLGetPath(pszFilename), CPLGetBasename(CPLGetBasename(pszFilename)), "gdbtable"); return GDAL_IDENTIFY_TRUE; } #endif #ifdef DEBUG /* For AFL, so that .cur_input is detected as the archive filename */ else if( EQUAL(CPLGetFilename(pszFilename), ".cur_input") ) { // This file may be recognized or not by this driver, // but there were not enough elements to judge. return GDAL_IDENTIFY_UNKNOWN; } #endif else if( EQUAL(pszFilename, ".") ) { GDALIdentifyEnum eRet = GDAL_IDENTIFY_FALSE; char* pszCurrentDir = CPLGetCurrentDir(); if( pszCurrentDir ) { const char* pszTmp = pszCurrentDir; eRet = OGROpenFileGDBDriverIdentifyInternal(poOpenInfo, pszTmp); CPLFree(pszCurrentDir); } return eRet; } else { return GDAL_IDENTIFY_FALSE; } } static int OGROpenFileGDBDriverIdentify( GDALOpenInfo* poOpenInfo ) { const char* pszFilename = poOpenInfo->pszFilename; return OGROpenFileGDBDriverIdentifyInternal( poOpenInfo, pszFilename ); } /************************************************************************/ /* Open() */ /************************************************************************/ static GDALDataset* OGROpenFileGDBDriverOpen( GDALOpenInfo* poOpenInfo ) { if( poOpenInfo->eAccess == GA_Update ) return NULL; const char* pszFilename = poOpenInfo->pszFilename; #ifdef FOR_FUSIL CPLString osOrigFilename(pszFilename); #endif if( OGROpenFileGDBDriverIdentifyInternal( poOpenInfo, pszFilename ) == GDAL_IDENTIFY_FALSE ) return NULL; #ifdef FOR_FUSIL const char* pszSrcDir = CPLGetConfigOption("FUSIL_SRC_DIR", NULL); if( pszSrcDir != NULL && VSIStatL( osOrigFilename, &stat ) == 0 && VSI_ISREG(stat.st_mode) ) { /* Copy all files from FUSIL_SRC_DIR to directory of pszFilename */ /* except pszFilename itself */ CPLString osSave(pszFilename); char** papszFiles = VSIReadDir(pszSrcDir); for(int i=0; papszFiles[i] != NULL; i++) { if( strcmp(papszFiles[i], CPLGetFilename(osOrigFilename)) != 0 ) { CPLCopyFile( CPLFormFilename(CPLGetPath(osOrigFilename), papszFiles[i], NULL), CPLFormFilename(pszSrcDir, papszFiles[i], NULL) ); } } CSLDestroy(papszFiles); pszFilename = CPLFormFilename("", osSave.c_str(), NULL); } #endif #ifdef DEBUG /* For AFL, so that .cur_input is detected as the archive filename */ if( poOpenInfo->fpL != NULL && !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") && EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") ) { GDALOpenInfo oOpenInfo( (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(), poOpenInfo->nOpenFlags ); oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions; return OGROpenFileGDBDriverOpen(&oOpenInfo); } #endif OGROpenFileGDBDataSource* poDS = new OGROpenFileGDBDataSource(); if( poDS->Open( pszFilename ) ) { return poDS; } delete poDS; return NULL; } /***********************************************************************/ /* RegisterOGROpenFileGDB() */ /***********************************************************************/ void RegisterOGROpenFileGDB() { if( !GDAL_CHECK_VERSION("OGR OpenFileGDB") ) return; if( GDALGetDriverByName( "OpenFileGDB" ) != NULL ) return; GDALDriver *poDriver = new GDALDriver(); poDriver->SetDescription( "OpenFileGDB" ); poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" ); poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ESRI FileGDB" ); poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gdb" ); poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_openfilegdb.html" ); poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" ); poDriver->pfnOpen = OGROpenFileGDBDriverOpen; poDriver->pfnIdentify = OGROpenFileGDBDriverIdentify; GetGDALDriverManager()->RegisterDriver( poDriver ); }