1 : /******************************************************************************
2 : * $Id: ogrpgeodriver.cpp 21550 2011-01-22 18:01:57Z 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 21550 2011-01-22 18:01:57Z rouault $");
34 :
35 : /************************************************************************/
36 : /* ~OGRODBCDriver() */
37 : /************************************************************************/
38 :
39 169 : OGRPGeoDriver::~OGRPGeoDriver()
40 :
41 : {
42 169 : }
43 :
44 : /************************************************************************/
45 : /* GetName() */
46 : /************************************************************************/
47 :
48 10050 : const char *OGRPGeoDriver::GetName()
49 :
50 : {
51 10050 : return "PGeo";
52 : }
53 :
54 : /************************************************************************/
55 : /* Open() */
56 : /************************************************************************/
57 :
58 64 : OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
59 : int bUpdate )
60 :
61 : {
62 : OGRPGeoDataSource *poDS;
63 :
64 64 : if( !EQUALN(pszFilename,"PGEO:",5)
65 : && !EQUAL(CPLGetExtension(pszFilename),"mdb") )
66 63 : return NULL;
67 :
68 1 : if( !EQUALN(pszFilename,"PGEO:",5) &&
69 : EQUAL(CPLGetExtension(pszFilename),"mdb") )
70 : {
71 1 : VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
72 1 : if (!fp)
73 0 : return NULL;
74 1 : GByte* pabyHeader = (GByte*) CPLMalloc(100000);
75 1 : VSIFReadL(pabyHeader, 100000, 1, fp);
76 1 : VSIFCloseL(fp);
77 :
78 : /* Look for GDB_GeomColumns table */
79 1 : 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' };
80 1 : int bFound = FALSE;
81 57497 : for(int i=0;i<100000 - (int)sizeof(pabyNeedle);i++)
82 : {
83 57497 : if (memcmp(pabyHeader + i, pabyNeedle, sizeof(pabyNeedle)) == 0)
84 : {
85 1 : bFound = TRUE;
86 1 : break;
87 : }
88 : }
89 1 : CPLFree(pabyHeader);
90 1 : if (!bFound)
91 0 : return NULL;
92 : }
93 :
94 : #ifndef WIN32
95 : // Try to register MDB Tools driver
96 : //
97 : // ODBCINST.INI NOTE:
98 : // This operation requires write access to odbcinst.ini file
99 : // located in directory pointed by ODBCINISYS variable.
100 : // Usually, it points to /etc, so non-root users can overwrite this
101 : // setting ODBCINISYS with location they have write access to, e.g.:
102 : // $ export ODBCINISYS=$HOME/etc
103 : // $ touch $ODBCINISYS/odbcinst.ini
104 : //
105 : // See: http://www.unixodbc.org/internals.html
106 : //
107 1 : if ( !InstallMdbDriver() )
108 : {
109 : CPLError( CE_Warning, CPLE_AppDefined,
110 0 : "Unable to install MDB driver for ODBC, MDB access may not supported.\n" );
111 : }
112 : else
113 1 : CPLDebug( "PGeo", "MDB Tools driver installed successfully!");
114 :
115 : #endif /* ndef WIN32 */
116 :
117 : // Open data source
118 1 : poDS = new OGRPGeoDataSource();
119 :
120 1 : if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
121 : {
122 1 : delete poDS;
123 1 : return NULL;
124 : }
125 : else
126 0 : return poDS;
127 : }
128 :
129 : /************************************************************************/
130 : /* TestCapability() */
131 : /************************************************************************/
132 :
133 0 : int OGRPGeoDriver::TestCapability( const char * pszCap )
134 :
135 : {
136 0 : return FALSE;
137 : }
138 :
139 :
140 : /*
141 : * START OF UNIX-only features.
142 : */
143 : #ifndef WIN32
144 :
145 : /************************************************************************/
146 : /* InstallMdbDriver() */
147 : /************************************************************************/
148 :
149 1 : bool OGRPGeoDriver::InstallMdbDriver()
150 : {
151 1 : if ( !FindDriverLib() )
152 : {
153 0 : return false;
154 : }
155 : else
156 : {
157 1 : CPLAssert( !osDriverFile.empty() );
158 1 : CPLDebug( "PGeo", "MDB Tools driver: %s", osDriverFile.c_str() );
159 :
160 1 : CPLString driverName("Microsoft Access Driver (*.mdb)");
161 1 : CPLString driver(driverName);
162 1 : driver += '\0';
163 1 : driver += "Driver=";
164 1 : driver += osDriverFile; // Found by FindDriverLib()
165 1 : driver += '\0';
166 1 : driver += "FileUsage=1";
167 1 : driver += '\0';
168 1 : driver += '\0';
169 :
170 : // Create installer and register driver
171 1 : CPLODBCDriverInstaller dri;
172 :
173 1 : if ( !dri.InstallDriver(driver.c_str(), 0, ODBC_INSTALL_COMPLETE) )
174 : {
175 : // Report ODBC error
176 0 : CPLError( CE_Failure, CPLE_AppDefined, "ODBC: %s", dri.GetLastError() );
177 0 : return false;
178 0 : }
179 : }
180 :
181 1 : return true;
182 : }
183 :
184 : /************************************************************************/
185 : /* FindDriverLib() */
186 : /************************************************************************/
187 :
188 1 : bool OGRPGeoDriver::FindDriverLib()
189 : {
190 : // Default name and path of driver library
191 : const char* aszDefaultLibName[] = {
192 : "libmdbodbc.so",
193 : "libmdbodbc.so.0" /* for Ubuntu 8.04 support */
194 1 : };
195 1 : const int nLibNames = sizeof(aszDefaultLibName) / sizeof(aszDefaultLibName[0]);
196 : const char* libPath[] = {
197 : "/usr/lib",
198 : "/usr/local/lib"
199 1 : };
200 1 : const int nLibPaths = sizeof(libPath) / sizeof(libPath[0]);
201 :
202 1 : CPLString strLibPath("");
203 :
204 1 : const char* pszDrvCfg = CPLGetConfigOption("MDBDRIVER_PATH", NULL);
205 1 : if ( NULL != pszDrvCfg )
206 : {
207 : // Directory or file path
208 0 : strLibPath = pszDrvCfg;
209 :
210 0 : VSIStatBuf sStatBuf = { 0 };
211 0 : if ( VSIStat( pszDrvCfg, &sStatBuf ) == 0
212 : && VSI_ISDIR( sStatBuf.st_mode ) )
213 : {
214 : // Find default library in custom directory
215 0 : const char* pszDriverFile = CPLFormFilename( pszDrvCfg, aszDefaultLibName[0], NULL );
216 0 : CPLAssert( 0 != pszDriverFile );
217 :
218 0 : strLibPath = pszDriverFile;
219 : }
220 :
221 0 : if ( LibraryExists( strLibPath.c_str() ) )
222 : {
223 : // Save custom driver path
224 0 : osDriverFile = strLibPath;
225 0 : return true;
226 : }
227 : }
228 :
229 : // Try to find library in default path
230 1 : for ( int i = 0; i < nLibPaths; i++ )
231 : {
232 2 : for ( int j = 0; j < nLibNames; j++ )
233 : {
234 2 : const char* pszDriverFile = CPLFormFilename( libPath[i], aszDefaultLibName[j], NULL );
235 2 : CPLAssert( 0 != pszDriverFile );
236 :
237 2 : if ( LibraryExists( pszDriverFile ) )
238 : {
239 : // Save default driver path
240 1 : osDriverFile = pszDriverFile;
241 1 : return true;
242 : }
243 : }
244 : }
245 :
246 0 : CPLError(CE_Failure, CPLE_AppDefined, "PGeo: MDB Tools driver not found!\n");
247 : // Driver not found!
248 0 : return false;
249 : }
250 :
251 : /************************************************************************/
252 : /* LibraryExists() */
253 : /************************************************************************/
254 :
255 2 : bool OGRPGeoDriver::LibraryExists(const char* pszLibPath)
256 : {
257 2 : CPLAssert( 0 != pszLibPath );
258 :
259 2 : VSIStatBuf stb = { 0 } ;
260 :
261 2 : if ( 0 == VSIStat( pszLibPath, &stb ) )
262 : {
263 1 : if (VSI_ISREG( stb.st_mode ) || VSI_ISLNK(stb.st_mode))
264 : {
265 1 : return true;
266 : }
267 : }
268 :
269 1 : return false;
270 : }
271 :
272 : #endif /* ndef WIN32 */
273 : /*
274 : * END OF UNIX-only features
275 : */
276 :
277 : /************************************************************************/
278 : /* RegisterOGRODBC() */
279 : /************************************************************************/
280 :
281 178 : void RegisterOGRPGeo()
282 :
283 : {
284 178 : OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRPGeoDriver );
285 178 : }
286 :
|