1 /******************************************************************************
2  *
3  * Project:  GDAL Core
4  * Purpose:  Implementation of GDALDriverManager class.
5  * Author:   Frank Warmerdam, warmerdam@pobox.com
6  *
7  ******************************************************************************
8  * Copyright (c) 1998, Frank Warmerdam
9  * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
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 "cpl_port.h"
31 #include "gdal_priv.h"
32 
33 #include <cstring>
34 #include <map>
35 
36 #include "cpl_conv.h"
37 #include "cpl_error.h"
38 #include "cpl_http.h"
39 #include "cpl_multiproc.h"
40 #include "cpl_port.h"
41 #include "cpl_string.h"
42 #include "cpl_vsi.h"
43 #include "gdal_alg.h"
44 #include "gdal_alg_priv.h"
45 #include "gdal.h"
46 #include "gdal_pam.h"
47 #include "gdal_version.h"
48 #include "gdal_thread_pool.h"
49 #include "ogr_srs_api.h"
50 #include "ograpispy.h"
51 #ifdef HAVE_XERCES
52 #  include "ogr_xerces.h"
53 #endif  // HAVE_XERCES
54 
55 #ifdef _MSC_VER
56 #  ifdef MSVC_USE_VLD
57 #    include <wchar.h>
58 #    include <vld.h>
59 #  endif
60 #endif
61 
62 // FIXME: Disabled following code as it crashed on OSX CI test.
63 // #include <mutex>
64 
65 CPL_CVSID("$Id: gdaldrivermanager.cpp 230012f811b25deeac8a0fd1180f6baae8ed67a4 2021-03-16 22:36:04 +0100 Even Rouault $")
66 
67 /************************************************************************/
68 /* ==================================================================== */
69 /*                           GDALDriverManager                          */
70 /* ==================================================================== */
71 /************************************************************************/
72 
73 static volatile GDALDriverManager *poDM = nullptr;
74 static CPLMutex *hDMMutex = nullptr;
75 
76 // FIXME: Disabled following code as it crashed on OSX CI test.
77 // static std::mutex oDeleteMutex;
78 
GDALGetphDMMutex()79 CPLMutex** GDALGetphDMMutex() { return &hDMMutex; }
80 
81 /************************************************************************/
82 /*                        GetGDALDriverManager()                        */
83 /*                                                                      */
84 /*      A freestanding function to get the only instance of the         */
85 /*      GDALDriverManager.                                              */
86 /************************************************************************/
87 
88 /**
89  * \brief Fetch the global GDAL driver manager.
90  *
91  * This function fetches the pointer to the singleton global driver manager.
92  * If the driver manager doesn't exist it is automatically created.
93  *
94  * @return pointer to the global driver manager.  This should not be able
95  * to fail.
96  */
97 
GetGDALDriverManager()98 GDALDriverManager * GetGDALDriverManager()
99 
100 {
101     if( poDM == nullptr )
102     {
103         CPLMutexHolderD( &hDMMutex );
104         // cppcheck-suppress identicalInnerCondition
105         if( poDM == nullptr )
106             poDM = new GDALDriverManager();
107     }
108 
109     CPLAssert( nullptr != poDM );
110 
111     return const_cast<GDALDriverManager *>( poDM );
112 }
113 
114 /************************************************************************/
115 /*                         GDALDriverManager()                          */
116 /************************************************************************/
117 
GDALDriverManager()118 GDALDriverManager::GDALDriverManager()
119 {
120     CPLAssert( poDM == nullptr );
121 
122     CPLLoadConfigOptionsFromPredefinedFiles();
123 
124 /* -------------------------------------------------------------------- */
125 /*      We want to push a location to search for data files             */
126 /*      supporting GDAL/OGR such as EPSG csv files, S-57 definition     */
127 /*      files, and so forth.  Use the INST_DATA macro (setup at         */
128 /*      configure time) if available. Otherwise we don't push anything  */
129 /*      and we hope other mechanisms such as environment variables will */
130 /*      have been employed.                                             */
131 /* -------------------------------------------------------------------- */
132 #ifdef INST_DATA
133     if( CPLGetConfigOption( "GDAL_DATA", nullptr ) != nullptr )
134     {
135         // This one is picked up automatically by finder initialization.
136     }
137     else
138     {
139         CPLPushFinderLocation( INST_DATA );
140     }
141 #endif
142 }
143 
144 /************************************************************************/
145 /*                         ~GDALDriverManager()                         */
146 /************************************************************************/
147 
148 // Keep these two in sync with gdalproxypool.cpp.
149 void GDALDatasetPoolPreventDestroy();
150 void GDALDatasetPoolForceDestroy();
151 
~GDALDriverManager()152 GDALDriverManager::~GDALDriverManager()
153 
154 {
155 /* -------------------------------------------------------------------- */
156 /*      Cleanup any open datasets.                                      */
157 /* -------------------------------------------------------------------- */
158 
159     // We have to prevent the destroying of the dataset pool during this first
160     // phase, otherwise it cause crashes with a VRT B referencing a VRT A, and
161     // if CloseDependentDatasets() is called first on VRT A.
162     // If we didn't do this nasty trick, due to the refCountOfDisableRefCount
163     // mechanism that cheats the real refcount of the dataset pool, we might
164     // destroy the dataset pool too early, leading the VRT A to
165     // destroy itself indirectly ... Ok, I am aware this explanation does
166     // not make any sense unless you try it under a debugger ...
167     // When people just manipulate "top-level" dataset handles, we luckily
168     // don't need this horrible hack, but GetOpenDatasets() expose "low-level"
169     // datasets, which defeat some "design" of the proxy pool.
170     GDALDatasetPoolPreventDestroy();
171 
172     // First begin by requesting each remaining dataset to drop any reference
173     // to other datasets.
174     bool bHasDroppedRef = false;
175 
176     do
177     {
178         int nDSCount = 0;
179         GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
180 
181         // If a dataset has dropped a reference, the list might have become
182         // invalid, so go out of the loop and try again with the new valid
183         // list.
184         bHasDroppedRef = false;
185         for( int i = 0; i < nDSCount && !bHasDroppedRef; ++i )
186         {
187 #if DEBUG_VERBOSE
188             CPLDebug( "GDAL", "Call CloseDependentDatasets() on %s",
189                       papoDSList[i]->GetDescription() );
190 #endif  // DEBUG_VERBOSE
191             bHasDroppedRef =
192                 CPL_TO_BOOL(papoDSList[i]->CloseDependentDatasets());
193         }
194     } while(bHasDroppedRef);
195 
196     // Now let's destroy the dataset pool. Nobody should use it afterwards
197     // if people have well released their dependent datasets above.
198     GDALDatasetPoolForceDestroy();
199 
200     // Now close the stand-alone datasets.
201     int nDSCount = 0;
202     GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
203     for( int i = 0; i < nDSCount; ++i )
204     {
205         CPLDebug( "GDAL",
206                   "Force close of %s (%p) in GDALDriverManager cleanup.",
207                   papoDSList[i]->GetDescription(), papoDSList[i] );
208         // Destroy with delete operator rather than GDALClose() to force
209         // deletion of datasets with multiple reference count.
210         // We could also iterate while GetOpenDatasets() returns a non NULL
211         // list.
212         delete papoDSList[i];
213     }
214 
215 /* -------------------------------------------------------------------- */
216 /*      Destroy the existing drivers.                                   */
217 /* -------------------------------------------------------------------- */
218     while( GetDriverCount() > 0 )
219     {
220         GDALDriver *poDriver = GetDriver(0);
221 
222         DeregisterDriver(poDriver);
223         delete poDriver;
224     }
225 
226     CleanupPythonDrivers();
227 
228     GDALDestroyGlobalThreadPool();
229 
230 /* -------------------------------------------------------------------- */
231 /*      Cleanup local memory.                                           */
232 /* -------------------------------------------------------------------- */
233     VSIFree( papoDrivers );
234 
235 /* -------------------------------------------------------------------- */
236 /*      Cleanup any Proxy related memory.                               */
237 /* -------------------------------------------------------------------- */
238     PamCleanProxyDB();
239 
240 /* -------------------------------------------------------------------- */
241 /*      Cleanup any memory allocated by the OGRSpatialReference         */
242 /*      related subsystem.                                              */
243 /* -------------------------------------------------------------------- */
244     OSRCleanup();
245 
246 /* -------------------------------------------------------------------- */
247 /*      Blow away all the finder hints paths.  We really should not     */
248 /*      be doing all of them, but it is currently hard to keep track    */
249 /*      of those that actually belong to us.                            */
250 /* -------------------------------------------------------------------- */
251     CPLFinderClean();
252     CPLFreeConfig();
253     CPLCleanupSharedFileMutex();
254 
255 #ifdef HAVE_XERCES
256     OGRCleanupXercesMutex();
257 #endif
258 
259 #ifdef OGRAPISPY_ENABLED
260     OGRAPISpyDestroyMutex();
261 #endif
262 
263 /* -------------------------------------------------------------------- */
264 /*      Cleanup VSIFileManager.                                         */
265 /* -------------------------------------------------------------------- */
266     VSICleanupFileManager();
267 
268 /* -------------------------------------------------------------------- */
269 /*      Cleanup thread local storage ... I hope the program is all      */
270 /*      done with GDAL/OGR!                                             */
271 /* -------------------------------------------------------------------- */
272     CPLCleanupTLS();
273 
274 /* -------------------------------------------------------------------- */
275 /*      Cleanup our mutex.                                              */
276 /* -------------------------------------------------------------------- */
277     if( hDMMutex )
278     {
279         CPLDestroyMutex( hDMMutex );
280         hDMMutex = nullptr;
281     }
282 
283 /* -------------------------------------------------------------------- */
284 /*      Cleanup dataset list mutex.                                     */
285 /* -------------------------------------------------------------------- */
286     if( *GDALGetphDLMutex() != nullptr )
287     {
288         CPLDestroyMutex( *GDALGetphDLMutex() );
289         *GDALGetphDLMutex() = nullptr;
290     }
291 
292 /* -------------------------------------------------------------------- */
293 /*      Cleanup raster block mutex.                                     */
294 /* -------------------------------------------------------------------- */
295     GDALRasterBlock::DestroyRBMutex();
296 
297 /* -------------------------------------------------------------------- */
298 /*      Cleanup gdaltransformer.cpp mutex.                              */
299 /* -------------------------------------------------------------------- */
300     GDALCleanupTransformDeserializerMutex();
301 
302 /* -------------------------------------------------------------------- */
303 /*      Cleanup cpl_error.cpp mutex.                                    */
304 /* -------------------------------------------------------------------- */
305     CPLCleanupErrorMutex();
306 
307 /* -------------------------------------------------------------------- */
308 /*      Cleanup CPLsetlocale mutex.                                     */
309 /* -------------------------------------------------------------------- */
310     CPLCleanupSetlocaleMutex();
311 
312 /* -------------------------------------------------------------------- */
313 /*      Cleanup QHull mutex.                                            */
314 /* -------------------------------------------------------------------- */
315     GDALTriangulationTerminate();
316 
317 /* -------------------------------------------------------------------- */
318 /*      Cleanup curl related stuff.                                     */
319 /* -------------------------------------------------------------------- */
320     CPLHTTPCleanup();
321 
322 /* -------------------------------------------------------------------- */
323 /*      Cleanup the master CPL mutex, which governs the creation        */
324 /*      of all other mutexes.                                           */
325 /* -------------------------------------------------------------------- */
326     CPLCleanupMasterMutex();
327 
328 /* -------------------------------------------------------------------- */
329 /*      Ensure the global driver manager pointer is NULLed out.         */
330 /* -------------------------------------------------------------------- */
331     if( poDM == this )
332         poDM = nullptr;
333 }
334 
335 /************************************************************************/
336 /*                           GetDriverCount()                           */
337 /************************************************************************/
338 
339 /**
340  * \brief Fetch the number of registered drivers.
341  *
342  * This C analog to this is GDALGetDriverCount().
343  *
344  * @return the number of registered drivers.
345  */
346 
GetDriverCount() const347 int GDALDriverManager::GetDriverCount() const
348 
349 {
350     return nDrivers;
351 }
352 
353 /************************************************************************/
354 /*                         GDALGetDriverCount()                         */
355 /************************************************************************/
356 
357 /**
358  * \brief Fetch the number of registered drivers.
359  *
360  * @see GDALDriverManager::GetDriverCount()
361  */
362 
GDALGetDriverCount()363 int CPL_STDCALL GDALGetDriverCount()
364 
365 {
366     return GetGDALDriverManager()->GetDriverCount();
367 }
368 
369 /************************************************************************/
370 /*                             GetDriver()                              */
371 /************************************************************************/
372 
373 /**
374  * \brief Fetch driver by index.
375  *
376  * This C analog to this is GDALGetDriver().
377  *
378  * @param iDriver the driver index from 0 to GetDriverCount()-1.
379  *
380  * @return the driver identified by the index or NULL if the index is invalid
381  */
382 
GetDriver(int iDriver)383 GDALDriver * GDALDriverManager::GetDriver( int iDriver )
384 
385 {
386     CPLMutexHolderD( &hDMMutex );
387 
388     return GetDriver_unlocked(iDriver);
389 }
390 
391 /************************************************************************/
392 /*                           GDALGetDriver()                            */
393 /************************************************************************/
394 
395 /**
396  * \brief Fetch driver by index.
397  *
398  * @see GDALDriverManager::GetDriver()
399  */
400 
GDALGetDriver(int iDriver)401 GDALDriverH CPL_STDCALL GDALGetDriver( int iDriver )
402 
403 {
404     return /* (GDALDriverH) */ GetGDALDriverManager()->GetDriver(iDriver);
405 }
406 
407 /************************************************************************/
408 /*                           RegisterDriver()                           */
409 /************************************************************************/
410 
411 /**
412  * \brief Register a driver for use.
413  *
414  * The C analog is GDALRegisterDriver().
415  *
416  * Normally this method is used by format specific C callable registration
417  * entry points such as GDALRegister_GTiff() rather than being called
418  * directly by application level code.
419  *
420  * If this driver (based on the object pointer, not short name) is already
421  * registered, then no change is made, and the index of the existing driver
422  * is returned.  Otherwise the driver list is extended, and the new driver
423  * is added at the end.
424  *
425  * @param poDriver the driver to register.
426  *
427  * @return the index of the new installed driver.
428  */
429 
RegisterDriver(GDALDriver * poDriver)430 int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
431 
432 {
433     CPLMutexHolderD( &hDMMutex );
434 
435 /* -------------------------------------------------------------------- */
436 /*      If it is already registered, just return the existing           */
437 /*      index.                                                          */
438 /* -------------------------------------------------------------------- */
439     if( GetDriverByName_unlocked( poDriver->GetDescription() ) != nullptr )
440     {
441         for( int i = 0; i < nDrivers; ++i )
442         {
443             if( papoDrivers[i] == poDriver )
444             {
445                 return i;
446             }
447         }
448 
449         CPLAssert( false );
450     }
451 
452 /* -------------------------------------------------------------------- */
453 /*      Otherwise grow the list to hold the new entry.                  */
454 /* -------------------------------------------------------------------- */
455     GDALDriver** papoNewDrivers = static_cast<GDALDriver **>(
456         VSI_REALLOC_VERBOSE(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1)) );
457     if( papoNewDrivers == nullptr )
458         return -1;
459     papoDrivers = papoNewDrivers;
460 
461     papoDrivers[nDrivers] = poDriver;
462     ++nDrivers;
463 
464     if( poDriver->pfnOpen != nullptr ||
465         poDriver->pfnOpenWithDriverArg != nullptr )
466         poDriver->SetMetadataItem( GDAL_DCAP_OPEN, "YES" );
467 
468     if( poDriver->pfnCreate != nullptr ||
469         poDriver->pfnCreateEx != nullptr )
470         poDriver->SetMetadataItem( GDAL_DCAP_CREATE, "YES" );
471 
472     if( poDriver->pfnCreateCopy != nullptr )
473         poDriver->SetMetadataItem( GDAL_DCAP_CREATECOPY, "YES" );
474 
475     if( poDriver->pfnCreateMultiDimensional != nullptr )
476         poDriver->SetMetadataItem( GDAL_DCAP_CREATE_MULTIDIMENSIONAL, "YES" );
477 
478     // Backward compatibility for GDAL raster out-of-tree drivers:
479     // If a driver hasn't explicitly set a vector capability, assume it is
480     // a raster-only driver (legacy OGR drivers will have DCAP_VECTOR set before
481     // calling RegisterDriver()).
482     if( poDriver->GetMetadataItem( GDAL_DCAP_RASTER ) == nullptr &&
483         poDriver->GetMetadataItem( GDAL_DCAP_VECTOR ) == nullptr &&
484         poDriver->GetMetadataItem( GDAL_DCAP_GNM ) == nullptr )
485     {
486         CPLDebug( "GDAL", "Assuming DCAP_RASTER for driver %s. Please fix it.",
487                   poDriver->GetDescription() );
488         poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
489     }
490 
491     if( poDriver->GetMetadataItem( GDAL_DMD_OPENOPTIONLIST ) != nullptr &&
492         poDriver->pfnIdentify == nullptr &&
493         poDriver->pfnIdentifyEx == nullptr &&
494         !STARTS_WITH_CI(poDriver->GetDescription(), "Interlis") )
495     {
496         CPLDebug( "GDAL",
497                   "Driver %s that defines GDAL_DMD_OPENOPTIONLIST must also "
498                   "implement Identify(), so that it can be used",
499                   poDriver->GetDescription() );
500     }
501 
502     oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] =
503         poDriver;
504 
505     int iResult = nDrivers - 1;
506 
507     return iResult;
508 }
509 
510 /************************************************************************/
511 /*                         GDALRegisterDriver()                         */
512 /************************************************************************/
513 
514 /**
515  * \brief Register a driver for use.
516  *
517  * @see GDALDriverManager::GetRegisterDriver()
518  */
519 
GDALRegisterDriver(GDALDriverH hDriver)520 int CPL_STDCALL GDALRegisterDriver( GDALDriverH hDriver )
521 
522 {
523     VALIDATE_POINTER1( hDriver, "GDALRegisterDriver", 0 );
524 
525     return GetGDALDriverManager()->
526         RegisterDriver( static_cast<GDALDriver *>( hDriver ) );
527 }
528 
529 /************************************************************************/
530 /*                          DeregisterDriver()                          */
531 /************************************************************************/
532 
533 /**
534  * \brief Deregister the passed driver.
535  *
536  * If the driver isn't found no change is made.
537  *
538  * The C analog is GDALDeregisterDriver().
539  *
540  * @param poDriver the driver to deregister.
541  */
542 
DeregisterDriver(GDALDriver * poDriver)543 void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
544 
545 {
546     CPLMutexHolderD( &hDMMutex );
547 
548     int i = 0;  // Used after for.
549     for( ; i < nDrivers; ++i )
550     {
551         if( papoDrivers[i] == poDriver )
552             break;
553     }
554 
555     if( i == nDrivers )
556         return;
557 
558     oMapNameToDrivers.erase(CPLString(poDriver->GetDescription()).toupper());
559     --nDrivers;
560     // Move all following drivers down by one to pack the list.
561     while( i < nDrivers )
562     {
563         papoDrivers[i] = papoDrivers[i+1];
564         ++i;
565     }
566 }
567 
568 /************************************************************************/
569 /*                        GDALDeregisterDriver()                        */
570 /************************************************************************/
571 
572 /**
573  * \brief Deregister the passed driver.
574  *
575  * @see GDALDriverManager::GetDeregisterDriver()
576  */
577 
GDALDeregisterDriver(GDALDriverH hDriver)578 void CPL_STDCALL GDALDeregisterDriver( GDALDriverH hDriver )
579 
580 {
581     VALIDATE_POINTER0( hDriver, "GDALDeregisterDriver" );
582 
583     GetGDALDriverManager()->DeregisterDriver( static_cast<GDALDriver *>(hDriver) );
584 }
585 
586 /************************************************************************/
587 /*                          GetDriverByName()                           */
588 /************************************************************************/
589 
590 /**
591  * \brief Fetch a driver based on the short name.
592  *
593  * The C analog is the GDALGetDriverByName() function.
594  *
595  * @param pszName the short name, such as GTiff, being searched for.
596  *
597  * @return the identified driver, or NULL if no match is found.
598  */
599 
GetDriverByName(const char * pszName)600 GDALDriver * GDALDriverManager::GetDriverByName( const char * pszName )
601 
602 {
603     CPLMutexHolderD( &hDMMutex );
604 
605     // Alias old name to new name
606     if( EQUAL(pszName, "CartoDB") )
607         pszName = "Carto";
608 
609     return oMapNameToDrivers[CPLString(pszName).toupper()];
610 }
611 
612 /************************************************************************/
613 /*                        GDALGetDriverByName()                         */
614 /************************************************************************/
615 
616 /**
617  * \brief Fetch a driver based on the short name.
618  *
619  * @see GDALDriverManager::GetDriverByName()
620  */
621 
GDALGetDriverByName(const char * pszName)622 GDALDriverH CPL_STDCALL GDALGetDriverByName( const char * pszName )
623 
624 {
625     VALIDATE_POINTER1( pszName, "GDALGetDriverByName", nullptr );
626 
627     return GetGDALDriverManager()->GetDriverByName( pszName );
628 }
629 
630 /************************************************************************/
631 /*                          AutoSkipDrivers()                           */
632 /************************************************************************/
633 
634 /**
635  * \brief This method unload undesirable drivers.
636  *
637  * All drivers specified in the comma delimited list in the GDAL_SKIP
638  * environment variable) will be deregistered and destroyed.  This method
639  * should normally be called after registration of standard drivers to allow
640  * the user a way of unloading undesired drivers.  The GDALAllRegister()
641  * function already invokes AutoSkipDrivers() at the end, so if that functions
642  * is called, it should not be necessary to call this method from application
643  * code.
644  *
645  * Note: space separator is also accepted for backward compatibility, but some
646  * vector formats have spaces in their names, so it is encouraged to use comma
647  * to avoid issues.
648  */
649 
AutoSkipDrivers()650 void GDALDriverManager::AutoSkipDrivers()
651 
652 {
653     char **apapszList[2] = { nullptr, nullptr };
654     const char* pszGDAL_SKIP = CPLGetConfigOption( "GDAL_SKIP", nullptr );
655     if( pszGDAL_SKIP != nullptr )
656     {
657         // Favor comma as a separator. If not found, then use space.
658         const char* pszSep = (strchr(pszGDAL_SKIP, ',') != nullptr) ? "," : " ";
659         apapszList[0] =
660             CSLTokenizeStringComplex( pszGDAL_SKIP, pszSep, FALSE, FALSE );
661     }
662     const char* pszOGR_SKIP = CPLGetConfigOption( "OGR_SKIP", nullptr );
663     if( pszOGR_SKIP != nullptr )
664     {
665         // OGR has always used comma as a separator.
666         apapszList[1] = CSLTokenizeStringComplex(pszOGR_SKIP, ",", FALSE, FALSE);
667     }
668 
669     for( auto j: {0, 1} )
670     {
671         for( int i = 0; apapszList[j] != nullptr && apapszList[j][i] != nullptr; ++i )
672         {
673             GDALDriver * const poDriver = GetDriverByName( apapszList[j][i] );
674 
675             if( poDriver == nullptr )
676             {
677                 CPLError( CE_Warning, CPLE_AppDefined,
678                           "Unable to find driver %s to unload from GDAL_SKIP "
679                           "environment variable.",
680                         apapszList[j][i] );
681             }
682             else
683             {
684                 CPLDebug( "GDAL", "AutoSkipDriver(%s)", apapszList[j][i] );
685                 DeregisterDriver( poDriver );
686                 delete poDriver;
687             }
688         }
689     }
690 
691     CSLDestroy( apapszList[0] );
692     CSLDestroy( apapszList[1] );
693 }
694 
695 /************************************************************************/
696 /*                          GetSearchPaths()                            */
697 /************************************************************************/
698 
GetSearchPaths(const char * pszGDAL_DRIVER_PATH)699 char** GDALDriverManager::GetSearchPaths(const char* pszGDAL_DRIVER_PATH)
700 {
701     char **papszSearchPaths = nullptr;
702     CPL_IGNORE_RET_VAL(pszGDAL_DRIVER_PATH);
703 #ifndef GDAL_NO_AUTOLOAD
704     if( pszGDAL_DRIVER_PATH != nullptr )
705     {
706 #ifdef WIN32
707         papszSearchPaths =
708             CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
709 #else
710         papszSearchPaths =
711             CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
712 #endif
713     }
714     else
715     {
716 #ifdef GDAL_PREFIX
717         papszSearchPaths = CSLAddString( papszSearchPaths,
718     #ifdef MACOSX_FRAMEWORK
719                                         GDAL_PREFIX "/PlugIns");
720     #else
721                                         GDAL_PREFIX "/lib/gdalplugins" );
722     #endif
723 #else
724         char szExecPath[1024];
725 
726         if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
727         {
728             char szPluginDir[sizeof(szExecPath)+50];
729             strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
730             strcat( szPluginDir, "\\gdalplugins" );
731             papszSearchPaths = CSLAddString( papszSearchPaths, szPluginDir );
732         }
733         else
734         {
735             papszSearchPaths = CSLAddString( papszSearchPaths,
736                                             "/usr/local/lib/gdalplugins" );
737         }
738 #endif
739 
740    #ifdef MACOSX_FRAMEWORK
741    #define num2str(x) str(x)
742    #define str(x) #x
743      papszSearchPaths = CSLAddString( papszSearchPaths,
744                                      "/Library/Application Support/GDAL/"
745                                      num2str(GDAL_VERSION_MAJOR) "."
746                                      num2str(GDAL_VERSION_MINOR) "/PlugIns" );
747 #endif
748     }
749 #endif // GDAL_NO_AUTOLOAD
750     return papszSearchPaths;
751 }
752 
753 /************************************************************************/
754 /*                          AutoLoadDrivers()                           */
755 /************************************************************************/
756 
757 /**
758  * \brief Auto-load GDAL drivers from shared libraries.
759  *
760  * This function will automatically load drivers from shared libraries.  It
761  * searches the "driver path" for .so (or .dll) files that start with the
762  * prefix "gdal_X.so".  It then tries to load them and then tries to call a
763  * function within them called GDALRegister_X() where the 'X' is the same as
764  * the remainder of the shared library basename ('X' is case sensitive), or
765  * failing that to call GDALRegisterMe().
766  *
767  * There are a few rules for the driver path.  If the GDAL_DRIVER_PATH
768  * environment variable it set, it is taken to be a list of directories to
769  * search separated by colons on UNIX, or semi-colons on Windows.  Otherwise
770  * the /usr/local/lib/gdalplugins directory, and (if known) the
771  * lib/gdalplugins subdirectory of the gdal home directory are searched on
772  * UNIX and $(BINDIR)\\gdalplugins on Windows.
773  *
774  * Auto loading can be completely disabled by setting the GDAL_DRIVER_PATH
775  * config option to "disable".
776  */
777 
AutoLoadDrivers()778 void GDALDriverManager::AutoLoadDrivers()
779 
780 {
781 #ifdef GDAL_NO_AUTOLOAD
782     CPLDebug( "GDAL", "GDALDriverManager::AutoLoadDrivers() not compiled in." );
783 #else
784     const char *pszGDAL_DRIVER_PATH =
785         CPLGetConfigOption( "GDAL_DRIVER_PATH", nullptr );
786     if( pszGDAL_DRIVER_PATH == nullptr )
787         pszGDAL_DRIVER_PATH = CPLGetConfigOption( "OGR_DRIVER_PATH", nullptr );
788 
789 /* -------------------------------------------------------------------- */
790 /*      Allow applications to completely disable this search by         */
791 /*      setting the driver path to the special string "disable".        */
792 /* -------------------------------------------------------------------- */
793     if( pszGDAL_DRIVER_PATH != nullptr && EQUAL(pszGDAL_DRIVER_PATH,"disable"))
794     {
795         CPLDebug( "GDAL", "GDALDriverManager::AutoLoadDrivers() disabled." );
796         return;
797     }
798 
799 /* -------------------------------------------------------------------- */
800 /*      Where should we look for stuff?                                 */
801 /* -------------------------------------------------------------------- */
802     char **papszSearchPaths = GetSearchPaths(pszGDAL_DRIVER_PATH);
803 
804 /* -------------------------------------------------------------------- */
805 /*      Format the ABI version specific subdirectory to look in.        */
806 /* -------------------------------------------------------------------- */
807     CPLString osABIVersion;
808 
809     osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
810 
811 /* -------------------------------------------------------------------- */
812 /*      Scan each directory looking for files starting with gdal_       */
813 /* -------------------------------------------------------------------- */
814     const int nSearchPaths = CSLCount(papszSearchPaths);
815     for( int iDir = 0; iDir < nSearchPaths; ++iDir )
816     {
817         CPLString osABISpecificDir =
818             CPLFormFilename( papszSearchPaths[iDir], osABIVersion, nullptr );
819 
820         VSIStatBufL sStatBuf;
821         if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
822             osABISpecificDir = papszSearchPaths[iDir];
823 
824         char **papszFiles = VSIReadDir( osABISpecificDir );
825         const int nFileCount = CSLCount(papszFiles);
826 
827         for( int iFile = 0; iFile < nFileCount; ++iFile )
828         {
829             const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
830 
831             if( !EQUAL(pszExtension,"dll")
832                 && !EQUAL(pszExtension,"so")
833                 && !EQUAL(pszExtension,"dylib") )
834                 continue;
835 
836             CPLString osFuncName;
837             if( STARTS_WITH_CI(papszFiles[iFile], "gdal_") )
838             {
839                 osFuncName.Printf("GDALRegister_%s",
840                         CPLGetBasename(papszFiles[iFile]) + strlen("gdal_") );
841             }
842             else if( STARTS_WITH_CI(papszFiles[iFile], "ogr_") )
843             {
844                 osFuncName.Printf(
845                          "RegisterOGR%s",
846                          CPLGetBasename(papszFiles[iFile]) + strlen("ogr_") );
847             }
848             else
849                 continue;
850 
851             const char *pszFilename
852                 = CPLFormFilename( osABISpecificDir,
853                                    papszFiles[iFile], nullptr );
854 
855             CPLErrorReset();
856             CPLPushErrorHandler(CPLQuietErrorHandler);
857             void *pRegister = CPLGetSymbol( pszFilename, osFuncName );
858             CPLPopErrorHandler();
859             if( pRegister == nullptr )
860             {
861                 CPLString osLastErrorMsg(CPLGetLastErrorMsg());
862                 osFuncName = "GDALRegisterMe";
863                 pRegister = CPLGetSymbol( pszFilename, osFuncName );
864                 if( pRegister == nullptr )
865                 {
866                     CPLError( CE_Failure, CPLE_AppDefined,
867                               "%s", osLastErrorMsg.c_str() );
868                 }
869             }
870 
871             if( pRegister != nullptr )
872             {
873                 CPLDebug( "GDAL", "Auto register %s using %s.",
874                           pszFilename, osFuncName.c_str() );
875 
876                 reinterpret_cast<void (*)()>(pRegister)();
877             }
878         }
879 
880         CSLDestroy( papszFiles );
881     }
882 
883     CSLDestroy( papszSearchPaths );
884 
885 #endif  // GDAL_NO_AUTOLOAD
886 }
887 
888 /************************************************************************/
889 /*                      GDALDestroyDriverManager()                      */
890 /************************************************************************/
891 
892 /**
893  * \brief Destroy the driver manager.
894  *
895  * Incidentally unloads all managed drivers.
896  *
897  * NOTE: This function is not thread safe.  It should not be called while
898  * other threads are actively using GDAL.
899  */
900 
GDALDestroyDriverManager(void)901 void CPL_STDCALL GDALDestroyDriverManager( void )
902 
903 {
904     // THREADSAFETY: We would like to lock the mutex here, but it
905     // needs to be reacquired within the destructor during driver
906     // deregistration.
907 
908 // FIXME: Disable following code as it crashed on OSX CI test.
909 // std::lock_guard<std::mutex> oLock(oDeleteMutex);
910 
911     if( poDM != nullptr )
912     {
913         delete poDM;
914         poDM = nullptr;
915     }
916 }
917 
918 /************************************************************************/
919 /*        GDALIsDriverDeprecatedForGDAL35StillEnabled()                 */
920 /************************************************************************/
921 
922 /**
923  * \brief Returns whether a deprecated driver is explicitly enabled by the user
924  */
925 
GDALIsDriverDeprecatedForGDAL35StillEnabled(const char * pszDriverName,const char * pszExtraMsg)926 bool GDALIsDriverDeprecatedForGDAL35StillEnabled(const char* pszDriverName, const char* pszExtraMsg)
927 {
928     CPLString osConfigOption;
929     osConfigOption.Printf("GDAL_ENABLE_DEPRECATED_DRIVER_%s", pszDriverName);
930     if( CPLTestBool(CPLGetConfigOption(osConfigOption.c_str(), "NO")) )
931     {
932         return true;
933     }
934     CPLError(CE_Failure, CPLE_AppDefined,
935         "Driver %s is considered for removal in GDAL 3.5.%s You are invited "
936         "to convert any dataset in that format to another more common one ."
937         "If you need this driver in future GDAL versions, create a ticket at "
938         "https://github.com/OSGeo/gdal (look first for an existing one first) to "
939         "explain how critical it is for you (but the GDAL project may still "
940         "remove it), and to enable it now, set the %s "
941         "configuration option / environment variable to YES",
942         pszDriverName, pszExtraMsg, osConfigOption.c_str());
943     return false;
944 }
945