1 : /******************************************************************************
2 : * $Id: ogrpgeodriver.cpp 23931 2012-02-09 13:41:13Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements Personal Geodatabase driver.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_pgeo.h"
31 : #include "cpl_conv.h"
32 :
33 : CPL_CVSID("$Id: ogrpgeodriver.cpp 23931 2012-02-09 13:41:13Z rouault $");
34 :
35 : /************************************************************************/
36 : /* ~OGRODBCDriver() */
37 : /************************************************************************/
38 :
39 214 : OGRPGeoDriver::~OGRPGeoDriver()
40 :
41 : {
42 214 : }
43 :
44 : /************************************************************************/
45 : /* GetName() */
46 : /************************************************************************/
47 :
48 13883 : const char *OGRPGeoDriver::GetName()
49 :
50 : {
51 13883 : return "PGeo";
52 : }
53 :
54 : /************************************************************************/
55 : /* Open() */
56 : /************************************************************************/
57 :
58 98 : OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
59 : int bUpdate )
60 :
61 : {
62 : OGRPGeoDataSource *poDS;
63 :
64 98 : if( !EQUALN(pszFilename,"PGEO:",5)
65 : && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
66 97 : return NULL;
67 :
68 : /* Disabling the attempt to guess if a MDB file is a PGeo database */
69 : /* or not. The mention to GDB_GeomColumns might be quite far in the */
70 : /* file, which can cause mis-detection. See http://trac.osgeo.org/gdal/ticket/4498 */
71 : /* This was initially meant to know if a MDB should be opened by the PGeo or the */
72 : /* Geomedia driver. */
73 : #if 0
74 : if( !EQUALN(pszFilename,"PGEO:",5) &&
75 : EQUAL(CPLGetExtension(pszFilename),"mdb") )
76 : {
77 : VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
78 : if (!fp)
79 : return NULL;
80 : GByte* pabyHeader = (GByte*) CPLMalloc(100000);
81 : VSIFReadL(pabyHeader, 100000, 1, fp);
82 : VSIFCloseL(fp);
83 :
84 : /* Look for GDB_GeomColumns table */
85 : const GByte pabyNeedle[] = { 'G', 0, 'D', 0, 'B', 0, '_', 0, 'G', 0, 'e', 0, 'o', 0, 'm', 0, 'C', 0, 'o', 0, 'l', 0, 'u', 0, 'm', 0, 'n', 0, 's' };
86 : int bFound = FALSE;
87 : for(int i=0;i<100000 - (int)sizeof(pabyNeedle);i++)
88 : {
89 : if (memcmp(pabyHeader + i, pabyNeedle, sizeof(pabyNeedle)) == 0)
90 : {
91 : bFound = TRUE;
92 : break;
93 : }
94 : }
95 : CPLFree(pabyHeader);
96 : if (!bFound)
97 : return NULL;
98 : }
99 : #endif
100 :
101 : #ifndef WIN32
102 : // Try to register MDB Tools driver
103 : //
104 : // ODBCINST.INI NOTE:
105 : // This operation requires write access to odbcinst.ini file
106 : // located in directory pointed by ODBCINISYS variable.
107 : // Usually, it points to /etc, so non-root users can overwrite this
108 : // setting ODBCINISYS with location they have write access to, e.g.:
109 : // $ export ODBCINISYS=$HOME/etc
110 : // $ touch $ODBCINISYS/odbcinst.ini
111 : //
112 : // See: http://www.unixodbc.org/internals.html
113 : //
114 1 : if ( !InstallMdbDriver() )
115 : {
116 : CPLError( CE_Warning, CPLE_AppDefined,
117 0 : "Unable to install MDB driver for ODBC, MDB access may not supported.\n" );
118 : }
119 : else
120 1 : CPLDebug( "PGeo", "MDB Tools driver installed successfully!");
121 :
122 : #endif /* ndef WIN32 */
123 :
124 : // Open data source
125 1 : poDS = new OGRPGeoDataSource();
126 :
127 1 : if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
128 : {
129 1 : delete poDS;
130 1 : return NULL;
131 : }
132 : else
133 0 : return poDS;
134 : }
135 :
136 : /************************************************************************/
137 : /* TestCapability() */
138 : /************************************************************************/
139 :
140 0 : int OGRPGeoDriver::TestCapability( const char * pszCap )
141 :
142 : {
143 0 : return FALSE;
144 : }
145 :
146 :
147 : /*
148 : * START OF UNIX-only features.
149 : */
150 : #ifndef WIN32
151 :
152 : /************************************************************************/
153 : /* InstallMdbDriver() */
154 : /************************************************************************/
155 :
156 1 : bool OGRPGeoDriver::InstallMdbDriver()
157 : {
158 1 : if ( !FindDriverLib() )
159 : {
160 0 : return false;
161 : }
162 : else
163 : {
164 1 : CPLAssert( !osDriverFile.empty() );
165 1 : CPLDebug( "PGeo", "MDB Tools driver: %s", osDriverFile.c_str() );
166 :
167 1 : CPLString driverName("Microsoft Access Driver (*.mdb)");
168 1 : CPLString driver(driverName);
169 1 : driver += '\0';
170 1 : driver += "Driver=";
171 1 : driver += osDriverFile; // Found by FindDriverLib()
172 1 : driver += '\0';
173 1 : driver += "FileUsage=1";
174 1 : driver += '\0';
175 1 : driver += '\0';
176 :
177 : // Create installer and register driver
178 1 : CPLODBCDriverInstaller dri;
179 :
180 1 : if ( !dri.InstallDriver(driver.c_str(), 0, ODBC_INSTALL_COMPLETE) )
181 : {
182 : // Report ODBC error
183 0 : CPLError( CE_Failure, CPLE_AppDefined, "ODBC: %s", dri.GetLastError() );
184 0 : return false;
185 0 : }
186 : }
187 :
188 1 : return true;
189 : }
190 :
191 : /************************************************************************/
192 : /* FindDriverLib() */
193 : /************************************************************************/
194 :
195 1 : bool OGRPGeoDriver::FindDriverLib()
196 : {
197 : // Default name and path of driver library
198 : const char* aszDefaultLibName[] = {
199 : "libmdbodbc.so",
200 : "libmdbodbc.so.0" /* for Ubuntu 8.04 support */
201 1 : };
202 1 : const int nLibNames = sizeof(aszDefaultLibName) / sizeof(aszDefaultLibName[0]);
203 : const char* libPath[] = {
204 : "/usr/lib",
205 : "/usr/local/lib"
206 1 : };
207 1 : const int nLibPaths = sizeof(libPath) / sizeof(libPath[0]);
208 :
209 1 : CPLString strLibPath("");
210 :
211 1 : const char* pszDrvCfg = CPLGetConfigOption("MDBDRIVER_PATH", NULL);
212 1 : if ( NULL != pszDrvCfg )
213 : {
214 : // Directory or file path
215 0 : strLibPath = pszDrvCfg;
216 :
217 0 : VSIStatBuf sStatBuf = { 0 };
218 0 : if ( VSIStat( pszDrvCfg, &sStatBuf ) == 0
219 : && VSI_ISDIR( sStatBuf.st_mode ) )
220 : {
221 : // Find default library in custom directory
222 0 : const char* pszDriverFile = CPLFormFilename( pszDrvCfg, aszDefaultLibName[0], NULL );
223 0 : CPLAssert( 0 != pszDriverFile );
224 :
225 0 : strLibPath = pszDriverFile;
226 : }
227 :
228 0 : if ( LibraryExists( strLibPath.c_str() ) )
229 : {
230 : // Save custom driver path
231 0 : osDriverFile = strLibPath;
232 0 : return true;
233 : }
234 : }
235 :
236 : // Try to find library in default path
237 1 : for ( int i = 0; i < nLibPaths; i++ )
238 : {
239 1 : for ( int j = 0; j < nLibNames; j++ )
240 : {
241 1 : const char* pszDriverFile = CPLFormFilename( libPath[i], aszDefaultLibName[j], NULL );
242 1 : CPLAssert( 0 != pszDriverFile );
243 :
244 1 : if ( LibraryExists( pszDriverFile ) )
245 : {
246 : // Save default driver path
247 1 : osDriverFile = pszDriverFile;
248 1 : return true;
249 : }
250 : }
251 : }
252 :
253 0 : CPLError(CE_Failure, CPLE_AppDefined, "PGeo: MDB Tools driver not found!\n");
254 : // Driver not found!
255 0 : return false;
256 : }
257 :
258 : /************************************************************************/
259 : /* LibraryExists() */
260 : /************************************************************************/
261 :
262 1 : bool OGRPGeoDriver::LibraryExists(const char* pszLibPath)
263 : {
264 1 : CPLAssert( 0 != pszLibPath );
265 :
266 1 : VSIStatBuf stb = { 0 } ;
267 :
268 1 : if ( 0 == VSIStat( pszLibPath, &stb ) )
269 : {
270 1 : if (VSI_ISREG( stb.st_mode ) || VSI_ISLNK(stb.st_mode))
271 : {
272 1 : return true;
273 : }
274 : }
275 :
276 0 : return false;
277 : }
278 :
279 : #endif /* ndef WIN32 */
280 : /*
281 : * END OF UNIX-only features
282 : */
283 :
284 : /************************************************************************/
285 : /* RegisterOGRODBC() */
286 : /************************************************************************/
287 :
288 226 : void RegisterOGRPGeo()
289 :
290 : {
291 226 : OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRPGeoDriver );
292 226 : }
293 :
|