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-05-31 00:00:17 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         551 : static GDALDataset *OGROpenFileGDBDriverOpen(GDALOpenInfo *poOpenInfo)
      38             : 
      39             : {
      40         551 :     const char *pszFilename = poOpenInfo->pszFilename;
      41         551 :     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        1181 :     if (poOpenInfo->fpL != nullptr &&
      48         630 :         !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        1100 :     auto poDS = std::make_unique<OGROpenFileGDBDataSource>();
      60         550 :     bool bRetryFileGDB = false;
      61         550 :     if (poDS->Open(poOpenInfo, bRetryFileGDB))
      62             :     {
      63         491 :         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         491 :         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           3 :     bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override
     180             :     {
     181             :         auto poDS =
     182           3 :             dynamic_cast<OGROpenFileGDBDataSource *>(m_dataset.GetDatasetRef());
     183           3 :         if (!poDS)
     184             :         {
     185           1 :             ReportError(CE_Failure, CPLE_AppDefined,
     186             :                         "%s is not a FileGeoDatabase",
     187           1 :                         m_dataset.GetName().c_str());
     188           1 :             return false;
     189             :         }
     190           2 :         bool bSuccess = true;
     191           2 :         int iLayer = 0;
     192           4 :         for (auto &poLayer : poDS->GetLayers())
     193             :         {
     194           2 :             void *pScaledData = GDALCreateScaledProgress(
     195           2 :                 static_cast<double>(iLayer) / poDS->GetLayerCount(),
     196           2 :                 static_cast<double>(iLayer + 1) / poDS->GetLayerCount(),
     197             :                 pfnProgress, pProgressData);
     198           2 :             const bool bRet = poLayer->Repack(
     199             :                 pScaledData ? GDALScaledProgress : nullptr, pScaledData);
     200           2 :             GDALDestroyScaledProgress(pScaledData);
     201           2 :             if (!bRet)
     202             :             {
     203           0 :                 ReportError(CE_Failure, CPLE_AppDefined,
     204             :                             "Repack of layer %s failed", poLayer->GetName());
     205           0 :                 bSuccess = false;
     206             :             }
     207           2 :             ++iLayer;
     208             :         }
     209           2 :         return bSuccess;
     210             :     }
     211             : 
     212             :   private:
     213             :     GDALArgDatasetValue m_dataset{};
     214             : };
     215             : 
     216             : /************************************************************************/
     217             : /*                 OGROpenFileGDBInstantiateAlgorithm()                 */
     218             : /************************************************************************/
     219             : 
     220             : static GDALAlgorithm *
     221          13 : OGROpenFileGDBInstantiateAlgorithm(const std::vector<std::string> &aosPath)
     222             : {
     223          13 :     if (aosPath.size() == 1 && aosPath[0] == "repack")
     224             :     {
     225          13 :         return std::make_unique<OpenFileGDBRepackAlgorithm>().release();
     226             :     }
     227             :     else
     228             :     {
     229           0 :         return nullptr;
     230             :     }
     231             : }
     232             : 
     233             : /***********************************************************************/
     234             : /*                       RegisterOGROpenFileGDB()                      */
     235             : /***********************************************************************/
     236             : 
     237        1889 : void RegisterOGROpenFileGDB()
     238             : 
     239             : {
     240        1889 :     if (!GDAL_CHECK_VERSION("OGR OpenFileGDB"))
     241           0 :         return;
     242             : 
     243        1889 :     if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
     244         282 :         return;
     245             : 
     246        1607 :     GDALDriver *poDriver = new GDALDriver();
     247        1607 :     OGROpenFileGDBDriverSetCommonMetadata(poDriver);
     248             : 
     249        1607 :     poDriver->pfnOpen = OGROpenFileGDBDriverOpen;
     250        1607 :     poDriver->pfnCreate = OGROpenFileGDBDriverCreate;
     251        1607 :     poDriver->pfnDelete = OGROpenFileGDBDriverDelete;
     252        1607 :     poDriver->pfnInstantiateAlgorithm = OGROpenFileGDBInstantiateAlgorithm;
     253             : 
     254        1607 :     GetGDALDriverManager()->RegisterDriver(poDriver);
     255             : }

Generated by: LCOV version 1.14