LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/openfilegdb - ogropenfilegdbdriver.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 87 98 88.8 %
Date: 2025-07-13 21:00:45 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements Open FileGDB OGR driver.
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_port.h"
      14             : #include "ogr_openfilegdb.h"
      15             : #include "ogropenfilegdbdrivercore.h"
      16             : 
      17             : #include <cstddef>
      18             : #include <cstring>
      19             : 
      20             : #include "cpl_conv.h"
      21             : #include "cpl_vsi.h"
      22             : #include "gdal.h"
      23             : #include "gdal_priv.h"
      24             : #include "gdalalgorithm.h"
      25             : #include "ogr_core.h"
      26             : 
      27             : // g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp
      28             : // -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
      29             : // -Iogr/ogrsf_frmts/mem -Iogr/ogrsf_frmts/openfilegdb -L. -lgdal
      30             : 
      31             : extern "C" void RegisterOGROpenFileGDB();
      32             : 
      33             : /************************************************************************/
      34             : /*                                Open()                                */
      35             : /************************************************************************/
      36             : 
      37         553 : static GDALDataset *OGROpenFileGDBDriverOpen(GDALOpenInfo *poOpenInfo)
      38             : 
      39             : {
      40         553 :     const char *pszFilename = poOpenInfo->pszFilename;
      41         553 :     if (OGROpenFileGDBDriverIdentify(poOpenInfo, pszFilename) ==
      42             :         GDAL_IDENTIFY_FALSE)
      43           0 :         return nullptr;
      44             : 
      45             : #ifdef DEBUG
      46             :     /* For AFL, so that .cur_input is detected as the archive filename */
      47        1185 :     if (poOpenInfo->fpL != nullptr &&
      48         632 :         !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
      49          79 :         EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input"))
      50             :     {
      51             :         GDALOpenInfo oOpenInfo(
      52           2 :             (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
      53           3 :             poOpenInfo->nOpenFlags);
      54           1 :         oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
      55           1 :         return OGROpenFileGDBDriverOpen(&oOpenInfo);
      56             :     }
      57             : #endif
      58             : 
      59        1104 :     auto poDS = std::make_unique<OGROpenFileGDBDataSource>();
      60         552 :     bool bRetryFileGDB = false;
      61         552 :     if (poDS->Open(poOpenInfo, bRetryFileGDB))
      62             :     {
      63         493 :         if (poDS->GetSubdatasets().size() == 2)
      64             :         {
      65             :             // If there is a single raster dataset, open it right away.
      66             :             GDALOpenInfo oOpenInfo(
      67           7 :                 poDS->GetSubdatasets().FetchNameValue("SUBDATASET_1_NAME"),
      68          21 :                 poOpenInfo->nOpenFlags);
      69           7 :             poDS = std::make_unique<OGROpenFileGDBDataSource>();
      70           7 :             if (poDS->Open(&oOpenInfo, bRetryFileGDB))
      71             :             {
      72           7 :                 poDS->SetDescription(poOpenInfo->pszFilename);
      73             :             }
      74             :             else
      75             :             {
      76           0 :                 poDS.reset();
      77             :             }
      78             :         }
      79         493 :         return poDS.release();
      80             :     }
      81          59 :     else if (bRetryFileGDB)
      82             :     {
      83           2 :         auto poDriver = GetGDALDriverManager()->GetDriverByName("FileGDB");
      84           2 :         if (poDriver)
      85             :         {
      86           4 :             GDALOpenInfo oOpenInfo(pszFilename, poOpenInfo->nOpenFlags);
      87           4 :             CPLStringList aosOpenOptions;
      88           2 :             aosOpenOptions.SetNameValue("@MAY_USE_OPENFILEGDB", "NO");
      89           2 :             oOpenInfo.papszOpenOptions = aosOpenOptions.List();
      90           2 :             return poDriver->Open(&oOpenInfo, false);
      91             :         }
      92             :     }
      93             : 
      94          57 :     return nullptr;
      95             : }
      96             : 
      97             : /************************************************************************/
      98             : /*                              Create()                                */
      99             : /************************************************************************/
     100             : 
     101         295 : static GDALDataset *OGROpenFileGDBDriverCreate(const char *pszName, int nXSize,
     102             :                                                int nYSize, int nBands,
     103             :                                                GDALDataType eType,
     104             :                                                char ** /* papszOptions*/)
     105             : 
     106             : {
     107         295 :     if (!(nXSize == 0 && nYSize == 0 && nBands == 0 && eType == GDT_Unknown))
     108             :     {
     109          50 :         CPLError(CE_Failure, CPLE_NotSupported,
     110             :                  "OpenFileGDB::Create(): only vector datasets supported");
     111          50 :         return nullptr;
     112             :     }
     113             : 
     114         490 :     auto poDS = std::make_unique<OGROpenFileGDBDataSource>();
     115         245 :     if (!poDS->Create(pszName))
     116           3 :         return nullptr;
     117         242 :     return poDS.release();
     118             : }
     119             : 
     120             : /************************************************************************/
     121             : /*                     OGROpenFileGDBDriverDelete()                     */
     122             : /************************************************************************/
     123             : 
     124          32 : static CPLErr OGROpenFileGDBDriverDelete(const char *pszFilename)
     125             : {
     126          64 :     CPLStringList aosFiles(VSIReadDir(pszFilename));
     127          32 :     if (aosFiles.empty())
     128           0 :         return CE_Failure;
     129             : 
     130         657 :     for (int i = 0; i < aosFiles.size(); ++i)
     131             :     {
     132         625 :         if (strcmp(aosFiles[i], ".") != 0 && strcmp(aosFiles[i], "..") != 0)
     133             :         {
     134             :             const std::string osFilename(
     135         623 :                 CPLFormFilenameSafe(pszFilename, aosFiles[i], nullptr));
     136         623 :             if (VSIUnlink(osFilename.c_str()) != 0)
     137             :             {
     138           0 :                 CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s",
     139             :                          osFilename.c_str());
     140           0 :                 return CE_Failure;
     141             :             }
     142             :         }
     143             :     }
     144          32 :     if (VSIRmdir(pszFilename) != 0)
     145             :     {
     146           0 :         CPLError(CE_Failure, CPLE_FileIO, "Cannot delete %s", pszFilename);
     147           0 :         return CE_Failure;
     148             :     }
     149             : 
     150          32 :     return CE_None;
     151             : }
     152             : 
     153             : /************************************************************************/
     154             : /*                    OpenFileGDBRepackAlgorithm                        */
     155             : /************************************************************************/
     156             : 
     157             : #ifndef _
     158             : #define _(x) x
     159             : #endif
     160             : 
     161             : class OpenFileGDBRepackAlgorithm final : public GDALAlgorithm
     162             : {
     163             :   public:
     164          13 :     OpenFileGDBRepackAlgorithm()
     165          13 :         : GDALAlgorithm("repack", "Repack a FileGeoDatabase dataset",
     166          13 :                         "/drivers/vector/openfilegdb.html")
     167             :     {
     168          13 :         AddProgressArg();
     169             : 
     170          13 :         constexpr int type = GDAL_OF_RASTER | GDAL_OF_VECTOR | GDAL_OF_UPDATE;
     171             :         auto &arg =
     172          26 :             AddArg("dataset", 0, _("FileGeoDatabase dataset"), &m_dataset, type)
     173          13 :                 .SetPositional()
     174          13 :                 .SetRequired();
     175          13 :         SetAutoCompleteFunctionForFilename(arg, type);
     176          13 :     }
     177             : 
     178             :   protected:
     179             :     bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override;
     180             : 
     181             :   private:
     182             :     GDALArgDatasetValue m_dataset{};
     183             : };
     184             : 
     185           3 : bool OpenFileGDBRepackAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
     186             :                                          void *pProgressData)
     187             : {
     188             :     auto poDS =
     189           3 :         dynamic_cast<OGROpenFileGDBDataSource *>(m_dataset.GetDatasetRef());
     190           3 :     if (!poDS)
     191             :     {
     192           1 :         ReportError(CE_Failure, CPLE_AppDefined, "%s is not a FileGeoDatabase",
     193           1 :                     m_dataset.GetName().c_str());
     194           1 :         return false;
     195             :     }
     196           2 :     bool bSuccess = true;
     197           2 :     int iLayer = 0;
     198           4 :     for (auto &poLayer : poDS->GetLayers())
     199             :     {
     200           2 :         void *pScaledData = GDALCreateScaledProgress(
     201           2 :             static_cast<double>(iLayer) / poDS->GetLayerCount(),
     202           2 :             static_cast<double>(iLayer + 1) / poDS->GetLayerCount(),
     203             :             pfnProgress, pProgressData);
     204           2 :         const bool bRet = poLayer->Repack(
     205             :             pScaledData ? GDALScaledProgress : nullptr, pScaledData);
     206           2 :         GDALDestroyScaledProgress(pScaledData);
     207           2 :         if (!bRet)
     208             :         {
     209           0 :             ReportError(CE_Failure, CPLE_AppDefined,
     210             :                         "Repack of layer %s failed", poLayer->GetName());
     211           0 :             bSuccess = false;
     212             :         }
     213           2 :         ++iLayer;
     214             :     }
     215           2 :     return bSuccess;
     216             : }
     217             : 
     218             : /************************************************************************/
     219             : /*                 OGROpenFileGDBInstantiateAlgorithm()                 */
     220             : /************************************************************************/
     221             : 
     222             : static GDALAlgorithm *
     223          13 : OGROpenFileGDBInstantiateAlgorithm(const std::vector<std::string> &aosPath)
     224             : {
     225          13 :     if (aosPath.size() == 1 && aosPath[0] == "repack")
     226             :     {
     227          13 :         return std::make_unique<OpenFileGDBRepackAlgorithm>().release();
     228             :     }
     229             :     else
     230             :     {
     231           0 :         return nullptr;
     232             :     }
     233             : }
     234             : 
     235             : /***********************************************************************/
     236             : /*                       RegisterOGROpenFileGDB()                      */
     237             : /***********************************************************************/
     238             : 
     239        1935 : void RegisterOGROpenFileGDB()
     240             : 
     241             : {
     242        1935 :     if (!GDAL_CHECK_VERSION("OGR OpenFileGDB"))
     243           0 :         return;
     244             : 
     245        1935 :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     246         282 :         return;
     247             : 
     248        1653 :     GDALDriver *poDriver = new GDALDriver();
     249        1653 :     OGROpenFileGDBDriverSetCommonMetadata(poDriver);
     250             : 
     251        1653 :     poDriver->pfnOpen = OGROpenFileGDBDriverOpen;
     252        1653 :     poDriver->pfnCreate = OGROpenFileGDBDriverCreate;
     253        1653 :     poDriver->pfnDelete = OGROpenFileGDBDriverDelete;
     254        1653 :     poDriver->pfnInstantiateAlgorithm = OGROpenFileGDBInstantiateAlgorithm;
     255             : 
     256        1653 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     257             : }

Generated by: LCOV version 1.14