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