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