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