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