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