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 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "cpl_port.h"
30 : #include "ogr_openfilegdb.h"
31 : #include "ogropenfilegdbdrivercore.h"
32 :
33 : #include <cstddef>
34 : #include <cstring>
35 :
36 : #include "cpl_conv.h"
37 : #include "cpl_vsi.h"
38 : #include "gdal.h"
39 : #include "gdal_priv.h"
40 : #include "ogr_core.h"
41 :
42 : // g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp
43 : // -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
44 : // -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/openfilegdb -L. -lgdal
45 :
46 : extern "C" void RegisterOGROpenFileGDB();
47 :
48 : /************************************************************************/
49 : /* Open() */
50 : /************************************************************************/
51 :
52 552 : static GDALDataset *OGROpenFileGDBDriverOpen(GDALOpenInfo *poOpenInfo)
53 :
54 : {
55 552 : const char *pszFilename = poOpenInfo->pszFilename;
56 : #ifdef FOR_FUSIL
57 : CPLString osOrigFilename(pszFilename);
58 : #endif
59 552 : if (OGROpenFileGDBDriverIdentify(poOpenInfo, pszFilename) ==
60 : GDAL_IDENTIFY_FALSE)
61 0 : return nullptr;
62 :
63 : #ifdef FOR_FUSIL
64 : const char *pszSrcDir = CPLGetConfigOption("FUSIL_SRC_DIR", NULL);
65 : if (pszSrcDir != NULL && VSIStatL(osOrigFilename, &stat) == 0 &&
66 : VSI_ISREG(stat.st_mode))
67 : {
68 : /* Copy all files from FUSIL_SRC_DIR to directory of pszFilename */
69 : /* except pszFilename itself */
70 : CPLString osSave(pszFilename);
71 : char **papszFiles = VSIReadDir(pszSrcDir);
72 : for (int i = 0; papszFiles[i] != NULL; i++)
73 : {
74 : if (strcmp(papszFiles[i], CPLGetFilename(osOrigFilename)) != 0)
75 : {
76 : CPLCopyFile(CPLFormFilename(CPLGetPath(osOrigFilename),
77 : papszFiles[i], NULL),
78 : CPLFormFilename(pszSrcDir, papszFiles[i], NULL));
79 : }
80 : }
81 : CSLDestroy(papszFiles);
82 : pszFilename = CPLFormFilename("", osSave.c_str(), NULL);
83 : }
84 : #endif
85 :
86 : #ifdef DEBUG
87 : /* For AFL, so that .cur_input is detected as the archive filename */
88 1210 : if (poOpenInfo->fpL != nullptr &&
89 658 : !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
90 106 : EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input"))
91 : {
92 : GDALOpenInfo oOpenInfo(
93 2 : (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
94 3 : poOpenInfo->nOpenFlags);
95 1 : oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
96 1 : return OGROpenFileGDBDriverOpen(&oOpenInfo);
97 : }
98 : #endif
99 :
100 1102 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>();
101 551 : bool bRetryFileGDB = false;
102 551 : if (poDS->Open(poOpenInfo, bRetryFileGDB))
103 : {
104 490 : if (poDS->GetSubdatasets().size() == 2)
105 : {
106 : // If there is a single raster dataset, open it right away.
107 : GDALOpenInfo oOpenInfo(
108 7 : poDS->GetSubdatasets().FetchNameValue("SUBDATASET_1_NAME"),
109 21 : poOpenInfo->nOpenFlags);
110 7 : poDS = std::make_unique<OGROpenFileGDBDataSource>();
111 7 : if (poDS->Open(&oOpenInfo, bRetryFileGDB))
112 : {
113 7 : poDS->SetDescription(poOpenInfo->pszFilename);
114 : }
115 : else
116 : {
117 0 : poDS.reset();
118 : }
119 : }
120 490 : return poDS.release();
121 : }
122 61 : else if (bRetryFileGDB)
123 : {
124 2 : auto poDriver = GetGDALDriverManager()->GetDriverByName("FileGDB");
125 2 : if (poDriver)
126 : {
127 4 : GDALOpenInfo oOpenInfo(pszFilename, poOpenInfo->nOpenFlags);
128 4 : CPLStringList aosOpenOptions;
129 2 : aosOpenOptions.SetNameValue("@MAY_USE_OPENFILEGDB", "NO");
130 2 : oOpenInfo.papszOpenOptions = aosOpenOptions.List();
131 2 : return poDriver->Open(&oOpenInfo, false);
132 : }
133 : }
134 :
135 59 : return nullptr;
136 : }
137 :
138 : /************************************************************************/
139 : /* Create() */
140 : /************************************************************************/
141 :
142 278 : static GDALDataset *OGROpenFileGDBDriverCreate(const char *pszName, int nXSize,
143 : int nYSize, int nBands,
144 : GDALDataType eType,
145 : char ** /* papszOptions*/)
146 :
147 : {
148 278 : if (!(nXSize == 0 && nYSize == 0 && nBands == 0 && eType == GDT_Unknown))
149 : {
150 50 : CPLError(CE_Failure, CPLE_NotSupported,
151 : "OpenFileGDB::Create(): only vector datasets supported");
152 50 : return nullptr;
153 : }
154 :
155 456 : auto poDS = std::make_unique<OGROpenFileGDBDataSource>();
156 228 : if (!poDS->Create(pszName))
157 3 : return nullptr;
158 225 : return poDS.release();
159 : }
160 :
161 : /************************************************************************/
162 : /* OGROpenFileGDBDriverDelete() */
163 : /************************************************************************/
164 :
165 30 : static CPLErr OGROpenFileGDBDriverDelete(const char *pszFilename)
166 : {
167 60 : CPLStringList aosFiles(VSIReadDir(pszFilename));
168 30 : if (aosFiles.empty())
169 0 : return CE_Failure;
170 :
171 618 : for (int i = 0; i < aosFiles.size(); ++i)
172 : {
173 588 : if (strcmp(aosFiles[i], ".") != 0 && strcmp(aosFiles[i], "..") != 0)
174 : {
175 : const std::string osFilename(
176 586 : CPLFormFilename(pszFilename, aosFiles[i], nullptr));
177 586 : if (VSIUnlink(osFilename.c_str()) != 0)
178 : {
179 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s",
180 : osFilename.c_str());
181 0 : return CE_Failure;
182 : }
183 : }
184 : }
185 30 : if (VSIRmdir(pszFilename) != 0)
186 : {
187 0 : CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s", pszFilename);
188 0 : return CE_Failure;
189 : }
190 :
191 30 : return CE_None;
192 : }
193 :
194 : /***********************************************************************/
195 : /* RegisterOGROpenFileGDB() */
196 : /***********************************************************************/
197 :
198 1512 : void RegisterOGROpenFileGDB()
199 :
200 : {
201 1512 : if (!GDAL_CHECK_VERSION("OGR OpenFileGDB"))
202 0 : return;
203 :
204 1512 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
205 295 : return;
206 :
207 1217 : GDALDriver *poDriver = new GDALDriver();
208 1217 : OGROpenFileGDBDriverSetCommonMetadata(poDriver);
209 :
210 1217 : poDriver->pfnOpen = OGROpenFileGDBDriverOpen;
211 1217 : poDriver->pfnCreate = OGROpenFileGDBDriverCreate;
212 1217 : poDriver->pfnDelete = OGROpenFileGDBDriverDelete;
213 :
214 1217 : GetGDALDriverManager()->RegisterDriver(poDriver);
215 : }
|