1 : /******************************************************************************
2 : * $Id: ogrsfdriverregistrar.cpp 22812 2011-07-25 04:50:23Z warmerdam $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: The OGRSFDriverRegistrar class implementation.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Les Technologies SoftMap Inc.
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 "ogrsf_frmts.h"
31 : #include "ogr_api.h"
32 : #include "ogr_p.h"
33 : #include "cpl_multiproc.h"
34 : #include "swq.h"
35 :
36 : #ifdef HAVE_UNISTD_H
37 : #include <unistd.h>
38 : #endif
39 :
40 : CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 22812 2011-07-25 04:50:23Z warmerdam $");
41 :
42 : static void *hDRMutex = NULL;
43 : static OGRSFDriverRegistrar * volatile poRegistrar = NULL;
44 :
45 : static const char *pszUpdatableINST_DATA =
46 : "__INST_DATA_TARGET: ";
47 : /************************************************************************/
48 : /* OGRSFDriverRegistrar */
49 : /************************************************************************/
50 :
51 : /**
52 : * \brief Constructor
53 : *
54 : * Normally the driver registrar is constucted by the
55 : * OGRSFDriverRegistrar::GetRegistrar() accessor which ensures singleton
56 : * status.
57 : */
58 :
59 175 : OGRSFDriverRegistrar::OGRSFDriverRegistrar()
60 :
61 : {
62 175 : CPLAssert( poRegistrar == NULL );
63 175 : nDrivers = 0;
64 175 : papoDrivers = NULL;
65 :
66 175 : nOpenDSCount = 0;
67 175 : papszOpenDSRawName = NULL;
68 175 : papoOpenDS = NULL;
69 175 : papoOpenDSDriver = NULL;
70 175 : panOpenDSPID = NULL;
71 :
72 : /* -------------------------------------------------------------------- */
73 : /* We want to push a location to search for data files */
74 : /* supporting GDAL/OGR such as EPSG csv files, S-57 definition */
75 : /* files, and so forth. The static pszUpdateableINST_DATA */
76 : /* string can be updated within the shared library or */
77 : /* executable during an install to point installed data */
78 : /* directory. If it isn't burned in here then we use the */
79 : /* INST_DATA macro (setup at configure time) if */
80 : /* available. Otherwise we don't push anything and we hope */
81 : /* other mechanisms such as environment variables will have */
82 : /* been employed. */
83 : /* -------------------------------------------------------------------- */
84 175 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
85 : {
86 175 : CPLPushFinderLocation( CPLGetConfigOption( "GDAL_DATA", NULL ) );
87 : }
88 0 : else if( pszUpdatableINST_DATA[19] != ' ' )
89 : {
90 0 : CPLPushFinderLocation( pszUpdatableINST_DATA + 19 );
91 : }
92 : else
93 : {
94 : #ifdef INST_DATA
95 0 : CPLPushFinderLocation( INST_DATA );
96 : #endif
97 : }
98 175 : }
99 :
100 : /************************************************************************/
101 : /* ~OGRSFDriverRegistrar() */
102 : /************************************************************************/
103 :
104 166 : OGRSFDriverRegistrar::~OGRSFDriverRegistrar()
105 :
106 : {
107 9626 : for( int i = 0; i < nDrivers; i++ )
108 : {
109 9460 : delete papoDrivers[i];
110 : }
111 :
112 166 : CPLFree( papoDrivers );
113 166 : papoDrivers = NULL;
114 :
115 166 : poRegistrar = NULL;
116 166 : }
117 :
118 : /************************************************************************/
119 : /* OGRCleanupAll() */
120 : /************************************************************************/
121 :
122 : /**
123 : * \brief Cleanup all OGR related resources.
124 : *
125 : * This function will destroy the OGRSFDriverRegistrar along with all registered
126 : * drivers, and then cleanup long lived OSR (OGRSpatialReference) and CPL
127 : * resources. This may be called in an application when OGR services are
128 : * no longer needed. It is not normally required, but by freeing all
129 : * dynamically allocated memory it can make memory leak testing easier.
130 : *
131 : * In addition to destroying the OGRDriverRegistrar, this function also calls:
132 : * - OSRCleanup()
133 : * - CPLFinderClean()
134 : * - VSICleanupFileManager()
135 : * - CPLFreeConfig()
136 : * - CPLCleanupTLS()
137 : */
138 442 : void OGRCleanupAll()
139 :
140 : {
141 : {
142 : // We don't want to hold the mutex while CPL level mutex services
143 : // are being destroyed ... just long enough to avoid conflict while
144 : // cleaning up OGR and OSR services.
145 442 : CPLMutexHolderD( &hDRMutex );
146 :
147 442 : if( poRegistrar != NULL )
148 166 : delete poRegistrar;
149 442 : OSRCleanup();
150 442 : swq_op_registrar::DeInitialize();
151 : }
152 :
153 442 : CPLDestroyMutex( hDRMutex );
154 442 : hDRMutex = NULL;
155 :
156 442 : CPLFinderClean();
157 442 : VSICleanupFileManager();
158 442 : CPLFreeConfig();
159 442 : CPLCleanupTLS();
160 442 : }
161 :
162 :
163 : /************************************************************************/
164 : /* GetRegistrar() */
165 : /************************************************************************/
166 :
167 : /**
168 : * \brief Fetch registrar.
169 : *
170 : * This static method should be used to fetch the singleton
171 : * registrar. It will create a registrar if there is not already
172 : * one in existance.
173 : *
174 : * @return the current driver registrar.
175 : */
176 :
177 13378 : OGRSFDriverRegistrar *OGRSFDriverRegistrar::GetRegistrar()
178 :
179 : {
180 13378 : if( poRegistrar == NULL )
181 : {
182 175 : CPLMutexHolderD( &hDRMutex );
183 :
184 175 : if( poRegistrar == NULL )
185 175 : poRegistrar = new OGRSFDriverRegistrar();
186 : }
187 :
188 13378 : CPLAssert( NULL != poRegistrar );
189 13378 : return poRegistrar;
190 : }
191 :
192 : /************************************************************************/
193 : /* Open() */
194 : /************************************************************************/
195 :
196 1045 : OGRDataSource *OGRSFDriverRegistrar::Open( const char * pszName,
197 : int bUpdate,
198 : OGRSFDriver ** ppoDriver )
199 :
200 : {
201 : OGRDataSource *poDS;
202 :
203 : #ifdef HAVE_READLINK
204 : char szPointerFilename[2048];
205 1045 : int bHasRetried = FALSE;
206 : #endif
207 :
208 1045 : if( ppoDriver != NULL )
209 73 : *ppoDriver = NULL;
210 :
211 1045 : GetRegistrar();
212 :
213 1045 : CPLErrorReset();
214 :
215 1045 : CPLAcquireMutex( hDRMutex, 0.1 );
216 :
217 : #ifdef HAVE_READLINK
218 : retry:
219 : #endif
220 14704 : for( int iDriver = 0; iDriver < poRegistrar->nDrivers; iDriver++ )
221 : {
222 14692 : OGRSFDriver *poDriver = poRegistrar->papoDrivers[iDriver];
223 :
224 14692 : CPLReleaseMutex( hDRMutex );
225 :
226 14692 : poDS = poDriver->Open( pszName, bUpdate );
227 14692 : if( poDS != NULL )
228 : {
229 1032 : if( ppoDriver != NULL )
230 71 : *ppoDriver = poDriver;
231 :
232 1032 : poDS->Reference();
233 1032 : if( poDS->GetDriver() == NULL )
234 921 : poDS->m_poDriver = poDriver;
235 :
236 : CPLDebug( "OGR", "OGROpen(%s/%p) succeeded as %s.",
237 1032 : pszName, poDS, poDS->GetDriver()->GetName() );
238 :
239 1032 : return poDS;
240 : }
241 :
242 13660 : if( CPLGetLastErrorType() == CE_Failure )
243 2 : return NULL;
244 :
245 13658 : CPLAcquireMutex( hDRMutex, 0.1 );
246 : }
247 :
248 : #ifdef HAVE_READLINK
249 12 : if (!bHasRetried)
250 : {
251 : /* If someone creates a file with "ln -sf /vsicurl/http://svn.osgeo.org/gdal/trunk/autotest/ogr/data/poly.shp my_remote_poly.shp" */
252 : /* we will be able to open it by passing my_remote_poly.shp */
253 : /* This helps a lot for OGR based readers that only provide file explorers to open datasources */
254 12 : int nBytes = readlink(pszName, szPointerFilename, sizeof(szPointerFilename));
255 12 : if (nBytes != -1)
256 : {
257 1 : szPointerFilename[MIN(nBytes, (int)sizeof(szPointerFilename)-1)] = 0;
258 1 : pszName = szPointerFilename;
259 1 : bHasRetried = TRUE;
260 1 : goto retry;
261 : }
262 : }
263 : #endif
264 :
265 11 : CPLReleaseMutex( hDRMutex );
266 :
267 11 : CPLDebug( "OGR", "OGROpen(%s) failed.", pszName );
268 :
269 11 : return NULL;
270 : }
271 :
272 : /************************************************************************/
273 : /* OGROpen() */
274 : /************************************************************************/
275 :
276 801 : OGRDataSourceH OGROpen( const char *pszName, int bUpdate,
277 : OGRSFDriverH *pahDriverList )
278 :
279 : {
280 801 : VALIDATE_POINTER1( pszName, "OGROpen", NULL );
281 :
282 801 : if (poRegistrar)
283 : return (OGRDataSourceH)
284 : poRegistrar->Open( pszName, bUpdate,
285 801 : (OGRSFDriver **) pahDriverList );
286 :
287 0 : return NULL;
288 : }
289 :
290 : /************************************************************************/
291 : /* OpenShared() */
292 : /************************************************************************/
293 :
294 : OGRDataSource *
295 42 : OGRSFDriverRegistrar::OpenShared( const char * pszName, int bUpdate,
296 : OGRSFDriver ** ppoDriver )
297 :
298 : {
299 : OGRDataSource *poDS;
300 :
301 42 : if( ppoDriver != NULL )
302 0 : *ppoDriver = NULL;
303 :
304 42 : CPLErrorReset();
305 :
306 : /* -------------------------------------------------------------------- */
307 : /* First try finding an existing open dataset matching exactly */
308 : /* on the original datasource raw name used to open the */
309 : /* datasource. */
310 : /* */
311 : /* NOTE: It is an error, but currently we ignore the bUpdate, */
312 : /* and return whatever is open even if it is read-only and the */
313 : /* application requested update access. */
314 : /* -------------------------------------------------------------------- */
315 : {
316 : int iDS;
317 42 : CPLMutexHolderD( &hDRMutex );
318 42 : GIntBig nThisPID = CPLGetPID();
319 :
320 54 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
321 : {
322 41 : poDS = papoOpenDS[iDS];
323 :
324 70 : if( strcmp( pszName, papszOpenDSRawName[iDS]) == 0
325 29 : && nThisPID == panOpenDSPID[iDS] )
326 : {
327 29 : poDS->Reference();
328 :
329 29 : if( ppoDriver != NULL )
330 0 : *ppoDriver = papoOpenDSDriver[iDS];
331 29 : return poDS;
332 : }
333 : }
334 :
335 : /* -------------------------------------------------------------------- */
336 : /* If that doesn't match, try matching on the name returned by */
337 : /* the datasource itself. */
338 : /* -------------------------------------------------------------------- */
339 19 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
340 : {
341 6 : poDS = papoOpenDS[iDS];
342 :
343 6 : if( strcmp( pszName, poDS->GetName()) == 0
344 0 : && nThisPID == panOpenDSPID[iDS] )
345 : {
346 0 : poDS->Reference();
347 :
348 0 : if( ppoDriver != NULL )
349 0 : *ppoDriver = papoOpenDSDriver[iDS];
350 0 : return poDS;
351 : }
352 0 : }
353 : }
354 :
355 : /* -------------------------------------------------------------------- */
356 : /* We don't have the datasource. Open it normally. */
357 : /* -------------------------------------------------------------------- */
358 13 : OGRSFDriver *poTempDriver = NULL;
359 :
360 13 : poDS = Open( pszName, bUpdate, &poTempDriver );
361 :
362 13 : if( poDS == NULL )
363 0 : return poDS;
364 :
365 : /* -------------------------------------------------------------------- */
366 : /* We don't have this datasource already. Grow our list to */
367 : /* hold the new datasource. */
368 : /* -------------------------------------------------------------------- */
369 : {
370 13 : CPLMutexHolderD( &hDRMutex );
371 :
372 : papszOpenDSRawName = (char **)
373 13 : CPLRealloc( papszOpenDSRawName, sizeof(char*) * (nOpenDSCount+1) );
374 :
375 : papoOpenDS = (OGRDataSource **)
376 13 : CPLRealloc( papoOpenDS, sizeof(char*) * (nOpenDSCount+1) );
377 :
378 : papoOpenDSDriver = (OGRSFDriver **)
379 13 : CPLRealloc( papoOpenDSDriver, sizeof(char*) * (nOpenDSCount+1) );
380 :
381 : panOpenDSPID = (GIntBig *)
382 13 : CPLRealloc( panOpenDSPID, sizeof(GIntBig) * (nOpenDSCount+1) );
383 :
384 13 : papszOpenDSRawName[nOpenDSCount] = CPLStrdup( pszName );
385 13 : papoOpenDS[nOpenDSCount] = poDS;
386 13 : papoOpenDSDriver[nOpenDSCount] = poTempDriver;
387 13 : panOpenDSPID[nOpenDSCount] = CPLGetPID();
388 :
389 13 : nOpenDSCount++;
390 : }
391 :
392 13 : if( ppoDriver != NULL )
393 0 : *ppoDriver = poTempDriver;
394 :
395 13 : return poDS;
396 : }
397 :
398 : /************************************************************************/
399 : /* OGROpenShared() */
400 : /************************************************************************/
401 :
402 19 : OGRDataSourceH OGROpenShared( const char *pszName, int bUpdate,
403 : OGRSFDriverH *pahDriverList )
404 :
405 : {
406 19 : VALIDATE_POINTER1( pszName, "OGROpenShared", NULL );
407 :
408 19 : OGRSFDriverRegistrar::GetRegistrar();
409 : return (OGRDataSourceH)
410 : poRegistrar->OpenShared( pszName, bUpdate,
411 19 : (OGRSFDriver **) pahDriverList );
412 : }
413 :
414 : /************************************************************************/
415 : /* ReleaseDataSource() */
416 : /************************************************************************/
417 :
418 1015 : OGRErr OGRSFDriverRegistrar::ReleaseDataSource( OGRDataSource * poDS )
419 :
420 : {
421 : {
422 1015 : CPLMutexHolderD( &hDRMutex );
423 :
424 : int iDS;
425 :
426 1079 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
427 : {
428 101 : if( poDS == papoOpenDS[iDS] )
429 37 : break;
430 : }
431 :
432 1015 : if( iDS == nOpenDSCount )
433 : {
434 : CPLDebug( "OGR",
435 : "ReleaseDataSource(%s/%p) on unshared datasource!\n"
436 : "Deleting directly.",
437 978 : poDS->GetName(), poDS );
438 978 : delete poDS;
439 978 : return OGRERR_FAILURE;
440 : }
441 :
442 37 : if( poDS->GetRefCount() > 0 )
443 37 : poDS->Dereference();
444 :
445 37 : if( poDS->GetRefCount() > 0 )
446 : {
447 : CPLDebug( "OGR",
448 : "ReleaseDataSource(%s/%p) ... just dereferencing.",
449 24 : poDS->GetName(), poDS );
450 24 : return OGRERR_NONE;
451 : }
452 :
453 13 : if( poDS->GetSummaryRefCount() > 0 )
454 : {
455 : CPLDebug( "OGR",
456 : "OGRSFDriverRegistrar::ReleaseDataSource(%s)\n"
457 : "Datasource reference count is now zero, but some layers\n"
458 : "are still referenced ... not closing datasource.",
459 0 : poDS->GetName() );
460 0 : return OGRERR_FAILURE;
461 : }
462 :
463 : /* -------------------------------------------------------------------- */
464 : /* We really want to close this file, and remove it from the */
465 : /* shared list. */
466 : /* -------------------------------------------------------------------- */
467 : CPLDebug( "OGR",
468 : "ReleaseDataSource(%s/%p) dereferenced and now destroying.",
469 13 : poDS->GetName(), poDS );
470 :
471 13 : CPLFree( papszOpenDSRawName[iDS] );
472 : memmove( papszOpenDSRawName + iDS, papszOpenDSRawName + iDS + 1,
473 13 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
474 : memmove( papoOpenDS + iDS, papoOpenDS + iDS + 1,
475 13 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
476 : memmove( papoOpenDSDriver + iDS, papoOpenDSDriver + iDS + 1,
477 13 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
478 : memmove( panOpenDSPID + iDS, panOpenDSPID + iDS + 1,
479 13 : sizeof(GIntBig) * (nOpenDSCount - iDS - 1) );
480 :
481 13 : nOpenDSCount--;
482 :
483 13 : if( nOpenDSCount == 0 )
484 : {
485 7 : CPLFree( papszOpenDSRawName );
486 7 : papszOpenDSRawName = NULL;
487 7 : CPLFree( papoOpenDS );
488 7 : papoOpenDS = NULL;
489 7 : CPLFree( papoOpenDSDriver );
490 7 : papoOpenDSDriver = NULL;
491 7 : CPLFree( panOpenDSPID );
492 7 : panOpenDSPID = NULL;
493 0 : }
494 : }
495 :
496 : /* -------------------------------------------------------------------- */
497 : /* We are careful to only do the delete poDS after adjusting */
498 : /* the table, as if it is a virtual dataset, other removals may */
499 : /* happen in the meantime. We are also careful to do this */
500 : /* outside the mutex protected loop as destroying a dataset can */
501 : /* take quite a while. */
502 : /* -------------------------------------------------------------------- */
503 13 : delete poDS;
504 :
505 13 : return OGRERR_NONE;
506 : }
507 :
508 : /************************************************************************/
509 : /* OGRReleaseDataSource() */
510 : /************************************************************************/
511 :
512 987 : OGRErr OGRReleaseDataSource( OGRDataSourceH hDS )
513 :
514 : {
515 987 : VALIDATE_POINTER1( hDS, "OGRReleaseDataSource", OGRERR_INVALID_HANDLE );
516 :
517 987 : OGRSFDriverRegistrar::GetRegistrar();
518 987 : return poRegistrar->ReleaseDataSource((OGRDataSource *) hDS);
519 : }
520 :
521 : /************************************************************************/
522 : /* OGRGetOpenDSCount() */
523 : /************************************************************************/
524 :
525 5 : int OGRGetOpenDSCount()
526 :
527 : {
528 5 : OGRSFDriverRegistrar::GetRegistrar();
529 5 : return poRegistrar->GetOpenDSCount();
530 : }
531 :
532 : /************************************************************************/
533 : /* GetOpenDS() */
534 : /************************************************************************/
535 :
536 1 : OGRDataSource *OGRSFDriverRegistrar::GetOpenDS( int iDS )
537 :
538 : {
539 1 : CPLMutexHolderD( &hDRMutex );
540 :
541 1 : if( iDS < 0 || iDS >= nOpenDSCount )
542 0 : return NULL;
543 : else
544 1 : return papoOpenDS[iDS];
545 : }
546 :
547 : /************************************************************************/
548 : /* OGRGetOpenDS() */
549 : /************************************************************************/
550 :
551 1 : OGRDataSourceH OGRGetOpenDS( int iDS )
552 :
553 : {
554 1 : OGRSFDriverRegistrar::GetRegistrar();
555 1 : return (OGRDataSourceH) poRegistrar->GetOpenDS( iDS );
556 : }
557 :
558 : /************************************************************************/
559 : /* RegisterDriver() */
560 : /************************************************************************/
561 :
562 10150 : void OGRSFDriverRegistrar::RegisterDriver( OGRSFDriver * poDriver )
563 :
564 : {
565 10150 : CPLMutexHolderD( &hDRMutex );
566 : int iDriver;
567 :
568 : /* -------------------------------------------------------------------- */
569 : /* It has no effect to register a driver more than once. */
570 : /* -------------------------------------------------------------------- */
571 294381 : for( iDriver = 0; iDriver < nDrivers; iDriver++ )
572 : {
573 284402 : if( poDriver == papoDrivers[iDriver] )
574 : return;
575 :
576 : /* Same name but different pointer. Likely a second call to OGRRegisterAll() */
577 : /* We delete the new driver */
578 284402 : if (EQUAL(poDriver->GetName(), papoDrivers[iDriver]->GetName()))
579 : {
580 171 : delete poDriver;
581 : return;
582 : }
583 : }
584 :
585 : /* -------------------------------------------------------------------- */
586 : /* Skip and destroy drivers in the black list. */
587 : /* -------------------------------------------------------------------- */
588 : char** papszSkipDrivers =
589 9979 : CSLTokenizeStringComplex(CPLGetConfigOption("OGR_SKIP", ""), ",", FALSE, FALSE);
590 9979 : char** iter = papszSkipDrivers;
591 20070 : while(*iter)
592 : {
593 114 : if (strcmp(*iter, poDriver->GetName()) == 0)
594 : {
595 2 : CSLDestroy(papszSkipDrivers);
596 2 : delete poDriver;
597 : return;
598 : }
599 112 : iter ++;
600 : }
601 9977 : CSLDestroy(papszSkipDrivers);
602 :
603 : /* -------------------------------------------------------------------- */
604 : /* Add to the end of the driver list. */
605 : /* -------------------------------------------------------------------- */
606 : papoDrivers = (OGRSFDriver **)
607 9977 : CPLRealloc( papoDrivers, (nDrivers+1) * sizeof(void*) );
608 :
609 9977 : papoDrivers[nDrivers++] = poDriver;
610 : }
611 :
612 : /************************************************************************/
613 : /* OGRRegisterDriver() */
614 : /************************************************************************/
615 :
616 4 : void OGRRegisterDriver( OGRSFDriverH hDriver )
617 :
618 : {
619 4 : VALIDATE_POINTER0( hDriver, "OGRRegisterDriver" );
620 :
621 : OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(
622 4 : (OGRSFDriver *) hDriver );
623 : }
624 :
625 : /************************************************************************/
626 : /* DeregisterDriver() */
627 : /************************************************************************/
628 :
629 4 : void OGRSFDriverRegistrar::DeregisterDriver( OGRSFDriver * poDriver )
630 :
631 : {
632 4 : CPLMutexHolderD( &hDRMutex );
633 : int i;
634 :
635 81 : for( i = 0; i < nDrivers; i++ )
636 : {
637 81 : if( poDriver == papoDrivers[i] )
638 4 : break;
639 : }
640 :
641 4 : if (i == nDrivers)
642 : return;
643 :
644 155 : while( i < nDrivers-1 )
645 : {
646 147 : papoDrivers[i] = papoDrivers[i+1];
647 147 : i++;
648 : }
649 4 : nDrivers--;
650 : }
651 :
652 : /************************************************************************/
653 : /* OGRDeregisterDriver() */
654 : /************************************************************************/
655 :
656 4 : void OGRDeregisterDriver( OGRSFDriverH hDriver )
657 :
658 : {
659 4 : VALIDATE_POINTER0( hDriver, "OGRDeregisterDriver" );
660 :
661 : OGRSFDriverRegistrar::GetRegistrar()->DeregisterDriver(
662 4 : (OGRSFDriver *) hDriver );
663 : }
664 :
665 : /************************************************************************/
666 : /* GetDriverCount() */
667 : /************************************************************************/
668 :
669 48 : int OGRSFDriverRegistrar::GetDriverCount()
670 :
671 : {
672 48 : return nDrivers;
673 : }
674 :
675 : /************************************************************************/
676 : /* OGRGetDriverCount() */
677 : /************************************************************************/
678 :
679 46 : int OGRGetDriverCount()
680 :
681 : {
682 46 : if (poRegistrar)
683 44 : return poRegistrar->GetDriverCount();
684 :
685 2 : return 0;
686 : }
687 :
688 : /************************************************************************/
689 : /* GetDriver() */
690 : /************************************************************************/
691 :
692 4 : OGRSFDriver *OGRSFDriverRegistrar::GetDriver( int iDriver )
693 :
694 : {
695 4 : CPLMutexHolderD( &hDRMutex );
696 :
697 4 : if( iDriver < 0 || iDriver >= nDrivers )
698 0 : return NULL;
699 : else
700 4 : return papoDrivers[iDriver];
701 : }
702 :
703 : /************************************************************************/
704 : /* OGRGetDriver() */
705 : /************************************************************************/
706 :
707 0 : OGRSFDriverH OGRGetDriver( int iDriver )
708 :
709 : {
710 0 : VALIDATE_POINTER1( poRegistrar, "OGRGetDriver", NULL );
711 :
712 0 : return (OGRSFDriverH) poRegistrar->GetDriver( iDriver );
713 : }
714 :
715 : /************************************************************************/
716 : /* GetDriverByName() */
717 : /************************************************************************/
718 :
719 464 : OGRSFDriver *OGRSFDriverRegistrar::GetDriverByName( const char * pszName )
720 :
721 : {
722 464 : CPLMutexHolderD( &hDRMutex );
723 :
724 4388 : for( int i = 0; i < nDrivers; i++ )
725 : {
726 13152 : if( papoDrivers[i] != NULL
727 8768 : && EQUAL(papoDrivers[i]->GetName(),pszName) )
728 460 : return papoDrivers[i];
729 : }
730 :
731 4 : return NULL;
732 : }
733 :
734 : /************************************************************************/
735 : /* OGRGetDriverByName() */
736 : /************************************************************************/
737 :
738 394 : OGRSFDriverH OGRGetDriverByName( const char *pszName )
739 :
740 : {
741 394 : VALIDATE_POINTER1( pszName, "OGRGetDriverByName", NULL );
742 :
743 : return (OGRSFDriverH)
744 394 : OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName( pszName );
745 : }
746 :
747 : /************************************************************************/
748 : /* AutoLoadDrivers() */
749 : /************************************************************************/
750 :
751 : /**
752 : * \brief Auto-load GDAL drivers from shared libraries.
753 : *
754 : * This function will automatically load drivers from shared libraries. It
755 : * searches the "driver path" for .so (or .dll) files that start with the
756 : * prefix "ogr_X.so". It then tries to load them and then tries to call
757 : * a function within them called RegisterOGRX() where the 'X' is the same
758 : * as the remainder of the shared library basename, or failing that to
759 : * call GDALRegisterMe().
760 : *
761 : * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
762 : * environment variable it set, it is taken to be a list of directories to
763 : * search separated by colons on unix, or semi-colons on Windows.
764 : *
765 : * If that is not set the following defaults are used:
766 : *
767 : * <ul>
768 : * <li> Linux/Unix: <prefix>/lib/gdalplugins is searched or
769 : * /usr/local/lib/gdalplugins if the install prefix is not known.
770 : * <li> MacOSX: <prefix>/PlugIns is searched, or /usr/local/lib/gdalplugins if
771 : * the install prefix is not known. Also, the framework directory
772 : * /Library/Application Support/GDAL/PlugIns is searched.
773 : * <li> Win32: <prefix>/lib/gdalplugins if the prefix is known (normally it
774 : * is not), otherwise the gdalplugins subdirectory of the directory containing
775 : * the currently running executable is used.
776 : * </ul>
777 : */
778 :
779 178 : void OGRSFDriverRegistrar::AutoLoadDrivers()
780 :
781 : {
782 178 : char **papszSearchPath = NULL;
783 : const char *pszGDAL_DRIVER_PATH =
784 178 : CPLGetConfigOption( "OGR_DRIVER_PATH", NULL );
785 :
786 178 : if( pszGDAL_DRIVER_PATH == NULL )
787 : pszGDAL_DRIVER_PATH =
788 178 : CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
789 :
790 : /* -------------------------------------------------------------------- */
791 : /* Where should we look for stuff? */
792 : /* -------------------------------------------------------------------- */
793 178 : if( pszGDAL_DRIVER_PATH != NULL )
794 : {
795 : #ifdef WIN32
796 : papszSearchPath =
797 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
798 : #else
799 : papszSearchPath =
800 0 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
801 : #endif
802 : }
803 : else
804 : {
805 : #ifdef GDAL_PREFIX
806 : papszSearchPath = CSLAddString( papszSearchPath,
807 : #ifdef MACOSX_FRAMEWORK
808 : GDAL_PREFIX "/PlugIns");
809 : #else
810 178 : GDAL_PREFIX "/lib/gdalplugins" );
811 : #endif
812 : #else
813 : char szExecPath[1024];
814 :
815 : if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
816 : {
817 : char szPluginDir[sizeof(szExecPath)+50];
818 : strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
819 : strcat( szPluginDir, "\\gdalplugins\\" );
820 : papszSearchPath = CSLAddString( papszSearchPath, szPluginDir );
821 : }
822 : else
823 : {
824 : papszSearchPath = CSLAddString( papszSearchPath,
825 : "/usr/local/lib/gdalplugins" );
826 : }
827 : #endif
828 :
829 : #ifdef MACOSX_FRAMEWORK
830 : #define num2str(x) str(x)
831 : #define str(x) #x
832 : papszSearchPath = CSLAddString( papszSearchPath,
833 : "/Library/Application Support/GDAL/"
834 : num2str(GDAL_VERSION_MAJOR) "."
835 : num2str(GDAL_VERSION_MINOR) "/PlugIns" );
836 : #endif
837 :
838 : }
839 :
840 : /* -------------------------------------------------------------------- */
841 : /* Format the ABI version specific subdirectory to look in. */
842 : /* -------------------------------------------------------------------- */
843 178 : CPLString osABIVersion;
844 :
845 178 : osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
846 :
847 : /* -------------------------------------------------------------------- */
848 : /* Scan each directory looking for files starting with ogr_ */
849 : /* -------------------------------------------------------------------- */
850 356 : for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
851 : {
852 178 : char **papszFiles = NULL;
853 : VSIStatBufL sStatBuf;
854 : CPLString osABISpecificDir =
855 178 : CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
856 :
857 178 : if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
858 178 : osABISpecificDir = papszSearchPath[iDir];
859 :
860 178 : papszFiles = CPLReadDir( osABISpecificDir );
861 :
862 178 : for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
863 : {
864 : char *pszFuncName;
865 : const char *pszFilename;
866 0 : const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
867 : void *pRegister;
868 :
869 0 : if( !EQUALN(papszFiles[iFile],"ogr_",4) )
870 0 : continue;
871 :
872 0 : if( !EQUAL(pszExtension,"dll")
873 : && !EQUAL(pszExtension,"so")
874 : && !EQUAL(pszExtension,"dylib") )
875 0 : continue;
876 :
877 0 : pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
878 : sprintf( pszFuncName, "RegisterOGR%s",
879 0 : CPLGetBasename(papszFiles[iFile]) + 4 );
880 :
881 : pszFilename =
882 : CPLFormFilename( osABISpecificDir,
883 0 : papszFiles[iFile], NULL );
884 :
885 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
886 0 : if( pRegister == NULL )
887 : {
888 0 : strcpy( pszFuncName, "GDALRegisterMe" );
889 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
890 : }
891 :
892 0 : if( pRegister != NULL )
893 : {
894 : CPLDebug( "OGR", "Auto register %s using %s.",
895 0 : pszFilename, pszFuncName );
896 :
897 0 : ((void (*)()) pRegister)();
898 : }
899 :
900 0 : CPLFree( pszFuncName );
901 : }
902 :
903 178 : CSLDestroy( papszFiles );
904 : }
905 :
906 178 : CSLDestroy( papszSearchPath );
907 178 : }
908 :
|