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