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