1 : /******************************************************************************
2 : * $Id: gdaldrivermanager.cpp 23175 2011-10-04 21:28:28Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALDriverManager class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, Frank Warmerdam
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 "gdal_priv.h"
31 : #include "cpl_string.h"
32 : #include "cpl_multiproc.h"
33 : #include "ogr_srs_api.h"
34 : #include "cpl_multiproc.h"
35 : #include "gdal_pam.h"
36 :
37 : CPL_CVSID("$Id: gdaldrivermanager.cpp 23175 2011-10-04 21:28:28Z rouault $");
38 :
39 : static const char *pszUpdatableINST_DATA =
40 : "__INST_DATA_TARGET: ";
41 :
42 : /************************************************************************/
43 : /* ==================================================================== */
44 : /* GDALDriverManager */
45 : /* ==================================================================== */
46 : /************************************************************************/
47 :
48 : static volatile GDALDriverManager *poDM = NULL;
49 : static void *hDMMutex = NULL;
50 :
51 : /************************************************************************/
52 : /* GetGDALDriverManager() */
53 : /* */
54 : /* A freestanding function to get the only instance of the */
55 : /* GDALDriverManager. */
56 : /************************************************************************/
57 :
58 : /**
59 : * \brief Fetch the global GDAL driver manager.
60 : *
61 : * This function fetches the pointer to the singleton global driver manager.
62 : * If the driver manager doesn't exist it is automatically created.
63 : *
64 : * @return pointer to the global driver manager. This should not be able
65 : * to fail.
66 : */
67 :
68 162214 : GDALDriverManager * GetGDALDriverManager()
69 :
70 : {
71 162214 : if( poDM == NULL )
72 : {
73 537 : CPLMutexHolderD( &hDMMutex );
74 :
75 537 : if( poDM == NULL )
76 537 : poDM = new GDALDriverManager();
77 : }
78 :
79 162214 : CPLAssert( NULL != poDM );
80 :
81 162214 : return const_cast<GDALDriverManager *>( poDM );
82 : }
83 :
84 : /************************************************************************/
85 : /* GDALDriverManager() */
86 : /************************************************************************/
87 :
88 537 : GDALDriverManager::GDALDriverManager()
89 :
90 : {
91 537 : nDrivers = 0;
92 537 : papoDrivers = NULL;
93 537 : pszHome = CPLStrdup("");
94 :
95 537 : CPLAssert( poDM == NULL );
96 :
97 : /* -------------------------------------------------------------------- */
98 : /* We want to push a location to search for data files */
99 : /* supporting GDAL/OGR such as EPSG csv files, S-57 definition */
100 : /* files, and so forth. The static pszUpdateableINST_DATA */
101 : /* string can be updated within the shared library or */
102 : /* executable during an install to point installed data */
103 : /* directory. If it isn't burned in here then we use the */
104 : /* INST_DATA macro (setup at configure time) if */
105 : /* available. Otherwise we don't push anything and we hope */
106 : /* other mechanisms such as environment variables will have */
107 : /* been employed. */
108 : /* -------------------------------------------------------------------- */
109 537 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
110 : {
111 : // this one is picked up automatically by finder initialization.
112 : }
113 0 : else if( pszUpdatableINST_DATA[19] != ' ' )
114 : {
115 0 : CPLPushFinderLocation( pszUpdatableINST_DATA + 19 );
116 : }
117 : else
118 : {
119 : #ifdef INST_DATA
120 0 : CPLPushFinderLocation( INST_DATA );
121 : #endif
122 : }
123 537 : }
124 :
125 : /************************************************************************/
126 : /* ~GDALDriverManager() */
127 : /************************************************************************/
128 :
129 : void GDALDatasetPoolPreventDestroy(); /* keep that in sync with gdalproxypool.cpp */
130 : void GDALDatasetPoolForceDestroy(); /* keep that in sync with gdalproxypool.cpp */
131 :
132 522 : GDALDriverManager::~GDALDriverManager()
133 :
134 : {
135 : /* -------------------------------------------------------------------- */
136 : /* Cleanup any open datasets. */
137 : /* -------------------------------------------------------------------- */
138 : int i, nDSCount;
139 : GDALDataset **papoDSList;
140 :
141 : /* First begin by requesting each reamining dataset to drop any reference */
142 : /* to other datasets */
143 : int bHasDroppedRef;
144 :
145 : /* We have to prevent the destroying of the dataset pool during this first */
146 : /* phase, otherwise it cause crashes with a VRT B referencing a VRT A, and if */
147 : /* CloseDependentDatasets() is called first on VRT A. */
148 : /* If we didn't do this nasty trick, due to the refCountOfDisableRefCount */
149 : /* mechanism that cheats the real refcount of the dataset pool, we might */
150 : /* destroy the dataset pool too early, leading the VRT A to */
151 : /* destroy itself indirectly ... Ok, I am aware this explanation does */
152 : /* not make any sense unless you try it under a debugger ... */
153 : /* When people just manipulate "top-level" dataset handles, we luckily */
154 : /* don't need this horrible hack, but GetOpenDatasets() expose "low-level" */
155 : /* datasets, which defeat some "design" of the proxy pool */
156 522 : GDALDatasetPoolPreventDestroy();
157 :
158 522 : do
159 : {
160 522 : papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
161 : /* If a dataset has dropped a reference, the list might have become */
162 : /* invalid, so go out of the loop and try again with the new valid */
163 : /* list */
164 522 : bHasDroppedRef = FALSE;
165 524 : for(i=0;i<nDSCount && !bHasDroppedRef;i++)
166 : {
167 : //CPLDebug("GDAL", "Call CloseDependentDatasets() on %s",
168 : // papoDSList[i]->GetDescription() );
169 2 : bHasDroppedRef = papoDSList[i]->CloseDependentDatasets();
170 : }
171 : } while(bHasDroppedRef);
172 :
173 : /* Now let's destroy the dataset pool. Nobody shoud use it afterwards */
174 : /* if people have well released their dependent datasets above */
175 522 : GDALDatasetPoolForceDestroy();
176 :
177 : /* Now close the stand-alone datasets */
178 522 : papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
179 524 : for(i=0;i<nDSCount;i++)
180 : {
181 : CPLDebug( "GDAL", "force close of %s in GDALDriverManager cleanup.",
182 2 : papoDSList[i]->GetDescription() );
183 : /* Destroy with delete operator rather than GDALClose() to force deletion of */
184 : /* datasets with multiple reference count */
185 : /* We could also iterate while GetOpenDatasets() returns a non NULL list */
186 2 : delete papoDSList[i];
187 : }
188 :
189 : /* -------------------------------------------------------------------- */
190 : /* Destroy the existing drivers. */
191 : /* -------------------------------------------------------------------- */
192 65249 : while( GetDriverCount() > 0 )
193 : {
194 64205 : GDALDriver *poDriver = GetDriver(0);
195 :
196 64205 : DeregisterDriver(poDriver);
197 64205 : delete poDriver;
198 : }
199 :
200 : /* -------------------------------------------------------------------- */
201 : /* Cleanup local memory. */
202 : /* -------------------------------------------------------------------- */
203 522 : VSIFree( papoDrivers );
204 522 : VSIFree( pszHome );
205 :
206 : /* -------------------------------------------------------------------- */
207 : /* Cleanup any Proxy related memory. */
208 : /* -------------------------------------------------------------------- */
209 522 : PamCleanProxyDB();
210 :
211 : /* -------------------------------------------------------------------- */
212 : /* Blow away all the finder hints paths. We really shouldn't */
213 : /* be doing all of them, but it is currently hard to keep track */
214 : /* of those that actually belong to us. */
215 : /* -------------------------------------------------------------------- */
216 522 : CPLFinderClean();
217 522 : CPLFreeConfig();
218 :
219 : /* -------------------------------------------------------------------- */
220 : /* Cleanup any memory allocated by the OGRSpatialReference */
221 : /* related subsystem. */
222 : /* -------------------------------------------------------------------- */
223 522 : OSRCleanup();
224 :
225 : /* -------------------------------------------------------------------- */
226 : /* Cleanup VSIFileManager. */
227 : /* -------------------------------------------------------------------- */
228 522 : VSICleanupFileManager();
229 :
230 : /* -------------------------------------------------------------------- */
231 : /* Cleanup thread local storage ... I hope the program is all */
232 : /* done with GDAL/OGR! */
233 : /* -------------------------------------------------------------------- */
234 522 : CPLCleanupTLS();
235 :
236 : /* -------------------------------------------------------------------- */
237 : /* Cleanup our mutex. */
238 : /* -------------------------------------------------------------------- */
239 522 : if( hDMMutex )
240 : {
241 522 : CPLDestroyMutex( hDMMutex );
242 522 : hDMMutex = NULL;
243 : }
244 :
245 : /* -------------------------------------------------------------------- */
246 : /* Ensure the global driver manager pointer is NULLed out. */
247 : /* -------------------------------------------------------------------- */
248 522 : if( poDM == this )
249 522 : poDM = NULL;
250 522 : }
251 :
252 : /************************************************************************/
253 : /* GetDriverCount() */
254 : /************************************************************************/
255 :
256 : /**
257 : * \brief Fetch the number of registered drivers.
258 : *
259 : * This C analog to this is GDALGetDriverCount().
260 : *
261 : * @return the number of registered drivers.
262 : */
263 :
264 1515810 : int GDALDriverManager::GetDriverCount()
265 :
266 : {
267 1515810 : return( nDrivers );
268 : }
269 :
270 : /************************************************************************/
271 : /* GDALGetDriverCount() */
272 : /************************************************************************/
273 :
274 : /**
275 : * \brief Fetch the number of registered drivers.
276 : *
277 : * @see GDALDriverManager::GetDriverCount()
278 : */
279 :
280 371 : int CPL_STDCALL GDALGetDriverCount()
281 :
282 : {
283 371 : return GetGDALDriverManager()->GetDriverCount();
284 : }
285 :
286 : /************************************************************************/
287 : /* GetDriver() */
288 : /************************************************************************/
289 :
290 : /**
291 : * \brief Fetch driver by index.
292 : *
293 : * This C analog to this is GDALGetDriver().
294 : *
295 : * @param iDriver the driver index from 0 to GetDriverCount()-1.
296 : *
297 : * @return the driver identified by the index or NULL if the index is invalid
298 : */
299 :
300 1507582 : GDALDriver * GDALDriverManager::GetDriver( int iDriver )
301 :
302 : {
303 1507582 : CPLMutexHolderD( &hDMMutex );
304 :
305 1507582 : if( iDriver < 0 || iDriver >= nDrivers )
306 0 : return NULL;
307 : else
308 1507582 : return papoDrivers[iDriver];
309 : }
310 :
311 : /************************************************************************/
312 : /* GDALGetDriver() */
313 : /************************************************************************/
314 :
315 : /**
316 : * \brief Fetch driver by index.
317 : *
318 : * @see GDALDriverManager::GetDriver()
319 : */
320 :
321 3051 : GDALDriverH CPL_STDCALL GDALGetDriver( int iDriver )
322 :
323 : {
324 3051 : return (GDALDriverH) GetGDALDriverManager()->GetDriver(iDriver);
325 : }
326 :
327 : /************************************************************************/
328 : /* RegisterDriver() */
329 : /************************************************************************/
330 :
331 : /**
332 : * \brief Register a driver for use.
333 : *
334 : * The C analog is GDALRegisterDriver().
335 : *
336 : * Normally this method is used by format specific C callable registration
337 : * entry points such as GDALRegister_GTiff() rather than being called
338 : * directly by application level code.
339 : *
340 : * If this driver (based on the object pointer, not short name) is already
341 : * registered, then no change is made, and the index of the existing driver
342 : * is returned. Otherwise the driver list is extended, and the new driver
343 : * is added at the end.
344 : *
345 : * @param poDriver the driver to register.
346 : *
347 : * @return the index of the new installed driver.
348 : */
349 :
350 66127 : int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
351 :
352 : {
353 66127 : CPLMutexHolderD( &hDMMutex );
354 :
355 : /* -------------------------------------------------------------------- */
356 : /* If it is already registered, just return the existing */
357 : /* index. */
358 : /* -------------------------------------------------------------------- */
359 66127 : if( GetDriverByName( poDriver->GetDescription() ) != NULL )
360 : {
361 : int i;
362 :
363 363 : for( i = 0; i < nDrivers; i++ )
364 : {
365 363 : if( papoDrivers[i] == poDriver )
366 : {
367 3 : return i;
368 : }
369 : }
370 :
371 0 : CPLAssert( FALSE );
372 : }
373 :
374 : /* -------------------------------------------------------------------- */
375 : /* Otherwise grow the list to hold the new entry. */
376 : /* -------------------------------------------------------------------- */
377 : papoDrivers = (GDALDriver **)
378 66124 : VSIRealloc(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1));
379 :
380 66124 : papoDrivers[nDrivers] = poDriver;
381 66124 : nDrivers++;
382 :
383 66124 : if( poDriver->pfnCreate != NULL )
384 18811 : poDriver->SetMetadataItem( GDAL_DCAP_CREATE, "YES" );
385 :
386 66124 : if( poDriver->pfnCreateCopy != NULL )
387 21533 : poDriver->SetMetadataItem( GDAL_DCAP_CREATECOPY, "YES" );
388 :
389 66124 : int iResult = nDrivers - 1;
390 :
391 66124 : return iResult;
392 : }
393 :
394 : /************************************************************************/
395 : /* GDALRegisterDriver() */
396 : /************************************************************************/
397 :
398 : /**
399 : * \brief Register a driver for use.
400 : *
401 : * @see GDALDriverManager::GetRegisterDriver()
402 : */
403 :
404 75 : int CPL_STDCALL GDALRegisterDriver( GDALDriverH hDriver )
405 :
406 : {
407 75 : VALIDATE_POINTER1( hDriver, "GDALRegisterDriver", 0 );
408 :
409 75 : return GetGDALDriverManager()->RegisterDriver( (GDALDriver *) hDriver );
410 : }
411 :
412 :
413 : /************************************************************************/
414 : /* DeregisterDriver() */
415 : /************************************************************************/
416 :
417 : /**
418 : * \brief Deregister the passed driver.
419 : *
420 : * If the driver isn't found no change is made.
421 : *
422 : * The C analog is GDALDeregisterDriver().
423 : *
424 : * @param poDriver the driver to deregister.
425 : */
426 :
427 64279 : void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
428 :
429 : {
430 : int i;
431 64279 : CPLMutexHolderD( &hDMMutex );
432 :
433 72602 : for( i = 0; i < nDrivers; i++ )
434 : {
435 72602 : if( papoDrivers[i] == poDriver )
436 64279 : break;
437 : }
438 :
439 64279 : if( i == nDrivers )
440 : return;
441 :
442 4045711 : while( i < nDrivers-1 )
443 : {
444 3917153 : papoDrivers[i] = papoDrivers[i+1];
445 3917153 : i++;
446 : }
447 64279 : nDrivers--;
448 : }
449 :
450 : /************************************************************************/
451 : /* GDALDeregisterDriver() */
452 : /************************************************************************/
453 :
454 : /**
455 : * \brief Deregister the passed driver.
456 : *
457 : * @see GDALDriverManager::GetDeregisterDriver()
458 : */
459 :
460 72 : void CPL_STDCALL GDALDeregisterDriver( GDALDriverH hDriver )
461 :
462 : {
463 72 : VALIDATE_POINTER0( hDriver, "GDALDeregisterDriver" );
464 :
465 72 : GetGDALDriverManager()->DeregisterDriver( (GDALDriver *) hDriver );
466 : }
467 :
468 :
469 : /************************************************************************/
470 : /* GetDriverByName() */
471 : /************************************************************************/
472 :
473 : /**
474 : * \brief Fetch a driver based on the short name.
475 : *
476 : * The C analog is the GDALGetDriverByName() function.
477 : *
478 : * @param pszName the short name, such as GTiff, being searched for.
479 : *
480 : * @return the identified driver, or NULL if no match is found.
481 : */
482 :
483 139817 : GDALDriver * GDALDriverManager::GetDriverByName( const char * pszName )
484 :
485 : {
486 : int i;
487 :
488 139817 : CPLMutexHolderD( &hDMMutex );
489 :
490 8470818 : for( i = 0; i < nDrivers; i++ )
491 : {
492 8338603 : if( EQUAL(papoDrivers[i]->GetDescription(), pszName) )
493 7602 : return papoDrivers[i];
494 : }
495 :
496 132215 : return NULL;
497 : }
498 :
499 : /************************************************************************/
500 : /* GDALGetDriverByName() */
501 : /************************************************************************/
502 :
503 : /**
504 : * \brief Fetch a driver based on the short name.
505 : *
506 : * @see GDALDriverManager::GetDriverByName()
507 : */
508 :
509 73639 : GDALDriverH CPL_STDCALL GDALGetDriverByName( const char * pszName )
510 :
511 : {
512 73639 : VALIDATE_POINTER1( pszName, "GDALGetDriverByName", NULL );
513 :
514 73639 : return( GetGDALDriverManager()->GetDriverByName( pszName ) );
515 : }
516 :
517 : /************************************************************************/
518 : /* GetHome() */
519 : /************************************************************************/
520 :
521 558 : const char *GDALDriverManager::GetHome()
522 :
523 : {
524 558 : return pszHome;
525 : }
526 :
527 : /************************************************************************/
528 : /* SetHome() */
529 : /************************************************************************/
530 :
531 0 : void GDALDriverManager::SetHome( const char * pszNewHome )
532 :
533 : {
534 0 : CPLMutexHolderD( &hDMMutex );
535 :
536 0 : CPLFree( pszHome );
537 0 : pszHome = CPLStrdup(pszNewHome);
538 0 : }
539 :
540 : /************************************************************************/
541 : /* AutoSkipDrivers() */
542 : /************************************************************************/
543 :
544 : /**
545 : * \brief This method unload undesirable drivers.
546 : *
547 : * All drivers specified in the space delimited list in the GDAL_SKIP
548 : * environment variable) will be deregistered and destroyed. This method
549 : * should normally be called after registration of standard drivers to allow
550 : * the user a way of unloading undesired drivers. The GDALAllRegister()
551 : * function already invokes AutoSkipDrivers() at the end, so if that functions
552 : * is called, it should not be necessary to call this method from application
553 : * code.
554 : */
555 :
556 558 : void GDALDriverManager::AutoSkipDrivers()
557 :
558 : {
559 558 : if( CPLGetConfigOption( "GDAL_SKIP", NULL ) == NULL )
560 557 : return;
561 :
562 1 : char **papszList = CSLTokenizeString( CPLGetConfigOption("GDAL_SKIP","") );
563 :
564 4 : for( int i = 0; i < CSLCount(papszList); i++ )
565 : {
566 3 : GDALDriver *poDriver = GetDriverByName( papszList[i] );
567 :
568 3 : if( poDriver == NULL )
569 : CPLError( CE_Warning, CPLE_AppDefined,
570 : "Unable to find driver %s to unload from GDAL_SKIP environment variable.",
571 1 : papszList[i] );
572 : else
573 : {
574 2 : CPLDebug( "GDAL", "AutoSkipDriver(%s)", papszList[i] );
575 2 : DeregisterDriver( poDriver );
576 2 : delete poDriver;
577 : }
578 : }
579 :
580 1 : CSLDestroy( papszList );
581 : }
582 :
583 : /************************************************************************/
584 : /* AutoLoadDrivers() */
585 : /************************************************************************/
586 :
587 : /**
588 : * \brief Auto-load GDAL drivers from shared libraries.
589 : *
590 : * This function will automatically load drivers from shared libraries. It
591 : * searches the "driver path" for .so (or .dll) files that start with the
592 : * prefix "gdal_X.so". It then tries to load them and then tries to call a
593 : * function within them called GDALRegister_X() where the 'X' is the same as
594 : * the remainder of the shared library basename ('X' is case sensitive), or
595 : * failing that to call GDALRegisterMe().
596 : *
597 : * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
598 : * environment variable it set, it is taken to be a list of directories to
599 : * search separated by colons on UNIX, or semi-colons on Windows. Otherwise
600 : * the /usr/local/lib/gdalplugins directory, and (if known) the
601 : * lib/gdalplugins subdirectory of the gdal home directory are searched on
602 : * UNIX and $(BINDIR)\gdalplugins on Windows.
603 : */
604 :
605 558 : void GDALDriverManager::AutoLoadDrivers()
606 :
607 : {
608 558 : char **papszSearchPath = NULL;
609 : const char *pszGDAL_DRIVER_PATH =
610 558 : CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
611 :
612 : /* -------------------------------------------------------------------- */
613 : /* Where should we look for stuff? */
614 : /* -------------------------------------------------------------------- */
615 558 : if( pszGDAL_DRIVER_PATH != NULL )
616 : {
617 : #ifdef WIN32
618 : papszSearchPath =
619 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
620 : #else
621 : papszSearchPath =
622 0 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
623 : #endif
624 : }
625 : else
626 : {
627 : #ifdef GDAL_PREFIX
628 : papszSearchPath = CSLAddString( papszSearchPath,
629 : #ifdef MACOSX_FRAMEWORK
630 : GDAL_PREFIX "/PlugIns");
631 : #else
632 558 : GDAL_PREFIX "/lib/gdalplugins" );
633 : #endif
634 : #else
635 : char szExecPath[1024];
636 :
637 : if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
638 : {
639 : char szPluginDir[sizeof(szExecPath)+50];
640 : strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
641 : strcat( szPluginDir, "\\gdalplugins" );
642 : papszSearchPath = CSLAddString( papszSearchPath, szPluginDir );
643 : }
644 : else
645 : {
646 : papszSearchPath = CSLAddString( papszSearchPath,
647 : "/usr/local/lib/gdalplugins" );
648 : }
649 : #endif
650 :
651 : #ifdef MACOSX_FRAMEWORK
652 : #define num2str(x) str(x)
653 : #define str(x) #x
654 : papszSearchPath = CSLAddString( papszSearchPath,
655 : "/Library/Application Support/GDAL/"
656 : num2str(GDAL_VERSION_MAJOR) "."
657 : num2str(GDAL_VERSION_MINOR) "/PlugIns" );
658 : #endif
659 :
660 :
661 558 : if( strlen(GetHome()) > 0 )
662 : {
663 : papszSearchPath = CSLAddString( papszSearchPath,
664 : CPLFormFilename( GetHome(),
665 : #ifdef MACOSX_FRAMEWORK
666 : "/Library/Application Support/GDAL/"
667 : num2str(GDAL_VERSION_MAJOR) "."
668 : num2str(GDAL_VERSION_MINOR) "/PlugIns", NULL ) );
669 : #else
670 0 : "lib/gdalplugins", NULL ) );
671 : #endif
672 : }
673 : }
674 :
675 : /* -------------------------------------------------------------------- */
676 : /* Format the ABI version specific subdirectory to look in. */
677 : /* -------------------------------------------------------------------- */
678 558 : CPLString osABIVersion;
679 :
680 558 : osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
681 :
682 : /* -------------------------------------------------------------------- */
683 : /* Scan each directory looking for files starting with gdal_ */
684 : /* -------------------------------------------------------------------- */
685 1116 : for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
686 : {
687 558 : char **papszFiles = NULL;
688 : VSIStatBufL sStatBuf;
689 : CPLString osABISpecificDir =
690 558 : CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
691 :
692 558 : if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
693 558 : osABISpecificDir = papszSearchPath[iDir];
694 :
695 558 : papszFiles = CPLReadDir( osABISpecificDir );
696 :
697 558 : for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
698 : {
699 : char *pszFuncName;
700 : const char *pszFilename;
701 0 : const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
702 : void *pRegister;
703 :
704 0 : if( !EQUALN(papszFiles[iFile],"gdal_",5) )
705 0 : continue;
706 :
707 0 : if( !EQUAL(pszExtension,"dll")
708 : && !EQUAL(pszExtension,"so")
709 : && !EQUAL(pszExtension,"dylib") )
710 0 : continue;
711 :
712 0 : pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
713 : sprintf( pszFuncName, "GDALRegister_%s",
714 0 : CPLGetBasename(papszFiles[iFile]) + 5 );
715 :
716 : pszFilename =
717 : CPLFormFilename( osABISpecificDir,
718 0 : papszFiles[iFile], NULL );
719 :
720 0 : CPLErrorReset();
721 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
722 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
723 0 : CPLPopErrorHandler();
724 0 : if( pRegister == NULL )
725 : {
726 0 : CPLString osLastErrorMsg(CPLGetLastErrorMsg());
727 0 : strcpy( pszFuncName, "GDALRegisterMe" );
728 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
729 0 : if( pRegister == NULL )
730 : {
731 : CPLError( CE_Failure, CPLE_AppDefined,
732 0 : "%s", osLastErrorMsg.c_str() );
733 0 : }
734 : }
735 :
736 0 : if( pRegister != NULL )
737 : {
738 : CPLDebug( "GDAL", "Auto register %s using %s.",
739 0 : pszFilename, pszFuncName );
740 :
741 0 : ((void (*)()) pRegister)();
742 : }
743 :
744 0 : CPLFree( pszFuncName );
745 : }
746 :
747 558 : CSLDestroy( papszFiles );
748 : }
749 :
750 558 : CSLDestroy( papszSearchPath );
751 558 : }
752 :
753 : /************************************************************************/
754 : /* GDALDestroyDriverManager() */
755 : /************************************************************************/
756 :
757 : /**
758 : * \brief Destroy the driver manager.
759 : *
760 : * Incidently unloads all managed drivers.
761 : *
762 : * NOTE: This function is not thread safe. It should not be called while
763 : * other threads are actively using GDAL.
764 : */
765 :
766 522 : void CPL_STDCALL GDALDestroyDriverManager( void )
767 :
768 : {
769 : // THREADSAFETY: We would like to lock the mutex here, but it
770 : // needs to be reacquired within the destructor during driver
771 : // deregistration.
772 522 : if( poDM != NULL )
773 522 : delete poDM;
774 522 : }
775 :
776 :
|