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 1485560 : GDALDriverManager *GetGDALDriverManager()
87 :
88 : {
89 1485560 : if (poDM == nullptr)
90 : {
91 2590 : CPLMutexHolderD(&hDMMutex);
92 : // cppcheck-suppress identicalInnerCondition
93 1295 : if (poDM == nullptr)
94 1295 : poDM = new GDALDriverManager();
95 : }
96 :
97 1485560 : CPLAssert(nullptr != poDM);
98 :
99 1485560 : 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 1295 : GDALDriverManager::GDALDriverManager()
110 : {
111 1295 : CPLAssert(poDM == nullptr);
112 :
113 1295 : CPLLoadConfigOptionsFromPredefinedFiles();
114 :
115 1295 : 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 1295 : 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 1295 : }
138 :
139 : /************************************************************************/
140 : /* ~GDALDriverManager() */
141 : /************************************************************************/
142 :
143 : // Keep these two in sync with gdalproxypool.cpp.
144 : void GDALDatasetPoolPreventDestroy();
145 : void GDALDatasetPoolForceDestroy();
146 :
147 1866 : 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 933 : GDALDatasetPoolPreventDestroy();
166 :
167 : // First begin by requesting each remaining dataset to drop any reference
168 : // to other datasets.
169 933 : bool bHasDroppedRef = false;
170 :
171 951 : do
172 : {
173 951 : int nDSCount = 0;
174 951 : 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 951 : bHasDroppedRef = false;
180 1244 : 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 293 : 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 933 : GDALDatasetPoolForceDestroy();
194 :
195 : // Now close the stand-alone datasets.
196 933 : int nDSCount = 0;
197 933 : GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
198 988 : for (int i = 0; i < nDSCount; ++i)
199 : {
200 55 : CPLDebug("GDAL", "Force close of %s (%p) in GDALDriverManager cleanup.",
201 55 : 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 55 : delete papoDSList[i];
207 : }
208 :
209 : /* -------------------------------------------------------------------- */
210 : /* Destroy the existing drivers. */
211 : /* -------------------------------------------------------------------- */
212 222983 : while (GetDriverCount() > 0)
213 : {
214 222050 : GDALDriver *poDriver = GetDriver(0);
215 :
216 222050 : DeregisterDriver(poDriver);
217 222050 : delete poDriver;
218 : }
219 :
220 933 : CleanupPythonDrivers();
221 :
222 933 : GDALDestroyGlobalThreadPool();
223 :
224 : /* -------------------------------------------------------------------- */
225 : /* Cleanup local memory. */
226 : /* -------------------------------------------------------------------- */
227 933 : VSIFree(papoDrivers);
228 :
229 : /* -------------------------------------------------------------------- */
230 : /* Cleanup any Proxy related memory. */
231 : /* -------------------------------------------------------------------- */
232 933 : PamCleanProxyDB();
233 :
234 : /* -------------------------------------------------------------------- */
235 : /* Cleanup any memory allocated by the OGRSpatialReference */
236 : /* related subsystem. */
237 : /* -------------------------------------------------------------------- */
238 933 : 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 933 : CPLFinderClean();
246 933 : CPLFreeConfig();
247 933 : CPLCleanupSharedFileMutex();
248 :
249 : #ifdef HAVE_XERCES
250 933 : OGRCleanupXercesMutex();
251 : #endif
252 :
253 : #ifdef OGRAPISPY_ENABLED
254 933 : OGRAPISpyDestroyMutex();
255 : #endif
256 :
257 : /* -------------------------------------------------------------------- */
258 : /* Cleanup VSIFileManager. */
259 : /* -------------------------------------------------------------------- */
260 933 : VSICleanupFileManager();
261 933 : CPLDestroyCompressorRegistry();
262 :
263 : /* -------------------------------------------------------------------- */
264 : /* Cleanup thread local storage ... I hope the program is all */
265 : /* done with GDAL/OGR! */
266 : /* -------------------------------------------------------------------- */
267 933 : CPLCleanupTLS();
268 :
269 : /* -------------------------------------------------------------------- */
270 : /* Cleanup our mutex. */
271 : /* -------------------------------------------------------------------- */
272 933 : if (hDMMutex)
273 : {
274 933 : CPLDestroyMutex(hDMMutex);
275 933 : hDMMutex = nullptr;
276 : }
277 :
278 : /* -------------------------------------------------------------------- */
279 : /* Cleanup dataset list mutex. */
280 : /* -------------------------------------------------------------------- */
281 933 : if (*GDALGetphDLMutex() != nullptr)
282 : {
283 933 : CPLDestroyMutex(*GDALGetphDLMutex());
284 933 : *GDALGetphDLMutex() = nullptr;
285 : }
286 :
287 : /* -------------------------------------------------------------------- */
288 : /* Cleanup raster block mutex. */
289 : /* -------------------------------------------------------------------- */
290 933 : GDALRasterBlock::DestroyRBMutex();
291 :
292 : /* -------------------------------------------------------------------- */
293 : /* Cleanup gdaltransformer.cpp mutex. */
294 : /* -------------------------------------------------------------------- */
295 933 : GDALCleanupTransformDeserializerMutex();
296 :
297 : /* -------------------------------------------------------------------- */
298 : /* Cleanup cpl_error.cpp mutex. */
299 : /* -------------------------------------------------------------------- */
300 933 : CPLCleanupErrorMutex();
301 :
302 : /* -------------------------------------------------------------------- */
303 : /* Cleanup CPLsetlocale mutex. */
304 : /* -------------------------------------------------------------------- */
305 933 : CPLCleanupSetlocaleMutex();
306 :
307 : /* -------------------------------------------------------------------- */
308 : /* Cleanup curl related stuff. */
309 : /* -------------------------------------------------------------------- */
310 933 : CPLHTTPCleanup();
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Cleanup the master CPL mutex, which governs the creation */
314 : /* of all other mutexes. */
315 : /* -------------------------------------------------------------------- */
316 933 : CPLCleanupMasterMutex();
317 :
318 : /* -------------------------------------------------------------------- */
319 : /* Ensure the global driver manager pointer is NULLed out. */
320 : /* -------------------------------------------------------------------- */
321 933 : if (poDM == this)
322 933 : poDM = nullptr;
323 1866 : }
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 251696 : int GDALDriverManager::GetDriverCount() const
338 :
339 : {
340 251696 : return nDrivers;
341 : }
342 :
343 : //! @cond Doxygen_Suppress
344 67300 : int GDALDriverManager::GetDriverCount(bool bIncludeHidden) const
345 :
346 : {
347 67300 : if (!bIncludeHidden)
348 0 : return nDrivers;
349 67300 : 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 3685 : int CPL_STDCALL GDALGetDriverCount()
385 :
386 : {
387 3685 : 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 11479800 : GDALDriver *GDALDriverManager::GetDriver(int iDriver)
405 :
406 : {
407 22959600 : CPLMutexHolderD(&hDMMutex);
408 :
409 22959600 : return GetDriver_unlocked(iDriver);
410 : }
411 :
412 : //! @cond Doxygen_Suppress
413 7878430 : GDALDriver *GDALDriverManager::GetDriver(int iDriver, bool bIncludeHidden)
414 :
415 : {
416 15763500 : CPLMutexHolderD(&hDMMutex);
417 7885090 : if (!bIncludeHidden || iDriver < nDrivers)
418 7885090 : 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 611357 : GDALDriverH CPL_STDCALL GDALGetDriver(int iDriver)
437 :
438 : {
439 611357 : 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 308646 : int GDALDriverManager::RegisterDriver(GDALDriver *poDriver)
466 : {
467 308646 : return RegisterDriver(poDriver, /*bHidden=*/false);
468 : }
469 :
470 308646 : int GDALDriverManager::RegisterDriver(GDALDriver *poDriver, bool bHidden)
471 : {
472 617292 : CPLMutexHolderD(&hDMMutex);
473 :
474 : /* -------------------------------------------------------------------- */
475 : /* If it is already registered, just return the existing */
476 : /* index. */
477 : /* -------------------------------------------------------------------- */
478 616706 : if (!m_bInDeferredDriverLoading &&
479 308060 : GetDriverByName_unlocked(poDriver->GetDescription()) != nullptr)
480 : {
481 238 : for (int i = 0; i < nDrivers; ++i)
482 : {
483 238 : if (papoDrivers[i] == poDriver)
484 : {
485 1 : return i;
486 : }
487 : }
488 :
489 0 : CPLAssert(false);
490 : }
491 :
492 308645 : if (poDriver->pfnOpen != nullptr ||
493 60779 : poDriver->pfnOpenWithDriverArg != nullptr)
494 247869 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
495 :
496 308645 : if (poDriver->pfnCreate != nullptr || poDriver->pfnCreateEx != nullptr)
497 107621 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
498 :
499 308645 : if (poDriver->pfnCreateCopy != nullptr)
500 55860 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
501 :
502 308645 : if (poDriver->pfnCreateMultiDimensional != nullptr)
503 3914 : 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 308645 : if (poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == nullptr &&
510 311234 : poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == nullptr &&
511 2589 : 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 308645 : if (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) != nullptr &&
519 107671 : poDriver->pfnIdentify == nullptr &&
520 418902 : poDriver->pfnIdentifyEx == nullptr &&
521 2586 : !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 308645 : if (poDriver->pfnVectorTranslateFrom != nullptr)
530 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR_TRANSLATE_FROM, "YES");
531 :
532 309231 : if (m_bInDeferredDriverLoading &&
533 586 : cpl::contains(oMapNameToDrivers,
534 309231 : 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 308060 : if (bHidden)
555 : {
556 0 : m_aoHiddenDrivers.push_back(std::unique_ptr<GDALDriver>(poDriver));
557 0 : return -1;
558 : }
559 :
560 : GDALDriver **papoNewDrivers =
561 308060 : static_cast<GDALDriver **>(VSI_REALLOC_VERBOSE(
562 : papoDrivers, sizeof(GDALDriver *) * (nDrivers + 1)));
563 308060 : if (papoNewDrivers == nullptr)
564 0 : return -1;
565 308060 : papoDrivers = papoNewDrivers;
566 :
567 308060 : papoDrivers[nDrivers] = poDriver;
568 308060 : ++nDrivers;
569 :
570 308060 : oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] =
571 : poDriver;
572 :
573 308060 : int iResult = nDrivers - 1;
574 :
575 308060 : 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 1386 : int CPL_STDCALL GDALRegisterDriver(GDALDriverH hDriver)
589 :
590 : {
591 1386 : VALIDATE_POINTER1(hDriver, "GDALRegisterDriver", 0);
592 :
593 1386 : return GetGDALDriverManager()->RegisterDriver(
594 1386 : 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 222156 : void GDALDriverManager::DeregisterDriver(GDALDriver *poDriver)
612 :
613 : {
614 222156 : CPLMutexHolderD(&hDMMutex);
615 :
616 222156 : int i = 0; // Used after for.
617 244038 : for (; i < nDrivers; ++i)
618 : {
619 244037 : if (papoDrivers[i] == poDriver)
620 222155 : break;
621 : }
622 :
623 222156 : if (i == nDrivers)
624 1 : return;
625 :
626 222155 : oMapNameToDrivers.erase(CPLString(poDriver->GetDescription()).toupper());
627 222155 : --nDrivers;
628 : // Move all following drivers down by one to pack the list.
629 26537900 : while (i < nDrivers)
630 : {
631 26315700 : papoDrivers[i] = papoDrivers[i + 1];
632 26315700 : ++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 470170 : GDALDriver *GDALDriverManager::GetDriverByName(const char *pszName)
670 :
671 : {
672 940340 : CPLMutexHolderD(&hDMMutex);
673 :
674 470170 : if (m_bInDeferredDriverLoading)
675 : {
676 586 : return nullptr;
677 : }
678 :
679 : // Alias old name to new name
680 469584 : if (EQUAL(pszName, "CartoDB"))
681 0 : pszName = "Carto";
682 :
683 469584 : 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 463324 : GDALDriverH CPL_STDCALL GDALGetDriverByName(const char *pszName)
697 :
698 : {
699 463324 : VALIDATE_POINTER1(pszName, "GDALGetDriverByName", nullptr);
700 :
701 463324 : 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 1596 : void GDALDriverManager::AutoSkipDrivers()
725 :
726 : {
727 1596 : char **apapszList[2] = {nullptr, nullptr};
728 1596 : const char *pszGDAL_SKIP = CPLGetConfigOption("GDAL_SKIP", nullptr);
729 1596 : 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 1596 : const char *pszOGR_SKIP = CPLGetConfigOption("OGR_SKIP", nullptr);
737 1596 : 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 4788 : for (auto j : {0, 1})
745 : {
746 3200 : 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 1596 : CSLDestroy(apapszList[0]);
768 1596 : CSLDestroy(apapszList[1]);
769 1596 : }
770 :
771 : /************************************************************************/
772 : /* GetSearchPaths() */
773 : /************************************************************************/
774 :
775 : //! @cond Doxygen_Suppress
776 4486 : char **GDALDriverManager::GetSearchPaths(const char *pszGDAL_DRIVER_PATH)
777 : {
778 4486 : char **papszSearchPaths = nullptr;
779 4486 : CPL_IGNORE_RET_VAL(pszGDAL_DRIVER_PATH);
780 : #ifndef GDAL_NO_AUTOLOAD
781 4486 : if (pszGDAL_DRIVER_PATH != nullptr)
782 : {
783 : #ifdef _WIN32
784 : papszSearchPaths =
785 : CSLTokenizeStringComplex(pszGDAL_DRIVER_PATH, ";", TRUE, FALSE);
786 : #else
787 : papszSearchPaths =
788 4486 : 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 : char szPluginDir[sizeof(szExecPath) + 50];
810 : strcpy(szPluginDir, CPLGetDirname(szExecPath));
811 : strcat(szPluginDir, "\\gdalplugins");
812 : papszSearchPaths = CSLAddString(papszSearchPaths, szPluginDir);
813 : }
814 : else
815 : {
816 : papszSearchPaths =
817 : CSLAddString(papszSearchPaths, "/usr/local/lib/gdalplugins");
818 : }
819 : #endif
820 :
821 : #ifdef MACOSX_FRAMEWORK
822 : #define num2str(x) str(x)
823 : #define str(x) #x
824 : papszSearchPaths = CSLAddString(
825 : papszSearchPaths,
826 : "/Library/Application Support/GDAL/" num2str(
827 : GDAL_VERSION_MAJOR) "." num2str(GDAL_VERSION_MINOR) "/PlugIns");
828 : #endif
829 : }
830 : #endif // GDAL_NO_AUTOLOAD
831 4486 : return papszSearchPaths;
832 : }
833 :
834 : //! @endcond
835 :
836 : /************************************************************************/
837 : /* LoadPlugin() */
838 : /************************************************************************/
839 :
840 : /**
841 : * \brief Load a single GDAL driver/plugin from shared libraries.
842 : *
843 : * This function will load a single named driver/plugin from shared libraries.
844 : * It searches the "driver path" for .so (or .dll) files named
845 : * "gdal_{name}.[so|dll|dylib]" or "ogr_{name}.[so|dll|dylib]", then tries to
846 : * call a function within them called GDALRegister_{name}(), or failing that
847 : * called GDALRegisterMe().
848 : *
849 : * \see GDALDriverManager::AutoLoadDrivers() for the rules used to determine
850 : * which paths are searched for plugin library files.
851 : */
852 :
853 1 : CPLErr GDALDriverManager::LoadPlugin(const char *name)
854 : {
855 : #ifdef GDAL_NO_AUTOLOAD
856 : CPLDebug("GDAL", "GDALDriverManager::LoadPlugin() not compiled in.");
857 : return CE_Failure;
858 : #else
859 : const char *pszGDAL_DRIVER_PATH =
860 1 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr);
861 1 : if (pszGDAL_DRIVER_PATH == nullptr)
862 0 : pszGDAL_DRIVER_PATH = CPLGetConfigOption("OGR_DRIVER_PATH", nullptr);
863 :
864 : /* -------------------------------------------------------------------- */
865 : /* Where should we look for stuff? */
866 : /* -------------------------------------------------------------------- */
867 2 : const CPLStringList aosSearchPaths(GetSearchPaths(pszGDAL_DRIVER_PATH));
868 :
869 : /* -------------------------------------------------------------------- */
870 : /* Format the ABI version specific subdirectory to look in. */
871 : /* -------------------------------------------------------------------- */
872 2 : CPLString osABIVersion;
873 :
874 1 : osABIVersion.Printf("%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
875 :
876 : /* -------------------------------------------------------------------- */
877 : /* Scan each directory looking for files matching */
878 : /* gdal_{name}.[so|dll|dylib] or ogr_{name}.[so|dll|dylib] */
879 : /* -------------------------------------------------------------------- */
880 1 : const int nSearchPaths = aosSearchPaths.size();
881 2 : for (int iDir = 0; iDir < nSearchPaths; ++iDir)
882 : {
883 : CPLString osABISpecificDir =
884 1 : CPLFormFilename(aosSearchPaths[iDir], osABIVersion, nullptr);
885 :
886 : VSIStatBufL sStatBuf;
887 1 : if (VSIStatL(osABISpecificDir, &sStatBuf) != 0)
888 1 : osABISpecificDir = aosSearchPaths[iDir];
889 :
890 3 : CPLString gdal_or_ogr[2] = {"gdal_", "ogr_"};
891 4 : CPLString platformExtensions[3] = {"so", "dll", "dylib"};
892 :
893 3 : for (const CPLString &prefix : gdal_or_ogr)
894 : {
895 8 : for (const CPLString &extension : platformExtensions)
896 : {
897 6 : const char *pszFilename = CPLFormFilename(
898 : osABISpecificDir, CPLSPrintf("%s%s", prefix.c_str(), name),
899 : extension);
900 6 : if (VSIStatL(pszFilename, &sStatBuf) != 0)
901 6 : continue;
902 :
903 0 : CPLString osFuncName;
904 0 : if (EQUAL(prefix, "gdal_"))
905 : {
906 0 : osFuncName.Printf("GDALRegister_%s", name);
907 : }
908 : else
909 : {
910 0 : osFuncName.Printf("RegisterOGR%s", name);
911 : }
912 0 : CPLErrorReset();
913 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
914 0 : void *pRegister = CPLGetSymbol(pszFilename, osFuncName);
915 0 : CPLPopErrorHandler();
916 0 : if (pRegister == nullptr)
917 : {
918 0 : CPLString osLastErrorMsg(CPLGetLastErrorMsg());
919 0 : osFuncName = "GDALRegisterMe";
920 0 : pRegister = CPLGetSymbol(pszFilename, osFuncName);
921 0 : if (pRegister == nullptr)
922 : {
923 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
924 : osLastErrorMsg.c_str());
925 0 : return CE_Failure;
926 : }
927 : }
928 0 : CPLDebug("GDAL", "Registering %s using %s in %s", name,
929 : osFuncName.c_str(), pszFilename);
930 0 : CPLErrorReset();
931 0 : reinterpret_cast<void (*)()>(pRegister)();
932 0 : if (CPLGetErrorCounter() > 0)
933 : {
934 0 : return CE_Failure;
935 : }
936 0 : return CE_None;
937 : }
938 : }
939 : }
940 1 : CPLError(CE_Failure, CPLE_AppDefined,
941 : "Failed to find driver %s in configured driver paths.", name);
942 1 : return CE_Failure;
943 : #endif // GDAL_NO_AUTOLOAD
944 : }
945 :
946 : /************************************************************************/
947 : /* AutoLoadDrivers() */
948 : /************************************************************************/
949 :
950 : /**
951 : * \brief Auto-load GDAL drivers from shared libraries.
952 : *
953 : * This function will automatically load drivers from shared libraries. It
954 : * searches the "driver path" for .so (or .dll) files that start with the
955 : * prefix "gdal_X.so". It then tries to load them and then tries to call a
956 : * function within them called GDALRegister_X() where the 'X' is the same as
957 : * the remainder of the shared library basename ('X' is case sensitive), or
958 : * failing that to call GDALRegisterMe().
959 : *
960 : * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
961 : * environment variable it set, it is taken to be a list of directories to
962 : * search separated by colons on UNIX, or semi-colons on Windows. Otherwise
963 : * the /usr/local/lib/gdalplugins directory, and (if known) the
964 : * lib/gdalplugins subdirectory of the gdal home directory are searched on
965 : * UNIX and $(BINDIR)\\gdalplugins on Windows.
966 : *
967 : * Auto loading can be completely disabled by setting the GDAL_DRIVER_PATH
968 : * config option to "disable".
969 : *
970 : * Starting with gdal 3.5, the default search path $(prefix)/lib/gdalplugins
971 : * can be overridden at compile time by passing
972 : * -DINSTALL_PLUGIN_DIR=/another/path to cmake.
973 : */
974 :
975 1596 : void GDALDriverManager::AutoLoadDrivers()
976 :
977 : {
978 : #ifdef GDAL_NO_AUTOLOAD
979 : CPLDebug("GDAL", "GDALDriverManager::AutoLoadDrivers() not compiled in.");
980 : #else
981 : const char *pszGDAL_DRIVER_PATH =
982 1596 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr);
983 1596 : if (pszGDAL_DRIVER_PATH == nullptr)
984 0 : pszGDAL_DRIVER_PATH = CPLGetConfigOption("OGR_DRIVER_PATH", nullptr);
985 :
986 : /* -------------------------------------------------------------------- */
987 : /* Allow applications to completely disable this search by */
988 : /* setting the driver path to the special string "disable". */
989 : /* -------------------------------------------------------------------- */
990 1596 : if (pszGDAL_DRIVER_PATH != nullptr && EQUAL(pszGDAL_DRIVER_PATH, "disable"))
991 : {
992 0 : CPLDebug("GDAL", "GDALDriverManager::AutoLoadDrivers() disabled.");
993 0 : return;
994 : }
995 :
996 : /* -------------------------------------------------------------------- */
997 : /* Where should we look for stuff? */
998 : /* -------------------------------------------------------------------- */
999 1596 : char **papszSearchPaths = GetSearchPaths(pszGDAL_DRIVER_PATH);
1000 :
1001 : /* -------------------------------------------------------------------- */
1002 : /* Format the ABI version specific subdirectory to look in. */
1003 : /* -------------------------------------------------------------------- */
1004 3192 : CPLString osABIVersion;
1005 :
1006 1596 : osABIVersion.Printf("%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
1007 :
1008 : /* -------------------------------------------------------------------- */
1009 : /* Scan each directory looking for files starting with gdal_ */
1010 : /* -------------------------------------------------------------------- */
1011 1596 : const int nSearchPaths = CSLCount(papszSearchPaths);
1012 1596 : bool bFoundOnePlugin = false;
1013 3192 : for (int iDir = 0; iDir < nSearchPaths; ++iDir)
1014 : {
1015 : CPLString osABISpecificDir =
1016 3192 : CPLFormFilename(papszSearchPaths[iDir], osABIVersion, nullptr);
1017 :
1018 : VSIStatBufL sStatBuf;
1019 1596 : if (VSIStatL(osABISpecificDir, &sStatBuf) != 0)
1020 1596 : osABISpecificDir = papszSearchPaths[iDir];
1021 :
1022 1596 : char **papszFiles = VSIReadDir(osABISpecificDir);
1023 1596 : const int nFileCount = CSLCount(papszFiles);
1024 :
1025 65436 : for (int iFile = 0; iFile < nFileCount; ++iFile)
1026 : {
1027 63840 : const char *pszExtension = CPLGetExtension(papszFiles[iFile]);
1028 :
1029 63840 : if (!EQUAL(pszExtension, "dll") && !EQUAL(pszExtension, "so") &&
1030 4788 : !EQUAL(pszExtension, "dylib"))
1031 : {
1032 4788 : if (strcmp(papszFiles[iFile], "drivers.ini") == 0)
1033 : {
1034 : m_osDriversIniPath = CPLFormFilename(
1035 1596 : osABISpecificDir, papszFiles[iFile], nullptr);
1036 : }
1037 63840 : continue;
1038 : }
1039 :
1040 59052 : if (cpl::contains(m_oSetPluginFileNames, papszFiles[iFile]))
1041 : {
1042 57456 : continue;
1043 : }
1044 :
1045 1596 : CPLString osFuncName;
1046 1596 : if (STARTS_WITH_CI(papszFiles[iFile], "gdal_"))
1047 : {
1048 : osFuncName.Printf("GDALRegister_%s",
1049 0 : CPLGetBasename(papszFiles[iFile]) +
1050 0 : strlen("gdal_"));
1051 : }
1052 1596 : else if (STARTS_WITH_CI(papszFiles[iFile], "ogr_"))
1053 : {
1054 : osFuncName.Printf("RegisterOGR%s",
1055 0 : CPLGetBasename(papszFiles[iFile]) +
1056 0 : strlen("ogr_"));
1057 : }
1058 : else
1059 1596 : continue;
1060 :
1061 : const char *pszFilename =
1062 0 : CPLFormFilename(osABISpecificDir, papszFiles[iFile], nullptr);
1063 :
1064 0 : CPLErrorReset();
1065 0 : CPLPushErrorHandler(CPLQuietErrorHandler);
1066 0 : void *pRegister = CPLGetSymbol(pszFilename, osFuncName);
1067 0 : CPLPopErrorHandler();
1068 0 : if (pRegister == nullptr)
1069 : {
1070 0 : CPLString osLastErrorMsg(CPLGetLastErrorMsg());
1071 0 : osFuncName = "GDALRegisterMe";
1072 0 : pRegister = CPLGetSymbol(pszFilename, osFuncName);
1073 0 : if (pRegister == nullptr)
1074 : {
1075 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1076 : osLastErrorMsg.c_str());
1077 : }
1078 : }
1079 :
1080 0 : if (pRegister != nullptr)
1081 : {
1082 0 : bFoundOnePlugin = true;
1083 0 : CPLDebug("GDAL", "Auto register %s using %s.", pszFilename,
1084 : osFuncName.c_str());
1085 :
1086 0 : reinterpret_cast<void (*)()>(pRegister)();
1087 : }
1088 : }
1089 :
1090 1596 : CSLDestroy(papszFiles);
1091 : }
1092 :
1093 1596 : CSLDestroy(papszSearchPaths);
1094 :
1095 : // No need to reorder drivers if there are no plugins
1096 1596 : if (!bFoundOnePlugin)
1097 1596 : m_osDriversIniPath.clear();
1098 :
1099 : #endif // GDAL_NO_AUTOLOAD
1100 : }
1101 :
1102 : /************************************************************************/
1103 : /* ReorderDrivers() */
1104 : /************************************************************************/
1105 :
1106 : /**
1107 : * \brief Reorder drivers according to the order of the drivers.ini file.
1108 : *
1109 : * This function is called by GDALAllRegister(), at the end of driver loading,
1110 : * in particular after plugin loading.
1111 : * It will load the drivers.ini configuration file located next to plugins and
1112 : * will use it to reorder the registration order of drivers. This can be
1113 : * important in some situations where multiple drivers could open the same
1114 : * dataset.
1115 : */
1116 :
1117 1596 : void GDALDriverManager::ReorderDrivers()
1118 : {
1119 : #ifndef GDAL_NO_AUTOLOAD
1120 1596 : if (m_osDriversIniPath.empty())
1121 : {
1122 1596 : if (m_oSetPluginFileNames.empty())
1123 0 : return;
1124 :
1125 1596 : m_osDriversIniPath = GetPluginFullPath("drivers.ini");
1126 1596 : if (m_osDriversIniPath.empty())
1127 0 : return;
1128 : }
1129 :
1130 1596 : CPLMutexHolderD(&hDMMutex);
1131 :
1132 1596 : CPLAssert(static_cast<int>(oMapNameToDrivers.size()) == nDrivers);
1133 :
1134 1596 : VSILFILE *fp = VSIFOpenL(m_osDriversIniPath.c_str(), "rb");
1135 1596 : if (fp == nullptr)
1136 0 : return;
1137 :
1138 : // Parse drivers.ini
1139 1596 : bool bInOrderSection = false;
1140 3192 : std::vector<std::string> aosOrderedDrivers;
1141 3192 : std::set<std::string> oSetOrderedDrivers;
1142 469224 : while (const char *pszLine = CPLReadLine2L(fp, 1024, nullptr))
1143 : {
1144 467628 : if (pszLine[0] == '#')
1145 52668 : continue;
1146 429324 : int i = 0;
1147 429324 : while (pszLine[i] != 0 &&
1148 414960 : isspace(static_cast<unsigned char>(pszLine[i])))
1149 0 : i++;
1150 429324 : if (pszLine[i] == 0)
1151 14364 : continue;
1152 414960 : if (strcmp(pszLine, "[order]") == 0)
1153 : {
1154 1596 : bInOrderSection = true;
1155 : }
1156 413364 : else if (pszLine[0] == '[')
1157 : {
1158 0 : bInOrderSection = false;
1159 : }
1160 413364 : else if (bInOrderSection)
1161 : {
1162 826728 : CPLString osUCDriverName(pszLine);
1163 413364 : osUCDriverName.toupper();
1164 413364 : if (cpl::contains(oSetOrderedDrivers, osUCDriverName))
1165 : {
1166 0 : CPLError(CE_Warning, CPLE_AppDefined,
1167 : "Duplicated name %s in [order] section", pszLine);
1168 : }
1169 413364 : else if (cpl::contains(oMapNameToDrivers, osUCDriverName))
1170 : {
1171 380120 : aosOrderedDrivers.emplace_back(pszLine);
1172 380120 : oSetOrderedDrivers.insert(osUCDriverName);
1173 : }
1174 : #ifdef DEBUG_VERBOSE
1175 : else
1176 : {
1177 : // Completely expected situation for "non-maximal" builds,
1178 : // but can help diagnose bad entries in drivers.ini
1179 : CPLDebug("GDAL",
1180 : "Driver %s is listed in %s but not registered.",
1181 : pszLine, m_osDriversIniPath.c_str());
1182 : }
1183 : #endif
1184 : }
1185 467628 : }
1186 1596 : VSIFCloseL(fp);
1187 :
1188 : // Find potential registered drivers not in drivers.ini, and put them in
1189 : // their registration order in aosUnorderedDrivers
1190 3192 : std::vector<std::string> aosUnorderedDrivers;
1191 381725 : for (int i = 0; i < nDrivers; ++i)
1192 : {
1193 380129 : const char *pszName = papoDrivers[i]->GetDescription();
1194 380129 : if (!cpl::contains(oSetOrderedDrivers, CPLString(pszName).toupper()))
1195 : {
1196 : // Could happen for a private plugin
1197 9 : CPLDebug("GDAL",
1198 : "Driver %s is registered but not listed in %s. "
1199 : "It will be registered before other drivers.",
1200 : pszName, m_osDriversIniPath.c_str());
1201 9 : aosUnorderedDrivers.emplace_back(pszName);
1202 : }
1203 : }
1204 :
1205 : // Put aosUnorderedDrivers in front of existing aosOrderedDrivers
1206 1596 : if (!aosUnorderedDrivers.empty())
1207 : {
1208 7 : aosUnorderedDrivers.insert(aosUnorderedDrivers.end(),
1209 : aosOrderedDrivers.begin(),
1210 14 : aosOrderedDrivers.end());
1211 7 : std::swap(aosOrderedDrivers, aosUnorderedDrivers);
1212 : }
1213 :
1214 : // Update papoDrivers[] to reflect aosOrderedDrivers order.
1215 1596 : CPLAssert(static_cast<int>(aosOrderedDrivers.size()) == nDrivers);
1216 381725 : for (int i = 0; i < nDrivers; ++i)
1217 : {
1218 : const auto oIter =
1219 380129 : oMapNameToDrivers.find(CPLString(aosOrderedDrivers[i]).toupper());
1220 380129 : CPLAssert(oIter != oMapNameToDrivers.end());
1221 380129 : papoDrivers[i] = oIter->second;
1222 : }
1223 : #endif
1224 : }
1225 :
1226 : /************************************************************************/
1227 : /* GDALPluginDriverProxy */
1228 : /************************************************************************/
1229 :
1230 : /** Constructor for a plugin driver proxy.
1231 : *
1232 : * @param osPluginFileName Plugin filename. e.g "ogr_Parquet.so"
1233 : */
1234 58185 : GDALPluginDriverProxy::GDALPluginDriverProxy(
1235 58185 : const std::string &osPluginFileName)
1236 58185 : : m_osPluginFileName(osPluginFileName)
1237 : {
1238 58185 : }
1239 :
1240 : //! @cond Doxygen_Suppress
1241 : #define DEFINE_DRIVER_METHOD_GET_CALLBACK(method_name, output_type) \
1242 : GDALDriver::output_type GDALPluginDriverProxy::method_name() \
1243 : { \
1244 : auto poRealDriver = GetRealDriver(); \
1245 : if (!poRealDriver) \
1246 : return nullptr; \
1247 : return poRealDriver->method_name(); \
1248 : }
1249 :
1250 10082 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetOpenCallback, OpenCallback)
1251 1500 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCreateCallback, CreateCallback)
1252 82 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCreateMultiDimensionalCallback,
1253 : CreateMultiDimensionalCallback)
1254 5465 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCreateCopyCallback, CreateCopyCallback)
1255 666 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetDeleteCallback, DeleteCallback)
1256 3 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetRenameCallback, RenameCallback)
1257 0 : DEFINE_DRIVER_METHOD_GET_CALLBACK(GetCopyFilesCallback, CopyFilesCallback)
1258 :
1259 : //! @endcond
1260 :
1261 1625 : char **GDALPluginDriverProxy::GetMetadata(const char *pszDomain)
1262 : {
1263 1625 : auto poRealDriver = GetRealDriver();
1264 1625 : if (!poRealDriver)
1265 0 : return nullptr;
1266 1625 : return poRealDriver->GetMetadata(pszDomain);
1267 : }
1268 :
1269 724177 : CPLErr GDALPluginDriverProxy::SetMetadataItem(const char *pszName,
1270 : const char *pszValue,
1271 : const char *pszDomain)
1272 : {
1273 724177 : if (!pszDomain || pszDomain[0] == 0)
1274 : {
1275 724177 : if (!EQUAL(pszName, GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE))
1276 : {
1277 724177 : m_oSetMetadataItems.insert(pszName);
1278 : }
1279 : }
1280 724177 : return GDALDriver::SetMetadataItem(pszName, pszValue, pszDomain);
1281 : }
1282 :
1283 : static const char *const apszProxyMetadataItems[] = {
1284 : GDAL_DMD_LONGNAME,
1285 : GDAL_DMD_EXTENSIONS,
1286 : GDAL_DMD_EXTENSION,
1287 : GDAL_DCAP_RASTER,
1288 : GDAL_DCAP_MULTIDIM_RASTER,
1289 : GDAL_DCAP_VECTOR,
1290 : GDAL_DCAP_GNM,
1291 : GDAL_DMD_OPENOPTIONLIST,
1292 : GDAL_DCAP_OPEN,
1293 : GDAL_DCAP_CREATE,
1294 : GDAL_DCAP_CREATE_MULTIDIMENSIONAL,
1295 : GDAL_DCAP_CREATECOPY,
1296 : GDAL_DMD_SUBDATASETS,
1297 : GDAL_DCAP_MULTIPLE_VECTOR_LAYERS,
1298 : GDAL_DCAP_NONSPATIAL,
1299 : GDAL_DMD_CONNECTION_PREFIX,
1300 : GDAL_DCAP_VECTOR_TRANSLATE_FROM,
1301 : GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
1302 : };
1303 :
1304 2095840 : const char *GDALPluginDriverProxy::GetMetadataItem(const char *pszName,
1305 : const char *pszDomain)
1306 : {
1307 2095180 : const auto IsListedProxyMetadataItem = [](const char *pszItem)
1308 : {
1309 16045300 : for (const char *pszListedItem : apszProxyMetadataItems)
1310 : {
1311 16026900 : if (EQUAL(pszItem, pszListedItem))
1312 2076860 : return true;
1313 : }
1314 18319 : return false;
1315 : };
1316 :
1317 2095840 : if (!pszDomain || pszDomain[0] == 0)
1318 : {
1319 2095810 : if (EQUAL(pszName, "IS_NON_LOADED_PLUGIN"))
1320 : {
1321 151 : return !m_poRealDriver ? "YES" : nullptr;
1322 : }
1323 2095660 : else if (EQUAL(pszName, "MISSING_PLUGIN_FILENAME"))
1324 : {
1325 0 : return m_osPluginFullPath.empty() ? m_osPluginFileName.c_str()
1326 0 : : nullptr;
1327 : }
1328 2095660 : else if (IsListedProxyMetadataItem(pszName))
1329 : {
1330 : const char *pszValue =
1331 2077600 : GDALDriver::GetMetadataItem(pszName, pszDomain);
1332 2076930 : if (!pszValue && EQUAL(pszName, GDAL_DMD_EXTENSION))
1333 : {
1334 : const char *pszOtherValue =
1335 51 : GDALDriver::GetMetadataItem(GDAL_DMD_EXTENSIONS, pszDomain);
1336 51 : if (pszOtherValue && strchr(pszOtherValue, ' '))
1337 51 : return pszOtherValue;
1338 : }
1339 2076880 : else if (!pszValue && EQUAL(pszName, GDAL_DMD_EXTENSIONS))
1340 : {
1341 9206 : return GDALDriver::GetMetadataItem(GDAL_DMD_EXTENSION,
1342 9206 : pszDomain);
1343 : }
1344 2067690 : return pszValue;
1345 : }
1346 18312 : else if (cpl::contains(m_oSetMetadataItems, pszName))
1347 : {
1348 15714 : return GDALDriver::GetMetadataItem(pszName, pszDomain);
1349 : }
1350 : }
1351 :
1352 2626 : auto poRealDriver = GetRealDriver();
1353 2628 : if (!poRealDriver)
1354 0 : return nullptr;
1355 2628 : return poRealDriver->GetMetadataItem(pszName, pszDomain);
1356 : }
1357 :
1358 : /************************************************************************/
1359 : /* GetRealDriver() */
1360 : /************************************************************************/
1361 :
1362 22051 : GDALDriver *GDALPluginDriverProxy::GetRealDriver()
1363 : {
1364 : // No need to take the mutex has this member variable is not modified
1365 : // under the mutex.
1366 22051 : if (m_osPluginFullPath.empty())
1367 0 : return nullptr;
1368 :
1369 44102 : CPLMutexHolderD(&hDMMutex);
1370 :
1371 22051 : if (m_poRealDriver)
1372 21495 : return m_poRealDriver.get();
1373 :
1374 556 : auto poDriverManager = GetGDALDriverManager();
1375 556 : auto oIter = poDriverManager->m_oMapRealDrivers.find(GetDescription());
1376 556 : if (oIter != poDriverManager->m_oMapRealDrivers.end())
1377 : {
1378 71 : m_poRealDriver = std::move(oIter->second);
1379 71 : poDriverManager->m_oMapRealDrivers.erase(oIter);
1380 : }
1381 : else
1382 : {
1383 970 : CPLString osFuncName;
1384 485 : if (STARTS_WITH(m_osPluginFileName.c_str(), "gdal_"))
1385 : {
1386 268 : osFuncName = "GDALRegister_";
1387 536 : osFuncName += m_osPluginFileName.substr(
1388 : strlen("gdal_"),
1389 536 : m_osPluginFileName.find('.') - strlen("gdal_"));
1390 : }
1391 : else
1392 : {
1393 217 : CPLAssert(STARTS_WITH(m_osPluginFileName.c_str(), "ogr_"));
1394 217 : osFuncName = "RegisterOGR";
1395 434 : osFuncName += m_osPluginFileName.substr(
1396 434 : strlen("ogr_"), m_osPluginFileName.find('.') - strlen("ogr_"));
1397 : }
1398 :
1399 485 : CPLErrorReset();
1400 485 : CPLPushErrorHandler(CPLQuietErrorHandler);
1401 485 : void *pRegister = CPLGetSymbol(m_osPluginFullPath.c_str(), osFuncName);
1402 485 : CPLPopErrorHandler();
1403 485 : if (pRegister == nullptr)
1404 : {
1405 0 : CPLString osLastErrorMsg(CPLGetLastErrorMsg());
1406 0 : osFuncName = "GDALRegisterMe";
1407 0 : pRegister = CPLGetSymbol(m_osPluginFullPath.c_str(), osFuncName);
1408 0 : if (pRegister == nullptr)
1409 : {
1410 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s",
1411 : osLastErrorMsg.c_str());
1412 : }
1413 : }
1414 :
1415 485 : if (pRegister != nullptr)
1416 : {
1417 485 : CPLDebug("GDAL", "On-demand registering %s using %s.",
1418 : m_osPluginFullPath.c_str(), osFuncName.c_str());
1419 :
1420 485 : poDriverManager->m_bInDeferredDriverLoading = true;
1421 : try
1422 : {
1423 485 : reinterpret_cast<void (*)()>(pRegister)();
1424 : }
1425 0 : catch (...)
1426 : {
1427 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s threw an exception",
1428 : osFuncName.c_str());
1429 : }
1430 485 : poDriverManager->m_bInDeferredDriverLoading = false;
1431 :
1432 485 : oIter = poDriverManager->m_oMapRealDrivers.find(GetDescription());
1433 485 : if (oIter == poDriverManager->m_oMapRealDrivers.end())
1434 : {
1435 0 : CPLError(CE_Failure, CPLE_AppDefined,
1436 : "Function %s of %s did not register a driver %s",
1437 : osFuncName.c_str(), m_osPluginFullPath.c_str(),
1438 0 : GetDescription());
1439 : }
1440 : else
1441 : {
1442 485 : m_poRealDriver = std::move(oIter->second);
1443 485 : poDriverManager->m_oMapRealDrivers.erase(oIter);
1444 : }
1445 : }
1446 : }
1447 :
1448 556 : if (m_poRealDriver)
1449 : {
1450 556 : pfnDelete = m_poRealDriver->pfnDelete;
1451 556 : pfnRename = m_poRealDriver->pfnRename;
1452 556 : pfnCopyFiles = m_poRealDriver->pfnCopyFiles;
1453 :
1454 556 : if (strcmp(GetDescription(), m_poRealDriver->GetDescription()) != 0)
1455 : {
1456 0 : CPLError(
1457 : CE_Warning, CPLE_AppDefined,
1458 : "Driver %s has not the same name as its underlying driver (%s)",
1459 0 : GetDescription(), m_poRealDriver->GetDescription());
1460 : }
1461 :
1462 8326 : for (const auto &osItem : m_oSetMetadataItems)
1463 : {
1464 7770 : const char *pszProxyValue = GetMetadataItem(osItem.c_str());
1465 : const char *pszRealValue =
1466 7770 : m_poRealDriver->GetMetadataItem(osItem.c_str());
1467 7770 : if (pszProxyValue &&
1468 7770 : (!pszRealValue || strcmp(pszProxyValue, pszRealValue) != 0))
1469 : {
1470 0 : CPLError(CE_Warning, CPLE_AppDefined,
1471 : "Proxy driver %s declares %s whereas its real driver "
1472 : "doesn't declare it or with a different value",
1473 0 : GetDescription(), osItem.c_str());
1474 : }
1475 : }
1476 10564 : for (const char *pszListedItem : apszProxyMetadataItems)
1477 : {
1478 : const char *pszRealValue =
1479 10008 : m_poRealDriver->GetMetadataItem(pszListedItem);
1480 10008 : if (pszRealValue)
1481 : {
1482 3800 : const char *pszProxyValue = GetMetadataItem(pszListedItem);
1483 3800 : if (!pszProxyValue || strcmp(pszProxyValue, pszRealValue) != 0)
1484 : {
1485 0 : CPLError(CE_Warning, CPLE_AppDefined,
1486 : "Driver %s declares %s whereas its proxy "
1487 : "doesn't declare it or with a different value",
1488 0 : GetDescription(), pszListedItem);
1489 : }
1490 : }
1491 : }
1492 :
1493 : const auto CheckFunctionPointer =
1494 1112 : [this](void *pfnFuncProxy, void *pfnFuncReal, const char *pszFunc)
1495 : {
1496 1112 : if (pfnFuncReal && !pfnFuncProxy)
1497 : {
1498 0 : CPLError(CE_Warning, CPLE_AppDefined,
1499 : "Driver %s declares a %s callback whereas its proxy "
1500 : "does not declare it",
1501 0 : GetDescription(), pszFunc);
1502 : }
1503 1112 : else if (!pfnFuncReal && pfnFuncProxy)
1504 : {
1505 0 : CPLError(CE_Warning, CPLE_AppDefined,
1506 : "Proxy driver %s declares a %s callback whereas the "
1507 : "real driver does not.",
1508 0 : GetDescription(), pszFunc);
1509 : }
1510 1668 : };
1511 :
1512 556 : CheckFunctionPointer(
1513 556 : reinterpret_cast<void *>(m_poRealDriver->pfnIdentify),
1514 556 : reinterpret_cast<void *>(pfnIdentify), "pfnIdentify");
1515 :
1516 : // The real driver might provide a more accurate identification method
1517 556 : if (m_poRealDriver->pfnIdentify)
1518 556 : pfnIdentify = m_poRealDriver->pfnIdentify;
1519 :
1520 556 : CheckFunctionPointer(
1521 556 : reinterpret_cast<void *>(m_poRealDriver->pfnGetSubdatasetInfoFunc),
1522 556 : reinterpret_cast<void *>(pfnGetSubdatasetInfoFunc),
1523 : "pfnGetSubdatasetInfoFunc");
1524 :
1525 : const auto CheckFunctionPointerVersusCap =
1526 4448 : [this](void *pfnFunc, const char *pszFunc, const char *pszItemName)
1527 : {
1528 2224 : if (pfnFunc && !GetMetadataItem(pszItemName))
1529 : {
1530 0 : CPLError(CE_Warning, CPLE_AppDefined,
1531 : "Driver %s declares a %s callback whereas its proxy "
1532 : "doest not declare %s",
1533 0 : GetDescription(), pszFunc, pszItemName);
1534 : }
1535 2224 : else if (!pfnFunc && GetMetadataItem(pszItemName))
1536 : {
1537 0 : CPLError(CE_Warning, CPLE_AppDefined,
1538 : "Proxy driver %s declares %s whereas the real "
1539 : "driver does not declare a %s callback",
1540 0 : GetDescription(), pszItemName, pszFunc);
1541 : }
1542 2780 : };
1543 :
1544 556 : CheckFunctionPointerVersusCap(
1545 556 : reinterpret_cast<void *>(m_poRealDriver->pfnOpen), "pfnOpen",
1546 : GDAL_DCAP_OPEN);
1547 556 : CheckFunctionPointerVersusCap(
1548 556 : reinterpret_cast<void *>(m_poRealDriver->pfnCreate), "pfnCreate",
1549 : GDAL_DCAP_CREATE);
1550 556 : CheckFunctionPointerVersusCap(
1551 556 : reinterpret_cast<void *>(m_poRealDriver->pfnCreateCopy),
1552 : "pfnCreateCopy", GDAL_DCAP_CREATECOPY);
1553 556 : CheckFunctionPointerVersusCap(
1554 556 : reinterpret_cast<void *>(m_poRealDriver->pfnCreateMultiDimensional),
1555 : "pfnCreateMultiDimensional", GDAL_DCAP_CREATE_MULTIDIMENSIONAL);
1556 : }
1557 :
1558 556 : return m_poRealDriver.get();
1559 : }
1560 :
1561 : /************************************************************************/
1562 : /* GetPluginFullPath() */
1563 : /************************************************************************/
1564 :
1565 59781 : std::string GDALDriverManager::GetPluginFullPath(const char *pszFilename) const
1566 : {
1567 59781 : if (!m_osLastTriedDirectory.empty())
1568 : {
1569 58488 : const char *pszFullFilename = CPLFormFilename(
1570 58488 : m_osLastTriedDirectory.c_str(), pszFilename, nullptr);
1571 : VSIStatBufL sStatBuf;
1572 58488 : if (VSIStatL(pszFullFilename, &sStatBuf) == 0)
1573 : {
1574 58488 : return pszFullFilename;
1575 : }
1576 : }
1577 :
1578 : const char *pszGDAL_DRIVER_PATH =
1579 1293 : CPLGetConfigOption("GDAL_DRIVER_PATH", nullptr);
1580 1293 : if (pszGDAL_DRIVER_PATH == nullptr)
1581 0 : pszGDAL_DRIVER_PATH = CPLGetConfigOption("OGR_DRIVER_PATH", nullptr);
1582 :
1583 : /* ---------------------------------------------------------------- */
1584 : /* Allow applications to completely disable this search by */
1585 : /* setting the driver path to the special string "disable". */
1586 : /* ---------------------------------------------------------------- */
1587 1293 : if (pszGDAL_DRIVER_PATH != nullptr && EQUAL(pszGDAL_DRIVER_PATH, "disable"))
1588 : {
1589 0 : CPLDebug("GDAL", "GDALDriverManager::GetPluginFullPath() disabled.");
1590 0 : return std::string();
1591 : }
1592 :
1593 : /* ---------------------------------------------------------------- */
1594 : /* Where should we look for stuff? */
1595 : /* ---------------------------------------------------------------- */
1596 : const CPLStringList aosSearchPaths(
1597 2586 : GDALDriverManager::GetSearchPaths(pszGDAL_DRIVER_PATH));
1598 :
1599 : /* ---------------------------------------------------------------- */
1600 : /* Format the ABI version specific subdirectory to look in. */
1601 : /* ---------------------------------------------------------------- */
1602 2586 : CPLString osABIVersion;
1603 :
1604 1293 : osABIVersion.Printf("%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
1605 :
1606 : /* ---------------------------------------------------------------- */
1607 : /* Scan each directory looking for the file of interest. */
1608 : /* ---------------------------------------------------------------- */
1609 1293 : const int nSearchPaths = aosSearchPaths.size();
1610 1293 : for (int iDir = 0; iDir < nSearchPaths; ++iDir)
1611 : {
1612 : std::string osABISpecificDir =
1613 1293 : CPLFormFilename(aosSearchPaths[iDir], osABIVersion, nullptr);
1614 :
1615 : VSIStatBufL sStatBuf;
1616 1293 : if (VSIStatL(osABISpecificDir.c_str(), &sStatBuf) != 0)
1617 1293 : osABISpecificDir = aosSearchPaths[iDir];
1618 :
1619 : const char *pszFullFilename =
1620 1293 : CPLFormFilename(osABISpecificDir.c_str(), pszFilename, nullptr);
1621 1293 : if (VSIStatL(pszFullFilename, &sStatBuf) == 0)
1622 : {
1623 1293 : m_osLastTriedDirectory = std::move(osABISpecificDir);
1624 1293 : return pszFullFilename;
1625 : }
1626 : }
1627 :
1628 0 : return std::string();
1629 : }
1630 :
1631 : /************************************************************************/
1632 : /* DeclareDeferredPluginDriver() */
1633 : /************************************************************************/
1634 :
1635 : /** Declare a driver that will be loaded as a plugin, when actually needed.
1636 : *
1637 : * @param poProxyDriver Plugin driver proxy
1638 : *
1639 : * @since 3.9
1640 : */
1641 58185 : void GDALDriverManager::DeclareDeferredPluginDriver(
1642 : GDALPluginDriverProxy *poProxyDriver)
1643 : {
1644 58185 : CPLMutexHolderD(&hDMMutex);
1645 :
1646 58185 : const auto &osPluginFileName = poProxyDriver->GetPluginFileName();
1647 58185 : const char *pszPluginFileName = osPluginFileName.c_str();
1648 58185 : if ((!STARTS_WITH(pszPluginFileName, "gdal_") &&
1649 20688 : !STARTS_WITH(pszPluginFileName, "ogr_")) ||
1650 58185 : !strchr(pszPluginFileName, '.'))
1651 : {
1652 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid plugin filename: %s",
1653 : pszPluginFileName);
1654 0 : return;
1655 : }
1656 :
1657 58185 : if (GDALGetDriverByName(poProxyDriver->GetDescription()))
1658 : {
1659 0 : CPLError(CE_Failure, CPLE_AppDefined,
1660 : "DeclarePluginDriver(): trying to register %s several times",
1661 0 : poProxyDriver->GetDescription());
1662 0 : delete poProxyDriver;
1663 0 : return;
1664 : }
1665 :
1666 116370 : const std::string osFullPath = GetPluginFullPath(pszPluginFileName);
1667 58185 : poProxyDriver->SetPluginFullPath(osFullPath);
1668 :
1669 58185 : if (osFullPath.empty())
1670 : {
1671 0 : CPLDebug("GDAL",
1672 : "Proxy driver %s *not* registered due to %s not being found",
1673 0 : poProxyDriver->GetDescription(), pszPluginFileName);
1674 0 : RegisterDriver(poProxyDriver, /*bHidden=*/true);
1675 : }
1676 : else
1677 : {
1678 : //CPLDebugOnly("GDAL", "Registering proxy driver %s",
1679 : // poProxyDriver->GetDescription());
1680 58185 : RegisterDriver(poProxyDriver);
1681 58185 : m_oSetPluginFileNames.insert(pszPluginFileName);
1682 : }
1683 : }
1684 :
1685 : /************************************************************************/
1686 : /* GDALDestroyDriverManager() */
1687 : /************************************************************************/
1688 :
1689 : /**
1690 : * \brief Destroy the driver manager.
1691 : *
1692 : * Incidentally unloads all managed drivers.
1693 : *
1694 : * NOTE: This function is not thread safe. It should not be called while
1695 : * other threads are actively using GDAL.
1696 : *
1697 : * \see GDALDestroy()
1698 : * \deprecated Use GDALDestroy() instead
1699 : */
1700 :
1701 1617 : void CPL_STDCALL GDALDestroyDriverManager(void)
1702 :
1703 : {
1704 : // THREADSAFETY: We would like to lock the mutex here, but it
1705 : // needs to be reacquired within the destructor during driver
1706 : // deregistration.
1707 :
1708 : // FIXME: Disable following code as it crashed on OSX CI test.
1709 : // std::lock_guard<std::mutex> oLock(oDeleteMutex);
1710 :
1711 1617 : if (poDM != nullptr)
1712 : {
1713 933 : delete poDM;
1714 933 : poDM = nullptr;
1715 : }
1716 1617 : }
|