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