gdal/apps/ogr2ogr_bin.cpp

238 lines
8.2 KiB
C++

/******************************************************************************
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: Simple client for translating between formats.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
* Copyright (c) 2008-2015, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT
****************************************************************************/
#include "cpl_port.h"
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <memory>
#include <vector>
#include "commonutils.h"
#include "cpl_conv.h"
#include "cpl_error.h"
#include "cpl_progress.h"
#include "cpl_string.h"
#include "gdal_version.h"
#include "gdal.h"
#include "gdal_priv.h"
#include "gdal_utils.h"
#include "gdal_utils_priv.h"
#include "ogr_api.h"
#include "ogr_core.h"
#include "ogr_p.h"
#include "ogrsf_frmts.h"
/************************************************************************/
/* Usage() */
/************************************************************************/
static void Usage()
{
fprintf(stderr, "%s\n", GDALVectorTranslateGetParserUsage().c_str());
}
/************************************************************************/
/* main() */
/************************************************************************/
MAIN_START(nArgc, papszArgv)
{
// Check strict compilation and runtime library version as we use C++ API.
if (!GDAL_CHECK_VERSION(papszArgv[0]))
exit(1);
EarlySetConfigOptions(nArgc, papszArgv);
/* -------------------------------------------------------------------- */
/* Register format(s). */
/* -------------------------------------------------------------------- */
OGRRegisterAll();
/* -------------------------------------------------------------------- */
/* Processing command line arguments. */
/* -------------------------------------------------------------------- */
GDALDatasetH hDS = nullptr;
GDALDatasetH hODS = nullptr;
bool bCloseODS = true;
GDALDatasetH hDstDS = nullptr;
int nRetCode = 1;
GDALVectorTranslateOptions *psOptions = nullptr;
GDALVectorTranslateOptionsForBinary sOptionsForBinary;
nArgc = OGRGeneralCmdLineProcessor(nArgc, &papszArgv, 0);
if (nArgc < 1)
{
papszArgv = nullptr;
nRetCode = -nArgc;
goto exit;
}
psOptions =
GDALVectorTranslateOptionsNew(papszArgv + 1, &sOptionsForBinary);
if (psOptions == nullptr)
{
if (sOptionsForBinary.bShowUsageIfError)
Usage();
goto exit;
}
if (sOptionsForBinary.osDestDataSource == "/vsistdout/")
sOptionsForBinary.bQuiet = true;
/* -------------------------------------------------------------------- */
/* Open data source. */
/* -------------------------------------------------------------------- */
// Avoid opening twice the same datasource if it is both the input and
// output Known to cause problems with at least FGdb, SQlite and GPKG
// drivers. See #4270
if (sOptionsForBinary.eAccessMode != ACCESS_CREATION &&
sOptionsForBinary.osDestDataSource == sOptionsForBinary.osDataSource)
{
hODS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
GDAL_OF_UPDATE | GDAL_OF_VECTOR,
sOptionsForBinary.aosAllowInputDrivers.List(),
sOptionsForBinary.aosOpenOptions.List(), nullptr);
GDALDriverH hDriver =
hODS != nullptr ? GDALGetDatasetDriver(hODS) : nullptr;
// Restrict to those 3 drivers. For example it is known to break with
// the PG driver due to the way it manages transactions.
if (hDriver && !(EQUAL(GDALGetDescription(hDriver), "FileGDB") ||
EQUAL(GDALGetDescription(hDriver), "SQLite") ||
EQUAL(GDALGetDescription(hDriver), "GPKG")))
{
hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
GDAL_OF_VECTOR,
sOptionsForBinary.aosAllowInputDrivers.List(),
sOptionsForBinary.aosOpenOptions.List(), nullptr);
}
else
{
hDS = hODS;
bCloseODS = false;
}
}
else
{
hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(), GDAL_OF_VECTOR,
sOptionsForBinary.aosAllowInputDrivers.List(),
sOptionsForBinary.aosOpenOptions.List(), nullptr);
}
/* -------------------------------------------------------------------- */
/* Report failure */
/* -------------------------------------------------------------------- */
if (hDS == nullptr)
{
GDALDriverManager *poDM = GetGDALDriverManager();
CPLError(CE_Failure, CPLE_AppDefined,
"Unable to open datasource `%s' with the following drivers.",
sOptionsForBinary.osDataSource.c_str());
for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
{
GDALDriver *poIter = poDM->GetDriver(iDriver);
char **papszDriverMD = poIter->GetMetadata();
if (CPLTestBool(CSLFetchNameValueDef(papszDriverMD,
GDAL_DCAP_VECTOR, "FALSE")))
{
fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
}
}
GDALVectorTranslateOptionsFree(psOptions);
goto exit;
}
if (hODS != nullptr && !sOptionsForBinary.osFormat.empty())
{
GDALDriverManager *poDM = GetGDALDriverManager();
GDALDriver *poDriver =
poDM->GetDriverByName(sOptionsForBinary.osFormat.c_str());
if (poDriver == nullptr)
{
fprintf(stderr, "Unable to find driver `%s'.\n",
sOptionsForBinary.osFormat.c_str());
fprintf(stderr, "The following drivers are available:\n");
for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
{
GDALDriver *poIter = poDM->GetDriver(iDriver);
char **papszDriverMD = poIter->GetMetadata();
if (CPLTestBool(CSLFetchNameValueDef(
papszDriverMD, GDAL_DCAP_VECTOR, "FALSE")) &&
(CPLTestBool(CSLFetchNameValueDef(
papszDriverMD, GDAL_DCAP_CREATE, "FALSE")) ||
CPLTestBool(CSLFetchNameValueDef(
papszDriverMD, GDAL_DCAP_CREATECOPY, "FALSE"))))
{
fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
}
}
GDALVectorTranslateOptionsFree(psOptions);
goto exit;
}
}
if (!(sOptionsForBinary.bQuiet))
{
GDALVectorTranslateOptionsSetProgress(psOptions, GDALTermProgress,
nullptr);
}
{
// TODO(schwehr): Remove scope after removing gotos
int bUsageError = FALSE;
hDstDS = GDALVectorTranslate(sOptionsForBinary.osDestDataSource.c_str(),
hODS, 1, &hDS, psOptions, &bUsageError);
if (bUsageError)
Usage();
else
nRetCode = hDstDS ? 0 : 1;
}
GDALVectorTranslateOptionsFree(psOptions);
if (hDS)
GDALClose(hDS);
if (bCloseODS)
{
if (nRetCode == 0)
CPLErrorReset();
if (GDALClose(hDstDS) != CE_None)
nRetCode = 1;
// TODO: Below code can be removed once all drivers have implemented
// GDALDataset::Close()
if (nRetCode == 0 && CPLGetLastErrorType() == CE_Failure)
nRetCode = 1;
}
exit:
CSLDestroy(papszArgv);
GDALDestroy();
return nRetCode;
}
MAIN_END