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