Line data Source code
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 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 : #include "gdal_priv.h"
16 :
17 : #include <algorithm>
18 : #include <cstring>
19 : #include <map>
20 : #include <set>
21 :
22 : #include "cpl_conv.h"
23 : #include "cpl_error.h"
24 : #include "cpl_http.h"
25 : #include "cpl_multiproc.h"
26 : #include "cpl_port.h"
27 : #include "cpl_string.h"
28 : #include "cpl_vsi.h"
29 : #include "cpl_compressor.h"
30 : #include "gdal_alg.h"
31 : #include "gdal_alg_priv.h"
32 : #include "gdal.h"
33 : #include "gdal_pam.h"
34 : #include "gdal_version_full/gdal_version.h"
35 : #include "gdal_thread_pool.h"
36 : #include "ogr_srs_api.h"
37 : #include "ograpispy.h"
38 : #ifdef HAVE_XERCES
39 : #include "ogr_xerces.h"
40 : #endif // HAVE_XERCES
41 :
42 : #ifdef _MSC_VER
43 : #ifdef MSVC_USE_VLD
44 : #include <wchar.h>
45 : #include <vld.h>
46 : #endif
47 : #endif
48 :
49 : // FIXME: Disabled following code as it crashed on OSX CI test.
50 : // #include <mutex>
51 :
52 : /************************************************************************/
53 : /* ==================================================================== */
54 : /* GDALDriverManager */
55 : /* ==================================================================== */
56 : /************************************************************************/
57 :
58 : static volatile GDALDriverManager *poDM = nullptr;
59 : static CPLMutex *hDMMutex = nullptr;
60 :
61 : // FIXME: Disabled following code as it crashed on OSX CI test.
62 : // static std::mutex oDeleteMutex;
63 :
64 33 : CPLMutex **GDALGetphDMMutex()
65 : {
66 33 : return &hDMMutex;
67 : }
68 :
69 : /************************************************************************/
70 : /* GetGDALDriverManager() */
71 : /* */
72 : /* A freestanding function to get the only instance of the */
73 : /* GDALDriverManager. */
74 : /************************************************************************/
75 :
76 : /**
77 : * \brief Fetch the global GDAL driver manager.
78 : *
79 : * This function fetches the pointer to the singleton global driver manager.
80 : * If the driver manager doesn't exist it is automatically created.
81 : *
82 : * @return pointer to the global driver manager. This should not be able
83 : * to fail.
84 : */
85 :
86 1558770 : GDALDriverManager *GetGDALDriverManager()
87 :
88 : {
89 1558770 : if (poDM == nullptr)
90 : {
91 2766 : CPLMutexHolderD(&hDMMutex);
92 : // cppcheck-suppress identicalInnerCondition
93 1383 : if (poDM == nullptr)
94 1383 : poDM = new GDALDriverManager();
95 : }
96 :
97 1558770 : CPLAssert(nullptr != poDM);
98 :
99 1558770 : return const_cast<GDALDriverManager *>(poDM);
100 : }
101 :
102 : /************************************************************************/
103 : /* GDALDriverManager() */
104 : /************************************************************************/
105 :
106 : #define XSTRINGIFY(x) #x
107 : #define STRINGIFY(x) XSTRINGIFY(x)
108 :
109 1383 : GDALDriverManager::GDALDriverManager()
110 : {
111 1383 : CPLAssert(poDM == nullptr);
112 :
113 1383 : CPLLoadConfigOptionsFromPredefinedFiles();
114 :
115 1383 : CPLHTTPSetDefaultUserAgent(
116 : "GDAL/" STRINGIFY(GDAL_VERSION_MAJOR) "." STRINGIFY(
117 : GDAL_VERSION_MINOR) "." STRINGIFY(GDAL_VERSION_REV));
118 :
119 : /* -------------------------------------------------------------------- */
120 : /* We want to push a location to search for data files */
121 : /* supporting GDAL/OGR such as EPSG csv files, S-57 definition */
122 : /* files, and so forth. Use the INST_DATA macro (setup at */
123 : /* configure time) if available. Otherwise we don't push anything */
124 : /* and we hope other mechanisms such as environment variables will */
125 : /* have been employed. */
126 : /* -------------------------------------------------------------------- */
127 : #ifdef INST_DATA
128 1383 : if (CPLGetConfigOption("GDAL_DATA", nullptr) != nullptr)
129 : {
130 : // This one is picked up automatically by finder initialization.
131 : }
132 : else
133 : {
134 2 : CPLPushFinderLocation(INST_DATA);
135 : }
136 : #endif
137 1383 : }
138 :
139 : /************************************************************************/
140 : /* ~GDALDriverManager() */
141 : /************************************************************************/
142 :
143 : // Keep these two in sync with gdalproxypool.cpp.
144 : void GDALDatasetPoolPreventDestroy();
145 : void GDALDatasetPoolForceDestroy();
146 :
147 1882 : GDALDriverManager::~GDALDriverManager()
148 :
149 : {
150 : /* -------------------------------------------------------------------- */
151 : /* Cleanup any open datasets. */
152 : /* -------------------------------------------------------------------- */
153 :
154 : // We have to prevent the destroying of the dataset pool during this first
155 : // phase, otherwise it cause crashes with a VRT B referencing a VRT A, and
156 : // if CloseDependentDatasets() is called first on VRT A.
157 : // If we didn't do this nasty trick, due to the refCountOfDisableRefCount
158 : // mechanism that cheats the real refcount of the dataset pool, we might
159 : // destroy the dataset pool too early, leading the VRT A to
160 : // destroy itself indirectly ... Ok, I am aware this explanation does
161 : // not make any sense unless you try it under a debugger ...
162 : // When people just manipulate "top-level" dataset handles, we luckily
163 : // don't need this horrible hack, but GetOpenDatasets() expose "low-level"
164 : // datasets, which defeat some "design" of the proxy pool.
165 941 : GDALDatasetPoolPreventDestroy();
166 :
167 : // First begin by requesting each remaining dataset to drop any reference
168 : // to other datasets.
169 941 : bool bHasDroppedRef = false;
170 :
171 958 : do
172 : {
173 958 : int nDSCount = 0;
174 958 : GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
175 :
176 : // If a dataset has dropped a reference, the list might have become
177 : // invalid, so go out of the loop and try again with the new valid
178 : // list.
179 958 : bHasDroppedRef = false;
180 1221 : for (int i = 0; i < nDSCount && !bHasDroppedRef; ++i)
181 : {
182 : #if DEBUG_VERBOSE
183 : CPLDebug("GDAL", "Call CloseDependentDatasets() on %s",
184 : papoDSList[i]->GetDescription());
185 : #endif // DEBUG_VERBOSE
186 : bHasDroppedRef =
187 263 : CPL_TO_BOOL(papoDSList[i]->CloseDependentDatasets());
188 : }
189 : } while (bHasDroppedRef);
190 :
191 : // Now let's destroy the dataset pool. Nobody should use it afterwards
192 : // if people have well released their dependent datasets above.
193 941 : GDALDatasetPoolForceDestroy();
194 :
195 : // Now close the stand-alone datasets.
196 941 : int nDSCount = 0;
197 941 : GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
198 998 : for (int i = 0; i < nDSCount; ++i)
199 : {
200 57 : CPLDebug("GDAL", "Force close of %s (%p) in GDALDriverManager cleanup.",
201 57 : papoDSList[i]->GetDescription(), papoDSList[i]);
202 : // Destroy with delete operator rather than GDALClose() to force
203 : // deletion of datasets with multiple reference count.
204 : // We could also iterate while GetOpenDatasets() returns a non NULL
205 : // list.
206 57 : delete papoDSList[i];
207 : }
208 :
209 : /* -------------------------------------------------------------------- */
210 : /* Destroy the existing drivers. */
211 : /* -------------------------------------------------------------------- */
212 225836 : while (GetDriverCount() > 0)
213 : {
214 224895 : GDALDriver *poDriver = GetDriver(0);
215 :
216 224895 : DeregisterDriver(poDriver);
217 224895 : delete poDriver;
218 : }
219 :
220 941 : CleanupPythonDrivers();
221 :
222 941 : GDALDestroyGlobalThreadPool();
223 :
224 : /* -------------------------------------------------------------------- */
225 : /* Cleanup local memory. */
226 : /* -------------------------------------------------------------------- */
227 941 : VSIFree(papoDrivers);
228 :
229 : /* -------------------------------------------------------------------- */
230 : /* Cleanup any Proxy related memory. */
231 : /* -------------------------------------------------------------------- */
232 941 : PamCleanProxyDB();
233 :
234 : /* -------------------------------------------------------------------- */
235 : /* Cleanup any memory allocated by the OGRSpatialReference */
236 : /* related subsystem. */
237 : /* -------------------------------------------------------------------- */
238 941 : OSRCleanup();
239 :
240 : /* -------------------------------------------------------------------- */
241 : /* Blow away all the finder hints paths. We really should not */
242 : /* be doing all of them, but it is currently hard to keep track */
243 : /* of those that actually belong to us. */
244 : /* -------------------------------------------------------------------- */
245 941 : CPLFinderClean();
246 941 : CPLFreeConfig();
247 941 : CPLCleanupSharedFileMutex();
248 :
249 : #ifdef HAVE_XERCES
250 941 : OGRCleanupXercesMutex();
251 : #endif
252 :
253 : #ifdef OGRAPISPY_ENABLED
254 941 : OGRAPISpyDestroyMutex();
255 : #endif
256 :
257 : /* -------------------------------------------------------------------- */
258 : /* Cleanup VSIFileManager. */
259 : /* -------------------------------------------------------------------- */
260 941 : VSICleanupFileManager();
261 941 : CPLDestroyCompressorRegistry();
262 :
263 : /* -------------------------------------------------------------------- */
264 : /* Cleanup thread local storage ... I hope the program is all */
265 : /* done with GDAL/OGR! */
266 : /* -------------------------------------------------------------------- */
267 941 : CPLCleanupTLS();
268 :
269 : /* -------------------------------------------------------------------- */
270 : /* Cleanup our mutex. */
271 : /* -------------------------------------------------------------------- */
272 941 : if (hDMMutex)
273 : {
274 941 : CPLDestroyMutex(hDMMutex);
275 941 : hDMMutex = nullptr;
276 : }
277 :
278 : /* -------------------------------------------------------------------- */
279 : /* Cleanup dataset list mutex. */
280 : /* -------------------------------------------------------------------- */
281 941 : if (*GDALGetphDLMutex() != nullptr)
282 : {
283 941 : CPLDestroyMutex(*GDALGetphDLMutex());
284 941 : *GDALGetphDLMutex() = nullptr;
285 : }
286 :
287 : /* -------------------------------------------------------------------- */
288 : /* Cleanup raster block mutex. */
289 : /* -------------------------------------------------------------------- */
290 941 : GDALRasterBlock::DestroyRBMutex();
291 :
292 : /* -------------------------------------------------------------------- */
293 : /* Cleanup gdaltransformer.cpp mutex. */
294 : /* -------------------------------------------------------------------- */
295 941 : GDALCleanupTransformDeserializerMutex();
296 :
297 : /* -------------------------------------------------------------------- */
298 : /* Cleanup cpl_error.cpp mutex. */
299 : /* -------------------------------------------------------------------- */
300 941 : CPLCleanupErrorMutex();
301 :
302 : /* -------------------------------------------------------------------- */
303 : /* Cleanup CPLsetlocale mutex. */
304 : /* -------------------------------------------------------------------- */
305 941 : CPLCleanupSetlocaleMutex();
306 :
307 : /* -------------------------------------------------------------------- */
308 : /* Cleanup curl related stuff. */
309 : /* -------------------------------------------------------------------- */
310 941 : CPLHTTPCleanup();
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Cleanup the master CPL mutex, which governs the creation */
314 : /* of all other mutexes. */
315 : /* -------------------------------------------------------------------- */
316 941 : CPLCleanupMasterMutex();
317 :
318 : /* -------------------------------------------------------------------- */
319 : /* Ensure the global driver manager pointer is NULLed out. */
320 : /* -------------------------------------------------------------------- */
321 941 : if (poDM == this)
322 941 : poDM = nullptr;
323 1882 : }
324 :
325 : /************************************************************************/
326 : /* GetDriverCount() */
327 : /************************************************************************/
328 :
329 : /**
330 : * \brief Fetch the number of registered drivers.
331 : *
332 : * This C analog to this is GDALGetDriverCount().
333 : *
334 : * @return the number of registered drivers.
335 : */
336 :
337 256839 : int GDALDriverManager::GetDriverCount() const
338 :
339 : {
340 256839 : return nDrivers;
341 : }
342 :
343 : //! @cond Doxygen_Suppress
344 69784 : int GDALDriverManager::GetDriverCount(bool bIncludeHidden) const
345 :
346 : {
347 69784 : if (!bIncludeHidden)
348 0 : return nDrivers;
349 69784 : return nDrivers + static_cast<int>(m_aoHiddenDrivers.size());
350 : }
351 :
352 : //! @endcond
353 :
354 : /************************************************************************/
355 : /* IsKnownDriver() */
356 : /************************************************************************/
357 :
358 : //! @cond Doxygen_Suppress
359 0 : bool GDALDriverManager::IsKnownDriver(const char *pszDriverName) const
360 : {
361 0 : CPLMutexHolderD(&hDMMutex);
362 0 : if (cpl::contains(oMapNameToDrivers, CPLString(pszDriverName).toupper()))
363 0 : return true;
364 0 : for (const auto &poDriver : m_aoHiddenDrivers)
365 : {
366 0 : if (EQUAL(poDriver->GetDescription(), pszDriverName))
367 0 : return true;
368 : }
369 0 : return false;
370 : }
371 :
372 : //! @endcond
373 :
374 : /************************************************************************/
375 : /* GDALGetDriverCount() */
376 : /************************************************************************/
377 :
378 : /**
379 : * \brief Fetch the number of registered drivers.
380 : *
381 : * @see GDALDriverManager::GetDriverCount()
382 : */
383 :
384 3763 : int CPL_STDCALL GDALGetDriverCount()
385 :
386 : {
387 3763 : return GetGDALDriverManager()->GetDriverCount();
388 : }
389 :
390 : /************************************************************************/
391 : /* GetDriver() */
392 : /************************************************************************/
393 :
394 : /**
395 : * \brief Fetch driver by index.
396 : *
397 : * This C analog to this is GDALGetDriver().
398 : *
399 : * @param iDriver the driver index from 0 to GetDriverCount()-1.
400 : *
401 : * @return the driver identified by the index or NULL if the index is invalid
402 : */
403 :
404 11657800 : GDALDriver *GDALDriverManager::GetDriver(int iDriver)
405 :
406 : {
407 23315700 : CPLMutexHolderD(&hDMMutex);
408 :
409 23315700 : return GetDriver_unlocked(iDriver);
410 : }
411 :
412 : //! @cond Doxygen_Suppress
413 8110060 : GDALDriver *GDALDriverManager::GetDriver(int iDriver, bool bIncludeHidden)
414 :
415 : {
416 16225000 : CPLMutexHolderD(&hDMMutex);
417 8114900 : if (!bIncludeHidden || iDriver < nDrivers)
418 8114900 : return GetDriver_unlocked(iDriver);
419 0 : if (iDriver - nDrivers < static_cast<int>(m_aoHiddenDrivers.size()))
420 0 : return m_aoHiddenDrivers[iDriver - nDrivers].get();
421 0 : return nullptr;
422 : }
423 :
424 : //! @endcond
425 :
426 : /************************************************************************/
427 : /* GDALGetDriver() */
428 : /************************************************************************/
429 :
430 : /**
431 : * \brief Fetch driver by index.
432 : *
433 : * @see GDALDriverManager::GetDriver()
434 : */
435 :
436 632638 : GDALDriverH CPL_STDCALL GDALGetDriver(int iDriver)
437 :
438 : {
439 632638 : return /* (GDALDriverH) */ GetGDALDriverManager()->GetDriver(iDriver);
440 : }
441 :
442 : /************************************************************************/
443 : /* RegisterDriver() */
444 : /************************************************************************/
445 :
446 : /**
447 : * \brief Register a driver for use.
448 : *
449 : * The C analog is GDALRegisterDriver().
450 : *
451 : * Normally this method is used by format specific C callable registration
452 : * entry points such as GDALRegister_GTiff() rather than being called
453 : * directly by application level code.
454 : *
455 : * If this driver (based on the object pointer, not short name) is already
456 : * registered, then no change is made, and the index of the existing driver
457 : * is returned. Otherwise the driver list is extended, and the new driver
458 : * is added at the end.
459 : *
460 : * @param poDriver the driver to register.
461 : *
462 : * @return the index of the new installed driver.
463 : */
464 :
465 330968 : int GDALDriverManager::RegisterDriver(GDALDriver *poDriver)
466 : {
467 330968 : return RegisterDriver(poDriver, /*bHidden=*/false);
468 : }
469 :
470 330968 : int GDALDriverManager::RegisterDriver(GDALDriver *poDriver, bool bHidden)
471 : {
472 661936 : CPLMutexHolderD(&hDMMutex);
473 :
474 : /* -------------------------------------------------------------------- */
475 : /* If it is already registered, just return the existing */
476 : /* index. */
477 : /* -------------------------------------------------------------------- */
478 661350 : if (!m_bInDeferredDriverLoading &&
479 330382 : GetDriverByName_unlocked(poDriver->GetDescription()) != nullptr)
480 : {
481 239 : for (int i = 0; i < nDrivers; ++i)
482 : {
483 239 : if (papoDrivers[i] == poDriver)
484 : {
485 1 : return i;
486 : }
487 : }
488 :
489 0 : CPLAssert(false);
490 : }
491 :
492 330967 : if (poDriver->pfnOpen != nullptr ||
493 64915 : poDriver->pfnOpenWithDriverArg != nullptr)
494 266055 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
495 :
496 330967 : if (poDriver->pfnCreate != nullptr || poDriver->pfnCreateEx != nullptr)
497 114925 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
498 :
499 330967 : if (poDriver->pfnCreateCopy != nullptr)
500 59644 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
501 :
502 330967 : if (poDriver->pfnCreateMultiDimensional != nullptr)
503 4178 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_MULTIDIMENSIONAL, "YES");
504 :
505 : // Backward compatibility for GDAL raster out-of-tree drivers:
506 : // If a driver hasn't explicitly set a vector capability, assume it is
507 : // a raster-only driver (legacy OGR drivers will have DCAP_VECTOR set before
508 : // calling RegisterDriver()).
509 330967 : if (poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr &&
510 333732 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr &&
511 2765 : poDriver->GetMetadataItem(GDAL_DCAP_GNM) == nullptr)
512 : {
513 3 : CPLDebug("GDAL", "Assuming DCAP_RASTER for driver %s. Please fix it.",
514 3 : poDriver->GetDescription());
515 3 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
516 : }
517 :
518 330967 : if (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) != nullptr &&
519 116356 : poDriver->pfnIdentify == nullptr &&
520 450085 : poDriver->pfnIdentifyEx == nullptr &&
521 2762 : !STARTS_WITH_CI(poDriver->GetDescription(), "Interlis"))
522 : {
523 0 : CPLDebug("GDAL",
524 : "Driver %s that defines GDAL_DMD_OPENOPTIONLIST must also "
525 : "implement Identify(), so that it can be used",
526 0 : poDriver->GetDescription());
527 : }
528 :
529 330967 : if (poDriver->pfnVectorTranslateFrom != nullptr)
530 1381 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR_TRANSLATE_FROM, "YES");
531 :
532 331553 : if (m_bInDeferredDriverLoading &&
533 586 : cpl::contains(oMapNameToDrivers,
534 331553 : CPLString(poDriver->GetDescription()).toupper()))
535 : {
536 585 : if (cpl::contains(m_oMapRealDrivers, poDriver->GetDescription()))
537 : {
538 0 : CPLError(
539 : CE_Failure, CPLE_AppDefined,
540 : "RegisterDriver() in m_bInDeferredDriverLoading: %s already "
541 : "registered!",
542 0 : poDriver->GetDescription());
543 0 : delete poDriver;
544 0 : return -1;
545 : }
546 1170 : m_oMapRealDrivers[poDriver->GetDescription()] =
547 1755 : std::unique_ptr<GDALDriver>(poDriver);
548 585 : return -1;
549 : }
550 :
551 : /* -------------------------------------------------------------------- */
552 : /* Otherwise grow the list to hold the new entry. */
553 : /* -------------------------------------------------------------------- */
554 330382 : if (bHidden)
555 : {
556 0 : m_aoHiddenDrivers.push_back(std::unique_ptr<GDALDriver>(poDriver));
557 0 : return -1;
558 : }
559 :
560 : GDALDriver **papoNewDrivers =
561 330382 : static_cast<GDALDriver **>(VSI_REALLOC_VERBOSE(
562 : papoDrivers, sizeof(GDALDriver *) * (nDrivers + 1)));
563 330382 : if (papoNewDrivers == nullptr)
564 0 : return -1;
565 330382 : papoDrivers = papoNewDrivers;
566 :
567 330382 : papoDrivers[nDrivers] = poDriver;
568 330382 : ++nDrivers;
569 :
570 330382 : oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] =
571 : poDriver;
572 :
573 330382 : int iResult = nDrivers - 1;
574 :
575 330382 : return iResult;
576 : }
577 :
578 : /************************************************************************/
579 : /* GDALRegisterDriver() */
580 : /************************************************************************/
581 :
582 : /**
583 : * \brief Register a driver for use.
584 : *
585 : * @see GDALDriverManager::GetRegisterDriver()
586 : */
587 :
588 1474 : int CPL_STDCALL GDALRegisterDriver(GDALDriverH hDriver)
589 :
590 : {
591 1474 : VALIDATE_POINTER1(hDriver, "GDALRegisterDriver", 0);
592 :
593 1474 : return GetGDALDriverManager()->RegisterDriver(
594 1474 : static_cast<GDALDriver *>(hDriver));
595 : }
596 :
597 : /************************************************************************/
598 : /* DeregisterDriver() */
599 : /************************************************************************/
600 :
601 : /**
602 : * \brief Deregister the passed driver.
603 : *
604 : * If the driver isn't found no change is made.
605 : *
606 : * The C analog is GDALDeregisterDriver().
607 : *
608 : * @param poDriver the driver to deregister.
609 : */
610 :
611 225001 : void GDALDriverManager::DeregisterDriver(GDALDriver *poDriver)
612 :
613 : {
614 225001 : CPLMutexHolderD(&hDMMutex);
615 :
616 225001 : int i = 0; // Used after for.
617 246984 : for (; i < nDrivers; ++i)
618 : {
619 246983 : if (papoDrivers[i] == poDriver)
620 225000 : break;
621 : }
622 :
623 225001 : if (i == nDrivers)
624 1 : return;
625 :
626 225000 : oMapNameToDrivers.erase(CPLString(poDriver->GetDescription()).toupper());
627 225000 : --nDrivers;
628 : // Move all following drivers down by one to pack the list.
629 26990300 : while (i < nDrivers)
630 : {
631 26765300 : papoDrivers[i] = papoDrivers[i + 1];
632 26765300 : ++i;
633 : }
634 : }
635 :
636 : /************************************************************************/
637 : /* GDALDeregisterDriver() */
638 : /************************************************************************/
639 :
640 : /**
641 : * \brief Deregister the passed driver.
642 : *
643 : * @see GDALDriverManager::GetDeregisterDriver()
644 : */
645 :
646 93 : void CPL_STDCALL GDALDeregisterDriver(GDALDriverH hDriver)
647 :
648 : {
649 93 : VALIDATE_POINTER0(hDriver, "GDALDeregisterDriver");
650 :
651 93 : GetGDALDriverManager()->DeregisterDriver(
652 : static_cast<GDALDriver *>(hDriver));
653 : }
654 :
655 : /************************************************************************/
656 : /* GetDriverByName() */
657 : /************************************************************************/
658 :
659 : /**
660 : * \brief Fetch a driver based on the short name.
661 : *
662 : * The C analog is the GDALGetDriverByName() function.
663 : *
664 : * @param pszName the short name, such as GTiff, being searched for.
665 : *
666 : * @return the identified driver, or NULL if no match is found.
667 : */
668 :
669 496894 : GDALDriver *GDALDriverManager::GetDriverByName(const char *pszName)
670 :
671 : {
672 993788 : CPLMutexHolderD(&hDMMutex);
673 :
674 496894 : if (m_bInDeferredDriverLoading)
675 : {
676 586 : return nullptr;
677 : }
678 :
679 : // Alias old name to new name
680 496308 : if (EQUAL(pszName, "CartoDB"))
681 0 : pszName = "Carto";
682 :
683 496308 : return GetDriverByName_unlocked(pszName);
684 : }
685 :
686 : /************************************************************************/
687 : /* GDALGetDriverByName() */
688 : /************************************************************************/
689 :
690 : /**
691 : * \brief Fetch a driver based on the short name.
692 : *
693 : * @see GDALDriverManager::GetDriverByName()
694 : */
695 :
696 489901 : GDALDriverH CPL_STDCALL GDALGetDriverByName(const char *pszName)
697 :
698 : {
699 489901 : VALIDATE_POINTER1(pszName, "GDALGetDriverByName", nullptr);
700 :
701 489901 : return GetGDALDriverManager()->GetDriverByName(pszName);
702 : }
703 :
704 : /************************************************************************/
705 : /* AutoSkipDrivers() */
706 : /************************************************************************/
707 :
708 : /**
709 : * \brief This method unload undesirable drivers.
710 : *
711 : * All drivers specified in the comma delimited list in the GDAL_SKIP
712 : * environment variable) will be deregistered and destroyed. This method
713 : * should normally be called after registration of standard drivers to allow
714 : * the user a way of unloading undesired drivers. The GDALAllRegister()
715 : * function already invokes AutoSkipDrivers() at the end, so if that functions
716 : * is called, it should not be necessary to call this method from application
717 : * code.
718 : *
719 : * Note: space separator is also accepted for backward compatibility, but some
720 : * vector formats have spaces in their names, so it is encouraged to use comma
721 : * to avoid issues.
722 : */
723 :
724 1683 : void GDALDriverManager::AutoSkipDrivers()
725 :
726 : {
727 1683 : char **apapszList[2] = {nullptr, nullptr};
728 1683 : const char *pszGDAL_SKIP = CPLGetConfigOption("GDAL_SKIP", nullptr);
729 1683 : if (pszGDAL_SKIP != nullptr)
730 : {
731 : // Favor comma as a separator. If not found, then use space.
732 4 : const char *pszSep = (strchr(pszGDAL_SKIP, ',') != nullptr) ? "," : " ";
733 4 : apapszList[0] =
734 4 : CSLTokenizeStringComplex(pszGDAL_SKIP, pszSep, FALSE, FALSE);
735 : }
736 1683 : const char *pszOGR_SKIP = CPLGetConfigOption("OGR_SKIP", nullptr);
737 1683 : if (pszOGR_SKIP != nullptr)
738 : {
739 : // OGR has always used comma as a separator.
740 4 : apapszList[1] =
741 4 : CSLTokenizeStringComplex(pszOGR_SKIP, ",", FALSE, FALSE);
742 : }
743 :
744 5049 : for (auto j : {0, 1})
745 : {
746 3374 : for (int i = 0; apapszList[j] != nullptr && apapszList[j][i] != nullptr;
747 : ++i)
748 : {
749 8 : GDALDriver *const poDriver = GetDriverByName(apapszList[j][i]);
750 :
751 8 : if (poDriver == nullptr)
752 : {
753 0 : CPLError(CE_Warning, CPLE_AppDefined,
754 : "Unable to find driver %s to unload from GDAL_SKIP "
755 : "environment variable.",
756 0 : apapszList[j][i]);
757 : }
758 : else
759 : {
760 8 : CPLDebug("GDAL", "AutoSkipDriver(%s)", apapszList[j][i]);
761 8 : DeregisterDriver(poDriver);
762 8 : delete poDriver;
763 : }
764 : }
765 : }
766 :
767 1683 : CSLDestroy(apapszList[0]);
768 1683 : CSLDestroy(apapszList[1]);
769 1683 : }
770 :
771 : /************************************************************************/
772 : /* GetSearchPaths() */
773 : /************************************************************************/
774 :
775 : //! @cond Doxygen_Suppress
776 4748 : char **GDALDriverManager::GetSearchPaths(const char *pszGDAL_DRIVER_PATH)
777 : {
778 4748 : char **papszSearchPaths = nullptr;
779 4748 : CPL_IGNORE_RET_VAL(pszGDAL_DRIVER_PATH);
780 : #ifndef GDAL_NO_AUTOLOAD
781 4748 : if (pszGDAL_DRIVER_PATH != nullptr)
782 : {
783 : #ifdef _WIN32
784 : papszSearchPaths =
785 : CSLTokenizeStringComplex(pszGDAL_DRIVER_PATH, ";", TRUE, FALSE);
786 : #else
787 : papszSearchPaths =
788 4748 : CSLTokenizeStringComplex(pszGDAL_DRIVER_PATH, ":", TRUE, FALSE);
789 : #endif
790 : }
791 : else
792 : {
793 : #ifdef INSTALL_PLUGIN_FULL_DIR
794 : // CMake way
795 : papszSearchPaths =
796 0 : CSLAddString(papszSearchPaths, INSTALL_PLUGIN_FULL_DIR);
797 : #elif defined(GDAL_PREFIX)
798 : papszSearchPaths = CSLAddString(papszSearchPaths,
799 : #ifdef MACOSX_FRAMEWORK
800 : GDAL_PREFIX "/PlugIns");
801 : #else
802 : GDAL_PREFIX "/lib/gdalplugins");
803 : #endif
804 : #else
805 : char szExecPath[1024];
806 :
807 : if (CPLGetExecPath(szExecPath, sizeof(szExecPath)))
808 : {
809 : papszSearchPaths = CSLAddString(
810 : papszSearchPaths,
811 : (CPLGetDirnameSafe(szExecPath) + "\\gdalplugins").c_str());
812 : }
813 : else
814 : {
815 : papszSearchPaths =
816 : CSLAddString(papszSearchPaths, "/usr/local/lib/gdalplugins");
817 : }
818 : #endif
819 :
820 : #ifdef MACOSX_FRAMEWORK
821 : #define num2str(x) str(x)
822 : #define str(x) #x
823 : papszSearchPaths = CSLAddString(
824 : papszSearchPaths,
825 : "/Library/Application Support/GDAL/" num2str(
826 : GDAL_VERSION_MAJOR) "." num2str(GDAL_VERSION_MINOR) "/PlugIns");
827 : #endif
828 : }
829 : #endif // GDAL_NO_AUTOLOAD
830 4748 : return papszSearchPaths;
831 : }
832 :
833 : //! @endcond
834 :
835 : /************************************************************************/
836 : /* LoadPlugin() */
837 : /************************************************************************/
838 :
839 : /**
840 : * \brief Load a single GDAL driver/plugin from shared libraries.
841 : *
842 : * This function will load a single named driver/plugin from shared libraries.
843 : * It searches the "driver path" for .so (or .dll) files named
844 : * "gdal_{name}.[so|dll|dylib]" or "ogr_{name}.[so|dll|dylib]", then tries to
845 : * call a function within them called GDALRegister_{name}(), or failing that
846 : * called GDALRegisterMe().
847 : *
848 : * \see GDALDriverManager::AutoLoadDrivers() for the rules used to determine
849 : * which paths are searched for plugin library files.
850 : */
851 :
852 1 : CPLErr GDALDriverManager::LoadPlugin(const char *name)
853 : {
854 : #ifdef GDAL_NO_AUTOLOAD
855 : CPLDebug("GDAL", "GDALDriverManager::LoadPlugin() not compiled in.");
856 : return CE_Failure;
857 : #else
858 : const char *pszGDAL_DRIVER_PATH =
859 1 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr);
860 1 : if (pszGDAL_DRIVER_PATH == nullptr)
861 0 : pszGDAL_DRIVER_PATH = CPLGetConfigOption("OGR_DRIVER_PATH", nullptr);
862 :
863 : /* -------------------------------------------------------------------- */
864 : /* Where should we look for stuff? */
865 : /* -------------------------------------------------------------------- */
866 2 : const CPLStringList aosSearchPaths(GetSearchPaths(pszGDAL_DRIVER_PATH));
867 :
868 : /* -------------------------------------------------------------------- */
869 : /* Format the ABI version specific subdirectory to look in. */
870 : /* -------------------------------------------------------------------- */
871 2 : CPLString osABIVersion;
872 :
873 1 : osABIVersion.Printf("%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
874 :
875 : /* -------------------------------------------------------------------- */
876 : /* Scan each directory looking for files matching */
877 : /* gdal_{name}.[so|dll|dylib] or ogr_{name}.[so|dll|dylib] */
878 : /* -------------------------------------------------------------------- */
879 1 : const int nSearchPaths = aosSearchPaths.size();
880 2 : for (int iDir = 0; iDir < nSearchPaths; ++iDir)
881 : {
882 : std::string osABISpecificDir =
883 1 : CPLFormFilenameSafe(aosSearchPaths[iDir], osABIVersion, nullptr);
884 :
885 : VSIStatBufL sStatBuf;
886 1 : if (VSIStatL(osABISpecificDir.c_str(), &sStatBuf) != 0)
887 1 : osABISpecificDir = aosSearchPaths[iDir];
888 :
889 3 : CPLString gdal_or_ogr[2] = {"gdal_", "ogr_"};
890 4 : CPLString platformExtensions[3] = {"so", "dll", "dylib"};
891 :
892 3 : for (const CPLString &prefix : gdal_or_ogr)
893 : {
894 8 : for (const CPLString &extension : platformExtensions)
895 : {
896 : const std::string osFilename = CPLFormFilenameSafe(
897 : osABISpecificDir.c_str(),
898 6 : CPLSPrintf("%s%s", prefix.c_str(), name), extension);
899 6 : if (VSIStatL(osFilename.c_str(), &sStatBuf) != 0)
900 6 : continue;
901 :
902 0 : CPLString osFuncName;
903 0 : if (EQUAL(prefix, "gdal_"))
904 : {
905 0 : osFuncName.Printf("GDALRegister_%s", name);
906 : }
907 : else
908 : {
909 0 : osFuncName.Printf("RegisterOGR%s", name);
910 : }
911 0 : CPLErrorReset();
912 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
913 0 : void *pRegister = CPLGetSymbol(osFilename.c_str(), osFuncName);
914 0 : CPLPopErrorHandler();
915 0 : if (pRegister == nullptr)
916 : {
917 0 : CPLString osLastErrorMsg(CPLGetLastErrorMsg());
918 0 : osFuncName = "GDALRegisterMe";
919 0 : pRegister = CPLGetSymbol(osFilename.c_str(), osFuncName);
920 0 : if (pRegister == nullptr)
921 : {
922 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
923 : osLastErrorMsg.c_str());
924 0 : return CE_Failure;
925 : }
926 : }
927 0 : CPLDebug("GDAL", "Registering %s using %s in %s", name,
928 : osFuncName.c_str(), osFilename.c_str());
929 0 : CPLErrorReset();
930 0 : reinterpret_cast<void (*)()>(pRegister)();
931 0 : if (CPLGetErrorCounter() > 0)
932 : {
933 0 : return CE_Failure;
934 : }
935 0 : return CE_None;
936 : }
937 : }
938 : }
939 1 : CPLError(CE_Failure, CPLE_AppDefined,
940 : "Failed to find driver %s in configured driver paths.", name);
941 1 : return CE_Failure;
942 : #endif // GDAL_NO_AUTOLOAD
943 : }
944 :
945 : /************************************************************************/
946 : /* AutoLoadDrivers() */
947 : /************************************************************************/
948 :
949 : /**
950 : * \brief Auto-load GDAL drivers from shared libraries.
951 : *
952 : * This function will automatically load drivers from shared libraries. It
953 : * searches the "driver path" for .so (or .dll) files that start with the
954 : * prefix "gdal_X.so". It then tries to load them and then tries to call a
955 : * function within them called GDALRegister_X() where the 'X' is the same as
956 : * the remainder of the shared library basename ('X' is case sensitive), or
957 : * failing that to call GDALRegisterMe().
958 : *
959 : * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
960 : * environment variable it set, it is taken to be a list of directories to
961 : * search separated by colons on UNIX, or semi-colons on Windows. Otherwise
962 : * the /usr/local/lib/gdalplugins directory, and (if known) the
963 : * lib/gdalplugins subdirectory of the gdal home directory are searched on
964 : * UNIX and $(BINDIR)\\gdalplugins on Windows.
965 : *
966 : * Auto loading can be completely disabled by setting the GDAL_DRIVER_PATH
967 : * config option to "disable".
968 : *
969 : * Starting with gdal 3.5, the default search path $(prefix)/lib/gdalplugins
970 : * can be overridden at compile time by passing
971 : * -DINSTALL_PLUGIN_DIR=/another/path to cmake.
972 : */
973 :
974 1683 : void GDALDriverManager::AutoLoadDrivers()
975 :
976 : {
977 : #ifdef GDAL_NO_AUTOLOAD
978 : CPLDebug("GDAL", "GDALDriverManager::AutoLoadDrivers() not compiled in.");
979 : #else
980 : const char *pszGDAL_DRIVER_PATH =
981 1683 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr);
982 1683 : if (pszGDAL_DRIVER_PATH == nullptr)
983 0 : pszGDAL_DRIVER_PATH = CPLGetConfigOption("OGR_DRIVER_PATH", nullptr);
984 :
985 : /* -------------------------------------------------------------------- */
986 : /* Allow applications to completely disable this search by */
987 : /* setting the driver path to the special string "disable". */
988 : /* -------------------------------------------------------------------- */
989 1683 : if (pszGDAL_DRIVER_PATH != nullptr && EQUAL(pszGDAL_DRIVER_PATH, "disable"))
990 : {
991 0 : CPLDebug("GDAL", "GDALDriverManager::AutoLoadDrivers() disabled.");
992 0 : return;
993 : }
994 :
995 : /* -------------------------------------------------------------------- */
996 : /* Where should we look for stuff? */
997 : /* -------------------------------------------------------------------- */
998 1683 : char **papszSearchPaths = GetSearchPaths(pszGDAL_DRIVER_PATH);
999 :
1000 : /* -------------------------------------------------------------------- */
1001 : /* Format the ABI version specific subdirectory to look in. */
1002 : /* -------------------------------------------------------------------- */
1003 3366 : CPLString osABIVersion;
1004 :
1005 1683 : osABIVersion.Printf("%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
1006 :
1007 : /* -------------------------------------------------------------------- */
1008 : /* Scan each directory looking for files starting with gdal_ */
1009 : /* -------------------------------------------------------------------- */
1010 1683 : const int nSearchPaths = CSLCount(papszSearchPaths);
1011 1683 : bool bFoundOnePlugin = false;
1012 3366 : for (int iDir = 0; iDir < nSearchPaths; ++iDir)
1013 : {
1014 : std::string osABISpecificDir =
1015 3366 : CPLFormFilenameSafe(papszSearchPaths[iDir], osABIVersion, nullptr);
1016 :
1017 : VSIStatBufL sStatBuf;
1018 1683 : if (VSIStatL(osABISpecificDir.c_str(), &sStatBuf) != 0)
1019 1683 : osABISpecificDir = papszSearchPaths[iDir];
1020 :
1021 1683 : char **papszFiles = VSIReadDir(osABISpecificDir.c_str());
1022 1683 : const int nFileCount = CSLCount(papszFiles);
1023 :
1024 69003 : for (int iFile = 0; iFile < nFileCount; ++iFile)
1025 : {
1026 : const CPLString osExtension =
1027 67320 : CPLGetExtensionSafe(papszFiles[iFile]);
1028 :
1029 72369 : if (!EQUAL(osExtension, "dll") && !EQUAL(osExtension, "so") &&
1030 5049 : !EQUAL(osExtension, "dylib"))
1031 : {
1032 5049 : if (strcmp(papszFiles[iFile], "drivers.ini") == 0)
1033 : {
1034 3366 : m_osDriversIniPath = CPLFormFilenameSafe(
1035 3366 : osABISpecificDir.c_str(), papszFiles[iFile], nullptr);
1036 : }
1037 5049 : continue;
1038 : }
1039 :
1040 62271 : if (cpl::contains(m_oSetPluginFileNames, papszFiles[iFile]))
1041 : {
1042 60588 : continue;
1043 : }
1044 :
1045 1683 : CPLString osFuncName;
1046 1683 : if (STARTS_WITH_CI(papszFiles[iFile], "gdal_"))
1047 : {
1048 : osFuncName.Printf(
1049 : "GDALRegister_%s",
1050 0 : CPLGetBasenameSafe(papszFiles[iFile]).c_str() +
1051 0 : strlen("gdal_"));
1052 : }
1053 1683 : else if (STARTS_WITH_CI(papszFiles[iFile], "ogr_"))
1054 : {
1055 : osFuncName.Printf(
1056 : "RegisterOGR%s",
1057 0 : CPLGetBasenameSafe(papszFiles[iFile]).c_str() +
1058 0 : strlen("ogr_"));
1059 : }
1060 : else
1061 1683 : continue;
1062 :
1063 : const std::string osFilename = CPLFormFilenameSafe(
1064 0 : osABISpecificDir.c_str(), papszFiles[iFile], nullptr);
1065 :
1066 0 : CPLErrorReset();
1067 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
1068 0 : void *pRegister = CPLGetSymbol(osFilename.c_str(), osFuncName);
1069 0 : CPLPopErrorHandler();
1070 0 : if (pRegister == nullptr)
1071 : {
1072 0 : CPLString osLastErrorMsg(CPLGetLastErrorMsg());
1073 0 : osFuncName = "GDALRegisterMe";
1074 0 : pRegister = CPLGetSymbol(osFilename.c_str(), osFuncName);
1075 0 : if (pRegister == nullptr)
1076 : {
1077 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1078 : osLastErrorMsg.c_str());
1079 : }
1080 : }
1081 :
1082 0 : if (pRegister != nullptr)
1083 : {
1084 0 : bFoundOnePlugin = true;
1085 0 : CPLDebug("GDAL", "Auto register %s using %s.",
1086 : osFilename.c_str(), osFuncName.c_str());
1087 :
1088 0 : reinterpret_cast<void (*)()>(pRegister)();
1089 : }
1090 : }
1091 :
1092 1683 : CSLDestroy(papszFiles);
1093 : }
1094 :
1095 1683 : CSLDestroy(papszSearchPaths);
1096 :
1097 : // No need to reorder drivers if there are no plugins
1098 1683 : if (!bFoundOnePlugin)
1099 1683 : m_osDriversIniPath.clear();
1100 :
1101 : #endif // GDAL_NO_AUTOLOAD
1102 : }
1103 :
1104 : /************************************************************************/
1105 : /* ReorderDrivers() */
1106 : /************************************************************************/
1107 :
1108 : /**
1109 : * \brief Reorder drivers according to the order of the drivers.ini file.
1110 : *
1111 : * This function is called by GDALAllRegister(), at the end of driver loading,
1112 : * in particular after plugin loading.
1113 : * It will load the drivers.ini configuration file located next to plugins and
1114 : * will use it to reorder the registration order of drivers. This can be
1115 : * important in some situations where multiple drivers could open the same
1116 : * dataset.
1117 : */
1118 :
1119 1683 : void GDALDriverManager::ReorderDrivers()
1120 : {
1121 : #ifndef GDAL_NO_AUTOLOAD
1122 1683 : if (m_osDriversIniPath.empty())
1123 : {
1124 1683 : if (m_oSetPluginFileNames.empty())
1125 0 : return;
1126 :
1127 1683 : m_osDriversIniPath = GetPluginFullPath("drivers.ini");
1128 1683 : if (m_osDriversIniPath.empty())
1129 0 : return;
1130 : }
1131 :
1132 1683 : CPLMutexHolderD(&hDMMutex);
1133 :
1134 1683 : CPLAssert(static_cast<int>(oMapNameToDrivers.size()) == nDrivers);
1135 :
1136 1683 : VSILFILE *fp = VSIFOpenL(m_osDriversIniPath.c_str(), "rb");
1137 1683 : if (fp == nullptr)
1138 0 : return;
1139 :
1140 : // Parse drivers.ini
1141 1683 : bool bInOrderSection = false;
1142 3366 : std::vector<std::string> aosOrderedDrivers;
1143 3366 : std::set<std::string> oSetOrderedDrivers;
1144 496485 : while (const char *pszLine = CPLReadLine2L(fp, 1024, nullptr))
1145 : {
1146 494802 : if (pszLine[0] == '#')
1147 55539 : continue;
1148 454410 : int i = 0;
1149 454410 : while (pszLine[i] != 0 &&
1150 439263 : isspace(static_cast<unsigned char>(pszLine[i])))
1151 0 : i++;
1152 454410 : if (pszLine[i] == 0)
1153 15147 : continue;
1154 439263 : if (strcmp(pszLine, "[order]") == 0)
1155 : {
1156 1683 : bInOrderSection = true;
1157 : }
1158 437580 : else if (pszLine[0] == '[')
1159 : {
1160 0 : bInOrderSection = false;
1161 : }
1162 437580 : else if (bInOrderSection)
1163 : {
1164 875160 : CPLString osUCDriverName(pszLine);
1165 437580 : osUCDriverName.toupper();
1166 437580 : if (cpl::contains(oSetOrderedDrivers, osUCDriverName))
1167 : {
1168 0 : CPLError(CE_Warning, CPLE_AppDefined,
1169 : "Duplicated name %s in [order] section", pszLine);
1170 : }
1171 437580 : else if (cpl::contains(oMapNameToDrivers, osUCDriverName))
1172 : {
1173 402506 : aosOrderedDrivers.emplace_back(pszLine);
1174 402506 : oSetOrderedDrivers.insert(osUCDriverName);
1175 : }
1176 : #ifdef DEBUG_VERBOSE
1177 : else
1178 : {
1179 : // Completely expected situation for "non-maximal" builds,
1180 : // but can help diagnose bad entries in drivers.ini
1181 : CPLDebug("GDAL",
1182 : "Driver %s is listed in %s but not registered.",
1183 : pszLine, m_osDriversIniPath.c_str());
1184 : }
1185 : #endif
1186 : }
1187 494802 : }
1188 1683 : VSIFCloseL(fp);
1189 :
1190 : // Find potential registered drivers not in drivers.ini, and put them in
1191 : // their registration order in aosUnorderedDrivers
1192 3366 : std::vector<std::string> aosUnorderedDrivers;
1193 404198 : for (int i = 0; i < nDrivers; ++i)
1194 : {
1195 402515 : const char *pszName = papoDrivers[i]->GetDescription();
1196 402515 : if (!cpl::contains(oSetOrderedDrivers, CPLString(pszName).toupper()))
1197 : {
1198 : // Could happen for a private plugin
1199 9 : CPLDebug("GDAL",
1200 : "Driver %s is registered but not listed in %s. "
1201 : "It will be registered before other drivers.",
1202 : pszName, m_osDriversIniPath.c_str());
1203 9 : aosUnorderedDrivers.emplace_back(pszName);
1204 : }
1205 : }
1206 :
1207 : // Put aosUnorderedDrivers in front of existing aosOrderedDrivers
1208 1683 : if (!aosUnorderedDrivers.empty())
1209 : {
1210 7 : aosUnorderedDrivers.insert(aosUnorderedDrivers.end(),
1211 : aosOrderedDrivers.begin(),
1212 14 : aosOrderedDrivers.end());
1213 7 : std::swap(aosOrderedDrivers, aosUnorderedDrivers);
1214 : }
1215 :
1216 : // Update papoDrivers[] to reflect aosOrderedDrivers order.
1217 1683 : CPLAssert(static_cast<int>(aosOrderedDrivers.size()) == nDrivers);
1218 404198 : for (int i = 0; i < nDrivers; ++i)
1219 : {
1220 : const auto oIter =
1221 402515 : oMapNameToDrivers.find(CPLString(aosOrderedDrivers[i]).toupper());
1222 402515 : CPLAssert(oIter != oMapNameToDrivers.end());
1223 402515 : papoDrivers[i] = oIter->second;
1224 : }
1225 : #endif
1226 : }
1227 :
1228 : /************************************************************************/
1229 : /* GDALPluginDriverProxy */
1230 : /************************************************************************/
1231 :
1232 : /** Constructor for a plugin driver proxy.
1233 : *
1234 : * @param osPluginFileName Plugin filename. e.g "ogr_Parquet.so"
1235 : */
1236 62145 : GDALPluginDriverProxy::GDALPluginDriverProxy(
1237 62145 : const std::string &osPluginFileName)
1238 62145 : : m_osPluginFileName(osPluginFileName)
1239 : {
1240 62145 : }
1241 :
1242 : //! @cond Doxygen_Suppress
1243 : #define DEFINE_DRIVER_METHOD_GET_CALLBACK(method_name, output_type) \
1244 : GDALDriver::output_type GDALPluginDriverProxy::method_name() \
1245 : { \
1246 : auto poRealDriver = GetRealDriver(); \
1247 : if (!poRealDriver) \
1248 : return nullptr; \
1249 : return poRealDriver->method_name(); \
1250 : }
1251 :
1252 10314 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetOpenCallback, OpenCallback)
1253 1500 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCreateCallback, CreateCallback)
1254 82 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCreateMultiDimensionalCallback,
1255 : CreateMultiDimensionalCallback)
1256 5458 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCreateCopyCallback, CreateCopyCallback)
1257 652 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetDeleteCallback, DeleteCallback)
1258 3 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetRenameCallback, RenameCallback)
1259 0 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCopyFilesCallback, CopyFilesCallback)
1260 :
1261 : //! @endcond
1262 :
1263 1604 : char **GDALPluginDriverProxy::GetMetadata(const char *pszDomain)
1264 : {
1265 1604 : auto poRealDriver = GetRealDriver();
1266 1604 : if (!poRealDriver)
1267 0 : return nullptr;
1268 1604 : return poRealDriver->GetMetadata(pszDomain);
1269 : }
1270 :
1271 773457 : CPLErr GDALPluginDriverProxy::SetMetadataItem(const char *pszName,
1272 : const char *pszValue,
1273 : const char *pszDomain)
1274 : {
1275 773457 : if (!pszDomain || pszDomain[0] == 0)
1276 : {
1277 773457 : if (!EQUAL(pszName, GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE))
1278 : {
1279 773457 : m_oSetMetadataItems.insert(pszName);
1280 : }
1281 : }
1282 773457 : return GDALDriver::SetMetadataItem(pszName, pszValue, pszDomain);
1283 : }
1284 :
1285 : static const char *const apszProxyMetadataItems[] = {
1286 : GDAL_DMD_LONGNAME,
1287 : GDAL_DMD_EXTENSIONS,
1288 : GDAL_DMD_EXTENSION,
1289 : GDAL_DCAP_RASTER,
1290 : GDAL_DCAP_MULTIDIM_RASTER,
1291 : GDAL_DCAP_VECTOR,
1292 : GDAL_DCAP_GNM,
1293 : GDAL_DMD_OPENOPTIONLIST,
1294 : GDAL_DCAP_OPEN,
1295 : GDAL_DCAP_CREATE,
1296 : GDAL_DCAP_CREATE_MULTIDIMENSIONAL,
1297 : GDAL_DCAP_CREATECOPY,
1298 : GDAL_DMD_SUBDATASETS,
1299 : GDAL_DCAP_MULTIPLE_VECTOR_LAYERS,
1300 : GDAL_DCAP_NONSPATIAL,
1301 : GDAL_DMD_CONNECTION_PREFIX,
1302 : GDAL_DCAP_VECTOR_TRANSLATE_FROM,
1303 : GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
1304 : };
1305 :
1306 2131230 : const char *GDALPluginDriverProxy::GetMetadataItem(const char *pszName,
1307 : const char *pszDomain)
1308 : {
1309 2131120 : const auto IsListedProxyMetadataItem = [](const char *pszItem)
1310 : {
1311 16339100 : for (const char *pszListedItem : apszProxyMetadataItems)
1312 : {
1313 16320600 : if (EQUAL(pszItem, pszListedItem))
1314 2112600 : return true;
1315 : }
1316 18519 : return false;
1317 : };
1318 :
1319 2131230 : if (!pszDomain || pszDomain[0] == 0)
1320 : {
1321 2131100 : if (EQUAL(pszName, "IS_NON_LOADED_PLUGIN"))
1322 : {
1323 154 : return !m_poRealDriver ? "YES" : nullptr;
1324 : }
1325 2130940 : else if (EQUAL(pszName, "MISSING_PLUGIN_FILENAME"))
1326 : {
1327 0 : return m_osPluginFullPath.empty() ? m_osPluginFileName.c_str()
1328 0 : : nullptr;
1329 : }
1330 2130940 : else if (IsListedProxyMetadataItem(pszName))
1331 : {
1332 : const char *pszValue =
1333 2112660 : GDALDriver::GetMetadataItem(pszName, pszDomain);
1334 2112570 : if (!pszValue && EQUAL(pszName, GDAL_DMD_EXTENSION))
1335 : {
1336 : const char *pszOtherValue =
1337 51 : GDALDriver::GetMetadataItem(GDAL_DMD_EXTENSIONS, pszDomain);
1338 51 : if (pszOtherValue && strchr(pszOtherValue, ' '))
1339 51 : return pszOtherValue;
1340 : }
1341 2112520 : else if (!pszValue && EQUAL(pszName, GDAL_DMD_EXTENSIONS))
1342 : {
1343 9583 : return GDALDriver::GetMetadataItem(GDAL_DMD_EXTENSION,
1344 9583 : pszDomain);
1345 : }
1346 2102950 : return pszValue;
1347 : }
1348 18511 : else if (cpl::contains(m_oSetMetadataItems, pszName))
1349 : {
1350 15711 : return GDALDriver::GetMetadataItem(pszName, pszDomain);
1351 : }
1352 : }
1353 :
1354 2938 : auto poRealDriver = GetRealDriver();
1355 2839 : if (!poRealDriver)
1356 0 : return nullptr;
1357 2839 : return poRealDriver->GetMetadataItem(pszName, pszDomain);
1358 : }
1359 :
1360 : /************************************************************************/
1361 : /* GetRealDriver() */
1362 : /************************************************************************/
1363 :
1364 22452 : GDALDriver *GDALPluginDriverProxy::GetRealDriver()
1365 : {
1366 : // No need to take the mutex has this member variable is not modified
1367 : // under the mutex.
1368 22452 : if (m_osPluginFullPath.empty())
1369 0 : return nullptr;
1370 :
1371 44904 : CPLMutexHolderD(&hDMMutex);
1372 :
1373 22452 : if (m_poRealDriver)
1374 21896 : return m_poRealDriver.get();
1375 :
1376 556 : auto poDriverManager = GetGDALDriverManager();
1377 556 : auto oIter = poDriverManager->m_oMapRealDrivers.find(GetDescription());
1378 556 : if (oIter != poDriverManager->m_oMapRealDrivers.end())
1379 : {
1380 71 : m_poRealDriver = std::move(oIter->second);
1381 71 : poDriverManager->m_oMapRealDrivers.erase(oIter);
1382 : }
1383 : else
1384 : {
1385 : #ifdef GDAL_NO_AUTOLOAD
1386 : return nullptr;
1387 : #else
1388 970 : CPLString osFuncName;
1389 485 : if (STARTS_WITH(m_osPluginFileName.c_str(), "gdal_"))
1390 : {
1391 268 : osFuncName = "GDALRegister_";
1392 536 : osFuncName += m_osPluginFileName.substr(
1393 : strlen("gdal_"),
1394 536 : m_osPluginFileName.find('.') - strlen("gdal_"));
1395 : }
1396 : else
1397 : {
1398 217 : CPLAssert(STARTS_WITH(m_osPluginFileName.c_str(), "ogr_"));
1399 217 : osFuncName = "RegisterOGR";
1400 434 : osFuncName += m_osPluginFileName.substr(
1401 434 : strlen("ogr_"), m_osPluginFileName.find('.') - strlen("ogr_"));
1402 : }
1403 :
1404 485 : CPLErrorReset();
1405 485 : CPLPushErrorHandler(CPLQuietErrorHandler);
1406 485 : void *pRegister = CPLGetSymbol(m_osPluginFullPath.c_str(), osFuncName);
1407 485 : CPLPopErrorHandler();
1408 485 : if (pRegister == nullptr)
1409 : {
1410 0 : CPLString osLastErrorMsg(CPLGetLastErrorMsg());
1411 0 : osFuncName = "GDALRegisterMe";
1412 0 : pRegister = CPLGetSymbol(m_osPluginFullPath.c_str(), osFuncName);
1413 0 : if (pRegister == nullptr)
1414 : {
1415 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1416 : osLastErrorMsg.c_str());
1417 : }
1418 : }
1419 :
1420 485 : if (pRegister != nullptr)
1421 : {
1422 485 : CPLDebug("GDAL", "On-demand registering %s using %s.",
1423 : m_osPluginFullPath.c_str(), osFuncName.c_str());
1424 :
1425 485 : poDriverManager->m_bInDeferredDriverLoading = true;
1426 : try
1427 : {
1428 485 : reinterpret_cast<void (*)()>(pRegister)();
1429 : }
1430 0 : catch (...)
1431 : {
1432 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s threw an exception",
1433 : osFuncName.c_str());
1434 : }
1435 485 : poDriverManager->m_bInDeferredDriverLoading = false;
1436 :
1437 485 : oIter = poDriverManager->m_oMapRealDrivers.find(GetDescription());
1438 485 : if (oIter == poDriverManager->m_oMapRealDrivers.end())
1439 : {
1440 0 : CPLError(CE_Failure, CPLE_AppDefined,
1441 : "Function %s of %s did not register a driver %s",
1442 : osFuncName.c_str(), m_osPluginFullPath.c_str(),
1443 0 : GetDescription());
1444 : }
1445 : else
1446 : {
1447 485 : m_poRealDriver = std::move(oIter->second);
1448 485 : poDriverManager->m_oMapRealDrivers.erase(oIter);
1449 : }
1450 : }
1451 : #endif // GDAL_NO_AUTOLOAD
1452 : }
1453 :
1454 556 : if (m_poRealDriver)
1455 : {
1456 556 : pfnDelete = m_poRealDriver->pfnDelete;
1457 556 : pfnRename = m_poRealDriver->pfnRename;
1458 556 : pfnCopyFiles = m_poRealDriver->pfnCopyFiles;
1459 :
1460 556 : if (strcmp(GetDescription(), m_poRealDriver->GetDescription()) != 0)
1461 : {
1462 0 : CPLError(
1463 : CE_Warning, CPLE_AppDefined,
1464 : "Driver %s has not the same name as its underlying driver (%s)",
1465 0 : GetDescription(), m_poRealDriver->GetDescription());
1466 : }
1467 :
1468 8326 : for (const auto &osItem : m_oSetMetadataItems)
1469 : {
1470 7770 : const char *pszProxyValue = GetMetadataItem(osItem.c_str());
1471 : const char *pszRealValue =
1472 7770 : m_poRealDriver->GetMetadataItem(osItem.c_str());
1473 7770 : if (pszProxyValue &&
1474 7770 : (!pszRealValue || strcmp(pszProxyValue, pszRealValue) != 0))
1475 : {
1476 0 : CPLError(CE_Warning, CPLE_AppDefined,
1477 : "Proxy driver %s declares %s whereas its real driver "
1478 : "doesn't declare it or with a different value",
1479 0 : GetDescription(), osItem.c_str());
1480 : }
1481 : }
1482 10564 : for (const char *pszListedItem : apszProxyMetadataItems)
1483 : {
1484 : const char *pszRealValue =
1485 10008 : m_poRealDriver->GetMetadataItem(pszListedItem);
1486 10008 : if (pszRealValue)
1487 : {
1488 3800 : const char *pszProxyValue = GetMetadataItem(pszListedItem);
1489 3800 : if (!pszProxyValue || strcmp(pszProxyValue, pszRealValue) != 0)
1490 : {
1491 0 : CPLError(CE_Warning, CPLE_AppDefined,
1492 : "Driver %s declares %s whereas its proxy "
1493 : "doesn't declare it or with a different value",
1494 0 : GetDescription(), pszListedItem);
1495 : }
1496 : }
1497 : }
1498 :
1499 : const auto CheckFunctionPointer =
1500 1112 : [this](void *pfnFuncProxy, void *pfnFuncReal, const char *pszFunc)
1501 : {
1502 1112 : if (pfnFuncReal && !pfnFuncProxy)
1503 : {
1504 0 : CPLError(CE_Warning, CPLE_AppDefined,
1505 : "Driver %s declares a %s callback whereas its proxy "
1506 : "does not declare it",
1507 0 : GetDescription(), pszFunc);
1508 : }
1509 1112 : else if (!pfnFuncReal && pfnFuncProxy)
1510 : {
1511 0 : CPLError(CE_Warning, CPLE_AppDefined,
1512 : "Proxy driver %s declares a %s callback whereas the "
1513 : "real driver does not.",
1514 0 : GetDescription(), pszFunc);
1515 : }
1516 1668 : };
1517 :
1518 556 : CheckFunctionPointer(
1519 556 : reinterpret_cast<void *>(m_poRealDriver->pfnIdentify),
1520 556 : reinterpret_cast<void *>(pfnIdentify), "pfnIdentify");
1521 :
1522 : // The real driver might provide a more accurate identification method
1523 556 : if (m_poRealDriver->pfnIdentify)
1524 556 : pfnIdentify = m_poRealDriver->pfnIdentify;
1525 :
1526 556 : CheckFunctionPointer(
1527 556 : reinterpret_cast<void *>(m_poRealDriver->pfnGetSubdatasetInfoFunc),
1528 556 : reinterpret_cast<void *>(pfnGetSubdatasetInfoFunc),
1529 : "pfnGetSubdatasetInfoFunc");
1530 :
1531 : const auto CheckFunctionPointerVersusCap =
1532 4448 : [this](void *pfnFunc, const char *pszFunc, const char *pszItemName)
1533 : {
1534 2224 : if (pfnFunc && !GetMetadataItem(pszItemName))
1535 : {
1536 0 : CPLError(CE_Warning, CPLE_AppDefined,
1537 : "Driver %s declares a %s callback whereas its proxy "
1538 : "doest not declare %s",
1539 0 : GetDescription(), pszFunc, pszItemName);
1540 : }
1541 2224 : else if (!pfnFunc && GetMetadataItem(pszItemName))
1542 : {
1543 0 : CPLError(CE_Warning, CPLE_AppDefined,
1544 : "Proxy driver %s declares %s whereas the real "
1545 : "driver does not declare a %s callback",
1546 0 : GetDescription(), pszItemName, pszFunc);
1547 : }
1548 2780 : };
1549 :
1550 556 : CheckFunctionPointerVersusCap(
1551 556 : reinterpret_cast<void *>(m_poRealDriver->pfnOpen), "pfnOpen",
1552 : GDAL_DCAP_OPEN);
1553 556 : CheckFunctionPointerVersusCap(
1554 556 : reinterpret_cast<void *>(m_poRealDriver->pfnCreate), "pfnCreate",
1555 : GDAL_DCAP_CREATE);
1556 556 : CheckFunctionPointerVersusCap(
1557 556 : reinterpret_cast<void *>(m_poRealDriver->pfnCreateCopy),
1558 : "pfnCreateCopy", GDAL_DCAP_CREATECOPY);
1559 556 : CheckFunctionPointerVersusCap(
1560 556 : reinterpret_cast<void *>(m_poRealDriver->pfnCreateMultiDimensional),
1561 : "pfnCreateMultiDimensional", GDAL_DCAP_CREATE_MULTIDIMENSIONAL);
1562 : }
1563 :
1564 556 : return m_poRealDriver.get();
1565 : }
1566 :
1567 : /************************************************************************/
1568 : /* GetPluginFullPath() */
1569 : /************************************************************************/
1570 :
1571 63828 : std::string GDALDriverManager::GetPluginFullPath(const char *pszFilename) const
1572 : {
1573 63828 : if (!m_osLastTriedDirectory.empty())
1574 : {
1575 : std::string osFullFilename = CPLFormFilenameSafe(
1576 62447 : m_osLastTriedDirectory.c_str(), pszFilename, nullptr);
1577 : VSIStatBufL sStatBuf;
1578 62447 : if (VSIStatL(osFullFilename.c_str(), &sStatBuf) == 0)
1579 : {
1580 62447 : return osFullFilename;
1581 : }
1582 : }
1583 :
1584 : const char *pszGDAL_DRIVER_PATH =
1585 1381 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr);
1586 1381 : if (pszGDAL_DRIVER_PATH == nullptr)
1587 0 : pszGDAL_DRIVER_PATH = CPLGetConfigOption("OGR_DRIVER_PATH", nullptr);
1588 :
1589 : /* ---------------------------------------------------------------- */
1590 : /* Allow applications to completely disable this search by */
1591 : /* setting the driver path to the special string "disable". */
1592 : /* ---------------------------------------------------------------- */
1593 1381 : if (pszGDAL_DRIVER_PATH != nullptr && EQUAL(pszGDAL_DRIVER_PATH, "disable"))
1594 : {
1595 0 : CPLDebug("GDAL", "GDALDriverManager::GetPluginFullPath() disabled.");
1596 0 : return std::string();
1597 : }
1598 :
1599 : /* ---------------------------------------------------------------- */
1600 : /* Where should we look for stuff? */
1601 : /* ---------------------------------------------------------------- */
1602 : const CPLStringList aosSearchPaths(
1603 2762 : GDALDriverManager::GetSearchPaths(pszGDAL_DRIVER_PATH));
1604 :
1605 : /* ---------------------------------------------------------------- */
1606 : /* Format the ABI version specific subdirectory to look in. */
1607 : /* ---------------------------------------------------------------- */
1608 2762 : CPLString osABIVersion;
1609 :
1610 1381 : osABIVersion.Printf("%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
1611 :
1612 : /* ---------------------------------------------------------------- */
1613 : /* Scan each directory looking for the file of interest. */
1614 : /* ---------------------------------------------------------------- */
1615 1381 : const int nSearchPaths = aosSearchPaths.size();
1616 1381 : for (int iDir = 0; iDir < nSearchPaths; ++iDir)
1617 : {
1618 : std::string osABISpecificDir =
1619 1381 : CPLFormFilenameSafe(aosSearchPaths[iDir], osABIVersion, nullptr);
1620 :
1621 : VSIStatBufL sStatBuf;
1622 1381 : if (VSIStatL(osABISpecificDir.c_str(), &sStatBuf) != 0)
1623 1381 : osABISpecificDir = aosSearchPaths[iDir];
1624 :
1625 : std::string osFullFilename =
1626 1381 : CPLFormFilenameSafe(osABISpecificDir.c_str(), pszFilename, nullptr);
1627 1381 : if (VSIStatL(osFullFilename.c_str(), &sStatBuf) == 0)
1628 : {
1629 1381 : m_osLastTriedDirectory = std::move(osABISpecificDir);
1630 1381 : return osFullFilename;
1631 : }
1632 : }
1633 :
1634 0 : return std::string();
1635 : }
1636 :
1637 : /************************************************************************/
1638 : /* DeclareDeferredPluginDriver() */
1639 : /************************************************************************/
1640 :
1641 : /** Declare a driver that will be loaded as a plugin, when actually needed.
1642 : *
1643 : * @param poProxyDriver Plugin driver proxy
1644 : *
1645 : * @since 3.9
1646 : */
1647 62145 : void GDALDriverManager::DeclareDeferredPluginDriver(
1648 : GDALPluginDriverProxy *poProxyDriver)
1649 : {
1650 62145 : CPLMutexHolderD(&hDMMutex);
1651 :
1652 62145 : const auto &osPluginFileName = poProxyDriver->GetPluginFileName();
1653 62145 : const char *pszPluginFileName = osPluginFileName.c_str();
1654 62145 : if ((!STARTS_WITH(pszPluginFileName, "gdal_") &&
1655 22096 : !STARTS_WITH(pszPluginFileName, "ogr_")) ||
1656 62145 : !strchr(pszPluginFileName, '.'))
1657 : {
1658 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid plugin filename: %s",
1659 : pszPluginFileName);
1660 0 : return;
1661 : }
1662 :
1663 62145 : if (GDALGetDriverByName(poProxyDriver->GetDescription()))
1664 : {
1665 0 : CPLError(CE_Failure, CPLE_AppDefined,
1666 : "DeclarePluginDriver(): trying to register %s several times",
1667 0 : poProxyDriver->GetDescription());
1668 0 : delete poProxyDriver;
1669 0 : return;
1670 : }
1671 :
1672 62145 : const std::string osFullPath = GetPluginFullPath(pszPluginFileName);
1673 62145 : poProxyDriver->SetPluginFullPath(osFullPath);
1674 :
1675 62145 : if (osFullPath.empty())
1676 : {
1677 : // Do not try to re-register a non-existent deferred plugin
1678 : // This would cause memory leaks in case of repeated calls to GDALAllRegister()
1679 : // Cf https://github.com/rasterio/rasterio/issues/3250
1680 0 : for (const auto &poDriver : m_aoHiddenDrivers)
1681 : {
1682 0 : if (EQUAL(poDriver->GetDescription(),
1683 : poProxyDriver->GetDescription()))
1684 : {
1685 0 : delete poProxyDriver;
1686 0 : return;
1687 : }
1688 : }
1689 :
1690 0 : CPLDebug("GDAL",
1691 : "Proxy driver %s *not* registered due to %s not being found",
1692 0 : poProxyDriver->GetDescription(), pszPluginFileName);
1693 0 : RegisterDriver(poProxyDriver, /*bHidden=*/true);
1694 : }
1695 : else
1696 : {
1697 : //CPLDebugOnly("GDAL", "Registering proxy driver %s",
1698 : // poProxyDriver->GetDescription());
1699 62145 : RegisterDriver(poProxyDriver);
1700 62145 : m_oSetPluginFileNames.insert(pszPluginFileName);
1701 : }
1702 : }
1703 :
1704 : /************************************************************************/
1705 : /* GDALDestroyDriverManager() */
1706 : /************************************************************************/
1707 :
1708 : /**
1709 : * \brief Destroy the driver manager.
1710 : *
1711 : * Incidentally unloads all managed drivers.
1712 : *
1713 : * NOTE: This function is not thread safe. It should not be called while
1714 : * other threads are actively using GDAL.
1715 : *
1716 : * \see GDALDestroy()
1717 : * \deprecated Use GDALDestroy() instead
1718 : */
1719 :
1720 1636 : void CPL_STDCALL GDALDestroyDriverManager(void)
1721 :
1722 : {
1723 : // THREADSAFETY: We would like to lock the mutex here, but it
1724 : // needs to be reacquired within the destructor during driver
1725 : // deregistration.
1726 :
1727 : // FIXME: Disable following code as it crashed on OSX CI test.
1728 : // std::lock_guard<std::mutex> oLock(oDeleteMutex);
1729 :
1730 1636 : if (poDM != nullptr)
1731 : {
1732 941 : delete poDM;
1733 941 : poDM = nullptr;
1734 : }
1735 1636 : }
|