1 /******************************************************************************
2 * $Id: gdaldrivermanager.cpp 29330 2015-06-14 12:11:11Z 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 * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "gdal_priv.h"
32 #include "cpl_string.h"
33 #include "cpl_multiproc.h"
34 #include "ogr_srs_api.h"
35 #include "cpl_multiproc.h"
36 #include "gdal_pam.h"
37 #include "gdal_alg_priv.h"
38
39 #ifdef _MSC_VER
40 # ifdef MSVC_USE_VLD
41 # include <wchar.h>
42 # include <vld.h>
43 # endif
44 #endif
45
46 CPL_CVSID("$Id: gdaldrivermanager.cpp 29330 2015-06-14 12:11:11Z rouault $");
47
48 static const char *pszUpdatableINST_DATA =
49 "__INST_DATA_TARGET: ";
50
51 /************************************************************************/
52 /* ==================================================================== */
53 /* GDALDriverManager */
54 /* ==================================================================== */
55 /************************************************************************/
56
57 static volatile GDALDriverManager *poDM = NULL;
58 static CPLMutex *hDMMutex = NULL;
59
GDALGetphDMMutex()60 CPLMutex** GDALGetphDMMutex() { return &hDMMutex; }
61
62 /************************************************************************/
63 /* GetGDALDriverManager() */
64 /* */
65 /* A freestanding function to get the only instance of the */
66 /* GDALDriverManager. */
67 /************************************************************************/
68
69 /**
70 * \brief Fetch the global GDAL driver manager.
71 *
72 * This function fetches the pointer to the singleton global driver manager.
73 * If the driver manager doesn't exist it is automatically created.
74 *
75 * @return pointer to the global driver manager. This should not be able
76 * to fail.
77 */
78
GetGDALDriverManager()79 GDALDriverManager * GetGDALDriverManager()
80
81 {
82 if( poDM == NULL )
83 {
84 CPLMutexHolderD( &hDMMutex );
85
86 if( poDM == NULL )
87 poDM = new GDALDriverManager();
88 }
89
90 CPLAssert( NULL != poDM );
91
92 return const_cast<GDALDriverManager *>( poDM );
93 }
94
95 /************************************************************************/
96 /* GDALDriverManager() */
97 /************************************************************************/
98
GDALDriverManager()99 GDALDriverManager::GDALDriverManager()
100
101 {
102 nDrivers = 0;
103 papoDrivers = NULL;
104
105 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 if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
120 {
121 // this one is picked up automatically by finder initialization.
122 }
123 else if( pszUpdatableINST_DATA[19] != ' ' )
124 {
125 CPLPushFinderLocation( pszUpdatableINST_DATA + 19 );
126 }
127 else
128 {
129 #ifdef INST_DATA
130 CPLPushFinderLocation( INST_DATA );
131 #endif
132 }
133 }
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
~GDALDriverManager()142 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 GDALDatasetPoolPreventDestroy();
167
168 do
169 {
170 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 bHasDroppedRef = FALSE;
175 for(i=0;i<nDSCount && !bHasDroppedRef;i++)
176 {
177 //CPLDebug("GDAL", "Call CloseDependentDatasets() on %s",
178 // papoDSList[i]->GetDescription() );
179 bHasDroppedRef = papoDSList[i]->CloseDependentDatasets();
180 }
181 } while(bHasDroppedRef);
182
183 /* Now let's destroy the dataset pool. Nobody should use it afterwards */
184 /* if people have well released their dependent datasets above */
185 GDALDatasetPoolForceDestroy();
186
187 /* Now close the stand-alone datasets */
188 papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
189 for(i=0;i<nDSCount;i++)
190 {
191 CPLDebug( "GDAL", "force close of %s (%p) in GDALDriverManager cleanup.",
192 papoDSList[i]->GetDescription(), papoDSList[i] );
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 delete papoDSList[i];
197 }
198
199 /* -------------------------------------------------------------------- */
200 /* Destroy the existing drivers. */
201 /* -------------------------------------------------------------------- */
202 while( GetDriverCount() > 0 )
203 {
204 GDALDriver *poDriver = GetDriver(0);
205
206 DeregisterDriver(poDriver);
207 delete poDriver;
208 }
209
210 delete GDALGetAPIPROXYDriver();
211
212 /* -------------------------------------------------------------------- */
213 /* Cleanup local memory. */
214 /* -------------------------------------------------------------------- */
215 VSIFree( papoDrivers );
216
217 /* -------------------------------------------------------------------- */
218 /* Cleanup any Proxy related memory. */
219 /* -------------------------------------------------------------------- */
220 PamCleanProxyDB();
221
222 /* -------------------------------------------------------------------- */
223 /* Blow away all the finder hints paths. We really shouldn't */
224 /* be doing all of them, but it is currently hard to keep track */
225 /* of those that actually belong to us. */
226 /* -------------------------------------------------------------------- */
227 CPLFinderClean();
228 CPLFreeConfig();
229 CPLCleanupSharedFileMutex();
230
231 /* -------------------------------------------------------------------- */
232 /* Cleanup any memory allocated by the OGRSpatialReference */
233 /* related subsystem. */
234 /* -------------------------------------------------------------------- */
235 OSRCleanup();
236
237 /* -------------------------------------------------------------------- */
238 /* Cleanup VSIFileManager. */
239 /* -------------------------------------------------------------------- */
240 VSICleanupFileManager();
241
242 /* -------------------------------------------------------------------- */
243 /* Cleanup thread local storage ... I hope the program is all */
244 /* done with GDAL/OGR! */
245 /* -------------------------------------------------------------------- */
246 CPLCleanupTLS();
247
248 /* -------------------------------------------------------------------- */
249 /* Cleanup our mutex. */
250 /* -------------------------------------------------------------------- */
251 if( hDMMutex )
252 {
253 CPLDestroyMutex( hDMMutex );
254 hDMMutex = NULL;
255 }
256
257 /* -------------------------------------------------------------------- */
258 /* Cleanup dataset list mutex */
259 /* -------------------------------------------------------------------- */
260 if ( *GDALGetphDLMutex() != NULL )
261 {
262 CPLDestroyMutex( *GDALGetphDLMutex() );
263 *GDALGetphDLMutex() = NULL;
264 }
265
266 /* -------------------------------------------------------------------- */
267 /* Cleanup raster block mutex */
268 /* -------------------------------------------------------------------- */
269 GDALRasterBlock::DestroyRBMutex();
270
271 /* -------------------------------------------------------------------- */
272 /* Cleanup gdaltransformer.cpp mutex */
273 /* -------------------------------------------------------------------- */
274 GDALCleanupTransformDeserializerMutex();
275
276 /* -------------------------------------------------------------------- */
277 /* Cleanup cpl_error.cpp mutex */
278 /* -------------------------------------------------------------------- */
279 CPLCleanupErrorMutex();
280
281 /* -------------------------------------------------------------------- */
282 /* Cleanup CPLsetlocale mutex */
283 /* -------------------------------------------------------------------- */
284 CPLCleanupSetlocaleMutex();
285
286 /* -------------------------------------------------------------------- */
287 /* Cleanup the master CPL mutex, which governs the creation */
288 /* of all other mutexes. */
289 /* -------------------------------------------------------------------- */
290 CPLCleanupMasterMutex();
291
292 /* -------------------------------------------------------------------- */
293 /* Ensure the global driver manager pointer is NULLed out. */
294 /* -------------------------------------------------------------------- */
295 if( poDM == this )
296 poDM = NULL;
297 }
298
299 /************************************************************************/
300 /* GetDriverCount() */
301 /************************************************************************/
302
303 /**
304 * \brief Fetch the number of registered drivers.
305 *
306 * This C analog to this is GDALGetDriverCount().
307 *
308 * @return the number of registered drivers.
309 */
310
GetDriverCount()311 int GDALDriverManager::GetDriverCount()
312
313 {
314 return( nDrivers );
315 }
316
317 /************************************************************************/
318 /* GDALGetDriverCount() */
319 /************************************************************************/
320
321 /**
322 * \brief Fetch the number of registered drivers.
323 *
324 * @see GDALDriverManager::GetDriverCount()
325 */
326
GDALGetDriverCount()327 int CPL_STDCALL GDALGetDriverCount()
328
329 {
330 return GetGDALDriverManager()->GetDriverCount();
331 }
332
333 /************************************************************************/
334 /* GetDriver() */
335 /************************************************************************/
336
337 /**
338 * \brief Fetch driver by index.
339 *
340 * This C analog to this is GDALGetDriver().
341 *
342 * @param iDriver the driver index from 0 to GetDriverCount()-1.
343 *
344 * @return the driver identified by the index or NULL if the index is invalid
345 */
346
GetDriver(int iDriver)347 GDALDriver * GDALDriverManager::GetDriver( int iDriver )
348
349 {
350 CPLMutexHolderD( &hDMMutex );
351
352 return GetDriver_unlocked(iDriver);
353 }
354
355 /************************************************************************/
356 /* GDALGetDriver() */
357 /************************************************************************/
358
359 /**
360 * \brief Fetch driver by index.
361 *
362 * @see GDALDriverManager::GetDriver()
363 */
364
GDALGetDriver(int iDriver)365 GDALDriverH CPL_STDCALL GDALGetDriver( int iDriver )
366
367 {
368 return (GDALDriverH) GetGDALDriverManager()->GetDriver(iDriver);
369 }
370
371 /************************************************************************/
372 /* RegisterDriver() */
373 /************************************************************************/
374
375 /**
376 * \brief Register a driver for use.
377 *
378 * The C analog is GDALRegisterDriver().
379 *
380 * Normally this method is used by format specific C callable registration
381 * entry points such as GDALRegister_GTiff() rather than being called
382 * directly by application level code.
383 *
384 * If this driver (based on the object pointer, not short name) is already
385 * registered, then no change is made, and the index of the existing driver
386 * is returned. Otherwise the driver list is extended, and the new driver
387 * is added at the end.
388 *
389 * @param poDriver the driver to register.
390 *
391 * @return the index of the new installed driver.
392 */
393
RegisterDriver(GDALDriver * poDriver)394 int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
395
396 {
397 CPLMutexHolderD( &hDMMutex );
398
399 /* -------------------------------------------------------------------- */
400 /* If it is already registered, just return the existing */
401 /* index. */
402 /* -------------------------------------------------------------------- */
403 if( GetDriverByName_unlocked( poDriver->GetDescription() ) != NULL )
404 {
405 int i;
406
407 for( i = 0; i < nDrivers; i++ )
408 {
409 if( papoDrivers[i] == poDriver )
410 {
411 return i;
412 }
413 }
414
415 CPLAssert( FALSE );
416 }
417
418 /* -------------------------------------------------------------------- */
419 /* Otherwise grow the list to hold the new entry. */
420 /* -------------------------------------------------------------------- */
421 papoDrivers = (GDALDriver **)
422 VSIRealloc(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1));
423
424 papoDrivers[nDrivers] = poDriver;
425 nDrivers++;
426
427 if( poDriver->pfnOpen != NULL ||
428 poDriver->pfnOpenWithDriverArg != NULL )
429 poDriver->SetMetadataItem( GDAL_DCAP_OPEN, "YES" );
430
431 if( poDriver->pfnCreate != NULL )
432 poDriver->SetMetadataItem( GDAL_DCAP_CREATE, "YES" );
433
434 if( poDriver->pfnCreateCopy != NULL )
435 poDriver->SetMetadataItem( GDAL_DCAP_CREATECOPY, "YES" );
436
437 /* Backward compability for GDAL raster out-of-tree drivers: */
438 /* if a driver hasn't explicitly set a vector capability, assume it is */
439 /* a raster driver (legacy OGR drivers will have DCAP_VECTOR set before */
440 /* calling RegisterDriver() ) */
441 if( poDriver->GetMetadataItem( GDAL_DCAP_RASTER ) == NULL &&
442 poDriver->GetMetadataItem( GDAL_DCAP_VECTOR ) == NULL )
443 {
444 CPLDebug("GDAL", "Assuming DCAP_RASTER for driver %s. Please fix it.",
445 poDriver->GetDescription() );
446 poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
447 }
448
449 if( poDriver->GetMetadataItem( GDAL_DMD_OPENOPTIONLIST ) != NULL &&
450 poDriver->pfnIdentify == NULL &&
451 !EQUALN(poDriver->GetDescription(), "Interlis", strlen("Interlis")) )
452 {
453 CPLDebug("GDAL", "Driver %s that defines GDAL_DMD_OPENOPTIONLIST must also "
454 "implement Identify(), so that it can be used",
455 poDriver->GetDescription() );
456 }
457
458 oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] = poDriver;
459
460 int iResult = nDrivers - 1;
461
462 return iResult;
463 }
464
465 /************************************************************************/
466 /* GDALRegisterDriver() */
467 /************************************************************************/
468
469 /**
470 * \brief Register a driver for use.
471 *
472 * @see GDALDriverManager::GetRegisterDriver()
473 */
474
GDALRegisterDriver(GDALDriverH hDriver)475 int CPL_STDCALL GDALRegisterDriver( GDALDriverH hDriver )
476
477 {
478 VALIDATE_POINTER1( hDriver, "GDALRegisterDriver", 0 );
479
480 return GetGDALDriverManager()->RegisterDriver( (GDALDriver *) hDriver );
481 }
482
483
484 /************************************************************************/
485 /* DeregisterDriver() */
486 /************************************************************************/
487
488 /**
489 * \brief Deregister the passed driver.
490 *
491 * If the driver isn't found no change is made.
492 *
493 * The C analog is GDALDeregisterDriver().
494 *
495 * @param poDriver the driver to deregister.
496 */
497
DeregisterDriver(GDALDriver * poDriver)498 void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
499
500 {
501 int i;
502 CPLMutexHolderD( &hDMMutex );
503
504 for( i = 0; i < nDrivers; i++ )
505 {
506 if( papoDrivers[i] == poDriver )
507 break;
508 }
509
510 if( i == nDrivers )
511 return;
512
513 oMapNameToDrivers.erase(CPLString(poDriver->GetDescription()).toupper());
514 while( i < nDrivers-1 )
515 {
516 papoDrivers[i] = papoDrivers[i+1];
517 i++;
518 }
519 nDrivers--;
520 }
521
522 /************************************************************************/
523 /* GDALDeregisterDriver() */
524 /************************************************************************/
525
526 /**
527 * \brief Deregister the passed driver.
528 *
529 * @see GDALDriverManager::GetDeregisterDriver()
530 */
531
GDALDeregisterDriver(GDALDriverH hDriver)532 void CPL_STDCALL GDALDeregisterDriver( GDALDriverH hDriver )
533
534 {
535 VALIDATE_POINTER0( hDriver, "GDALDeregisterDriver" );
536
537 GetGDALDriverManager()->DeregisterDriver( (GDALDriver *) hDriver );
538 }
539
540
541 /************************************************************************/
542 /* GetDriverByName() */
543 /************************************************************************/
544
545 /**
546 * \brief Fetch a driver based on the short name.
547 *
548 * The C analog is the GDALGetDriverByName() function.
549 *
550 * @param pszName the short name, such as GTiff, being searched for.
551 *
552 * @return the identified driver, or NULL if no match is found.
553 */
554
GetDriverByName(const char * pszName)555 GDALDriver * GDALDriverManager::GetDriverByName( const char * pszName )
556
557 {
558 CPLMutexHolderD( &hDMMutex );
559
560 return oMapNameToDrivers[CPLString(pszName).toupper()];
561 }
562
563 /************************************************************************/
564 /* GDALGetDriverByName() */
565 /************************************************************************/
566
567 /**
568 * \brief Fetch a driver based on the short name.
569 *
570 * @see GDALDriverManager::GetDriverByName()
571 */
572
GDALGetDriverByName(const char * pszName)573 GDALDriverH CPL_STDCALL GDALGetDriverByName( const char * pszName )
574
575 {
576 VALIDATE_POINTER1( pszName, "GDALGetDriverByName", NULL );
577
578 return( GetGDALDriverManager()->GetDriverByName( pszName ) );
579 }
580
581 /************************************************************************/
582 /* AutoSkipDrivers() */
583 /************************************************************************/
584
585 /**
586 * \brief This method unload undesirable drivers.
587 *
588 * All drivers specified in the comma delimited list in the GDAL_SKIP
589 * environment variable) will be deregistered and destroyed. This method
590 * should normally be called after registration of standard drivers to allow
591 * the user a way of unloading undesired drivers. The GDALAllRegister()
592 * function already invokes AutoSkipDrivers() at the end, so if that functions
593 * is called, it should not be necessary to call this method from application
594 * code.
595 *
596 * Note: space separator is also accepted for backward compatibility, but some
597 * vector formats have spaces in their names, so it is encouraged to use comma
598 * to avoid issues.
599 */
600
AutoSkipDrivers()601 void GDALDriverManager::AutoSkipDrivers()
602
603 {
604 char **apapszList[2] = { NULL, NULL };
605 const char* pszGDAL_SKIP = CPLGetConfigOption( "GDAL_SKIP", NULL );
606 if( pszGDAL_SKIP != NULL )
607 {
608 /* Favour comma as a separator. If not found, then use space */
609 const char* pszSep = (strchr(pszGDAL_SKIP, ',') != NULL) ? "," : " ";
610 apapszList[0] = CSLTokenizeStringComplex( pszGDAL_SKIP, pszSep, FALSE, FALSE);
611 }
612 const char* pszOGR_SKIP = CPLGetConfigOption( "OGR_SKIP", NULL );
613 if( pszOGR_SKIP != NULL )
614 {
615 /* OGR has always used comma as a separator */
616 apapszList[1] = CSLTokenizeStringComplex(pszOGR_SKIP, ",", FALSE, FALSE);
617 }
618
619 for( int j = 0; j < 2; j++ )
620 {
621 for( int i = 0; apapszList[j] != NULL && apapszList[j][i] != NULL; i++ )
622 {
623 GDALDriver *poDriver = GetDriverByName( apapszList[j][i] );
624
625 if( poDriver == NULL )
626 CPLError( CE_Warning, CPLE_AppDefined,
627 "Unable to find driver %s to unload from GDAL_SKIP environment variable.",
628 apapszList[j][i] );
629 else
630 {
631 CPLDebug( "GDAL", "AutoSkipDriver(%s)", apapszList[j][i] );
632 DeregisterDriver( poDriver );
633 delete poDriver;
634 }
635 }
636 }
637
638 CSLDestroy( apapszList[0] );
639 CSLDestroy( apapszList[1] );
640 }
641
642 /************************************************************************/
643 /* AutoLoadDrivers() */
644 /************************************************************************/
645
646 /**
647 * \brief Auto-load GDAL drivers from shared libraries.
648 *
649 * This function will automatically load drivers from shared libraries. It
650 * searches the "driver path" for .so (or .dll) files that start with the
651 * prefix "gdal_X.so". It then tries to load them and then tries to call a
652 * function within them called GDALRegister_X() where the 'X' is the same as
653 * the remainder of the shared library basename ('X' is case sensitive), or
654 * failing that to call GDALRegisterMe().
655 *
656 * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
657 * environment variable it set, it is taken to be a list of directories to
658 * search separated by colons on UNIX, or semi-colons on Windows. Otherwise
659 * the /usr/local/lib/gdalplugins directory, and (if known) the
660 * lib/gdalplugins subdirectory of the gdal home directory are searched on
661 * UNIX and $(BINDIR)\gdalplugins on Windows.
662 *
663 * Auto loading can be completely disabled by setting the GDAL_DRIVER_PATH
664 * config option to "disable".
665 */
666
AutoLoadDrivers()667 void GDALDriverManager::AutoLoadDrivers()
668
669 {
670 char **papszSearchPath = NULL;
671 const char *pszGDAL_DRIVER_PATH =
672 CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
673 if( pszGDAL_DRIVER_PATH == NULL )
674 pszGDAL_DRIVER_PATH = CPLGetConfigOption( "OGR_DRIVER_PATH", NULL );
675
676 /* -------------------------------------------------------------------- */
677 /* Allow applications to completely disable this search by */
678 /* setting the driver path to the special string "disable". */
679 /* -------------------------------------------------------------------- */
680 if( pszGDAL_DRIVER_PATH != NULL && EQUAL(pszGDAL_DRIVER_PATH,"disable"))
681 {
682 CPLDebug( "GDAL", "GDALDriverManager::AutoLoadDrivers() disabled." );
683 return;
684 }
685
686 /* -------------------------------------------------------------------- */
687 /* Where should we look for stuff? */
688 /* -------------------------------------------------------------------- */
689 if( pszGDAL_DRIVER_PATH != NULL )
690 {
691 #ifdef WIN32
692 papszSearchPath =
693 CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
694 #else
695 papszSearchPath =
696 CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
697 #endif
698 }
699 else
700 {
701 #ifdef GDAL_PREFIX
702 papszSearchPath = CSLAddString( papszSearchPath,
703 #ifdef MACOSX_FRAMEWORK
704 GDAL_PREFIX "/PlugIns");
705 #else
706 GDAL_PREFIX "/lib/gdalplugins" );
707 #endif
708 #else
709 char szExecPath[1024];
710
711 if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
712 {
713 char szPluginDir[sizeof(szExecPath)+50];
714 strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
715 strcat( szPluginDir, "\\gdalplugins" );
716 papszSearchPath = CSLAddString( papszSearchPath, szPluginDir );
717 }
718 else
719 {
720 papszSearchPath = CSLAddString( papszSearchPath,
721 "/usr/local/lib/gdalplugins" );
722 }
723 #endif
724
725 #ifdef MACOSX_FRAMEWORK
726 #define num2str(x) str(x)
727 #define str(x) #x
728 papszSearchPath = CSLAddString( papszSearchPath,
729 "/Library/Application Support/GDAL/"
730 num2str(GDAL_VERSION_MAJOR) "."
731 num2str(GDAL_VERSION_MINOR) "/PlugIns" );
732 #endif
733
734 }
735
736 /* -------------------------------------------------------------------- */
737 /* Format the ABI version specific subdirectory to look in. */
738 /* -------------------------------------------------------------------- */
739 CPLString osABIVersion;
740
741 osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
742
743 /* -------------------------------------------------------------------- */
744 /* Scan each directory looking for files starting with gdal_ */
745 /* -------------------------------------------------------------------- */
746 for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
747 {
748 char **papszFiles = NULL;
749 VSIStatBufL sStatBuf;
750 CPLString osABISpecificDir =
751 CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
752
753 if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
754 osABISpecificDir = papszSearchPath[iDir];
755
756 papszFiles = CPLReadDir( osABISpecificDir );
757 int nFileCount = CSLCount(papszFiles);
758
759 for( int iFile = 0; iFile < nFileCount; iFile++ )
760 {
761 char *pszFuncName;
762 const char *pszFilename;
763 const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
764 void *pRegister;
765
766 if( !EQUAL(pszExtension,"dll")
767 && !EQUAL(pszExtension,"so")
768 && !EQUAL(pszExtension,"dylib") )
769 continue;
770
771 if( EQUALN(papszFiles[iFile],"gdal_",strlen("gdal_")) )
772 {
773 pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
774 sprintf( pszFuncName, "GDALRegister_%s",
775 CPLGetBasename(papszFiles[iFile]) + strlen("gdal_") );
776 }
777 else if ( EQUALN(papszFiles[iFile],"ogr_",strlen("ogr_")) )
778 {
779 pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
780 sprintf( pszFuncName, "RegisterOGR%s",
781 CPLGetBasename(papszFiles[iFile]) + strlen("ogr_") );
782 }
783 else
784 continue;
785
786 pszFilename =
787 CPLFormFilename( osABISpecificDir,
788 papszFiles[iFile], NULL );
789
790 CPLErrorReset();
791 CPLPushErrorHandler(CPLQuietErrorHandler);
792 pRegister = CPLGetSymbol( pszFilename, pszFuncName );
793 CPLPopErrorHandler();
794 if( pRegister == NULL )
795 {
796 CPLString osLastErrorMsg(CPLGetLastErrorMsg());
797 strcpy( pszFuncName, "GDALRegisterMe" );
798 pRegister = CPLGetSymbol( pszFilename, pszFuncName );
799 if( pRegister == NULL )
800 {
801 CPLError( CE_Failure, CPLE_AppDefined,
802 "%s", osLastErrorMsg.c_str() );
803 }
804 }
805
806 if( pRegister != NULL )
807 {
808 CPLDebug( "GDAL", "Auto register %s using %s.",
809 pszFilename, pszFuncName );
810
811 ((void (*)()) pRegister)();
812 }
813
814 CPLFree( pszFuncName );
815 }
816
817 CSLDestroy( papszFiles );
818 }
819
820 CSLDestroy( papszSearchPath );
821 }
822
823 /************************************************************************/
824 /* GDALDestroyDriverManager() */
825 /************************************************************************/
826
827 /**
828 * \brief Destroy the driver manager.
829 *
830 * Incidently unloads all managed drivers.
831 *
832 * NOTE: This function is not thread safe. It should not be called while
833 * other threads are actively using GDAL.
834 */
835
GDALDestroyDriverManager(void)836 void CPL_STDCALL GDALDestroyDriverManager( void )
837
838 {
839 // THREADSAFETY: We would like to lock the mutex here, but it
840 // needs to be reacquired within the destructor during driver
841 // deregistration.
842 if( poDM != NULL )
843 delete poDM;
844 }
845
846
847