Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Simple client for translating between formats.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1999, Frank Warmerdam
9 : * Copyright (c) 2008-2015, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_port.h"
15 :
16 : #include <cstddef>
17 : #include <cstdio>
18 : #include <cstdlib>
19 : #include <cstring>
20 : #include <algorithm>
21 : #include <memory>
22 : #include <vector>
23 :
24 : #include "commonutils.h"
25 : #include "cpl_conv.h"
26 : #include "cpl_error.h"
27 : #include "cpl_progress.h"
28 : #include "cpl_string.h"
29 : #include "gdal_version.h"
30 : #include "gdal.h"
31 : #include "gdal_priv.h"
32 : #include "gdal_utils.h"
33 : #include "gdal_utils_priv.h"
34 : #include "ogr_api.h"
35 : #include "ogr_core.h"
36 : #include "ogr_p.h"
37 : #include "ogrsf_frmts.h"
38 :
39 : /************************************************************************/
40 : /* Usage() */
41 : /************************************************************************/
42 :
43 1 : static void Usage()
44 : {
45 1 : fprintf(stderr, "%s\n", GDALVectorTranslateGetParserUsage().c_str());
46 1 : }
47 :
48 : /************************************************************************/
49 : /* main() */
50 : /************************************************************************/
51 :
52 135 : MAIN_START(nArgc, papszArgv)
53 : {
54 : // Check strict compilation and runtime library version as we use C++ API.
55 135 : if (!GDAL_CHECK_VERSION(papszArgv[0]))
56 0 : exit(1);
57 :
58 135 : EarlySetConfigOptions(nArgc, papszArgv);
59 :
60 : /* -------------------------------------------------------------------- */
61 : /* Register format(s). */
62 : /* -------------------------------------------------------------------- */
63 135 : OGRRegisterAll();
64 :
65 : /* -------------------------------------------------------------------- */
66 : /* Processing command line arguments. */
67 : /* -------------------------------------------------------------------- */
68 135 : GDALDatasetH hDS = nullptr;
69 135 : GDALDatasetH hODS = nullptr;
70 135 : bool bCloseODS = true;
71 135 : GDALDatasetH hDstDS = nullptr;
72 135 : int nRetCode = 1;
73 135 : GDALVectorTranslateOptions *psOptions = nullptr;
74 135 : GDALVectorTranslateOptionsForBinary sOptionsForBinary;
75 :
76 135 : nArgc = OGRGeneralCmdLineProcessor(nArgc, &papszArgv, 0);
77 :
78 135 : if (nArgc < 1)
79 : {
80 1 : papszArgv = nullptr;
81 1 : nRetCode = -nArgc;
82 1 : goto exit;
83 : }
84 :
85 : psOptions =
86 134 : GDALVectorTranslateOptionsNew(papszArgv + 1, &sOptionsForBinary);
87 :
88 131 : if (psOptions == nullptr)
89 : {
90 1 : if (sOptionsForBinary.bShowUsageIfError)
91 1 : Usage();
92 1 : goto exit;
93 : }
94 :
95 130 : if (sOptionsForBinary.osDestDataSource == "/vsistdout/")
96 0 : sOptionsForBinary.bQuiet = true;
97 :
98 : /* -------------------------------------------------------------------- */
99 : /* Open data source. */
100 : /* -------------------------------------------------------------------- */
101 :
102 : // Avoid opening twice the same datasource if it is both the input and
103 : // output Known to cause problems with at least FGdb, SQlite and GPKG
104 : // drivers. See #4270
105 155 : if (sOptionsForBinary.eAccessMode != ACCESS_CREATION &&
106 25 : sOptionsForBinary.osDestDataSource == sOptionsForBinary.osDataSource)
107 : {
108 2 : hODS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
109 : GDAL_OF_UPDATE | GDAL_OF_VECTOR,
110 2 : sOptionsForBinary.aosAllowInputDrivers.List(),
111 2 : sOptionsForBinary.aosOpenOptions.List(), nullptr);
112 :
113 : GDALDriverH hDriver =
114 2 : hODS != nullptr ? GDALGetDatasetDriver(hODS) : nullptr;
115 :
116 : // Restrict to those 3 drivers. For example it is known to break with
117 : // the PG driver due to the way it manages transactions.
118 4 : if (hDriver && !(EQUAL(GDALGetDescription(hDriver), "FileGDB") ||
119 2 : EQUAL(GDALGetDescription(hDriver), "SQLite") ||
120 1 : EQUAL(GDALGetDescription(hDriver), "GPKG")))
121 : {
122 1 : hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
123 : GDAL_OF_VECTOR,
124 1 : sOptionsForBinary.aosAllowInputDrivers.List(),
125 1 : sOptionsForBinary.aosOpenOptions.List(), nullptr);
126 : }
127 : else
128 : {
129 1 : hDS = hODS;
130 1 : bCloseODS = false;
131 : }
132 : }
133 : else
134 : {
135 128 : hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(), GDAL_OF_VECTOR,
136 128 : sOptionsForBinary.aosAllowInputDrivers.List(),
137 128 : sOptionsForBinary.aosOpenOptions.List(), nullptr);
138 : }
139 :
140 : /* -------------------------------------------------------------------- */
141 : /* Report failure */
142 : /* -------------------------------------------------------------------- */
143 130 : if (hDS == nullptr)
144 : {
145 1 : GDALDriverManager *poDM = GetGDALDriverManager();
146 :
147 1 : CPLError(CE_Failure, CPLE_AppDefined,
148 : "Unable to open datasource `%s' with the following drivers.",
149 : sOptionsForBinary.osDataSource.c_str());
150 :
151 239 : for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
152 : {
153 238 : GDALDriver *poIter = poDM->GetDriver(iDriver);
154 238 : char **papszDriverMD = poIter->GetMetadata();
155 238 : if (CPLTestBool(CSLFetchNameValueDef(papszDriverMD,
156 : GDAL_DCAP_VECTOR, "FALSE")))
157 : {
158 93 : fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
159 : }
160 : }
161 :
162 1 : GDALVectorTranslateOptionsFree(psOptions);
163 1 : goto exit;
164 : }
165 :
166 129 : if (hODS != nullptr && !sOptionsForBinary.osFormat.empty())
167 : {
168 0 : GDALDriverManager *poDM = GetGDALDriverManager();
169 :
170 : GDALDriver *poDriver =
171 0 : poDM->GetDriverByName(sOptionsForBinary.osFormat.c_str());
172 0 : if (poDriver == nullptr)
173 : {
174 0 : fprintf(stderr, "Unable to find driver `%s'.\n",
175 : sOptionsForBinary.osFormat.c_str());
176 0 : fprintf(stderr, "The following drivers are available:\n");
177 :
178 0 : for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
179 : {
180 0 : GDALDriver *poIter = poDM->GetDriver(iDriver);
181 0 : char **papszDriverMD = poIter->GetMetadata();
182 0 : if (CPLTestBool(CSLFetchNameValueDef(
183 0 : papszDriverMD, GDAL_DCAP_VECTOR, "FALSE")) &&
184 0 : (CPLTestBool(CSLFetchNameValueDef(
185 0 : papszDriverMD, GDAL_DCAP_CREATE, "FALSE")) ||
186 0 : CPLTestBool(CSLFetchNameValueDef(
187 : papszDriverMD, GDAL_DCAP_CREATECOPY, "FALSE"))))
188 : {
189 0 : fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
190 : }
191 : }
192 0 : GDALVectorTranslateOptionsFree(psOptions);
193 0 : goto exit;
194 : }
195 : }
196 :
197 129 : if (!(sOptionsForBinary.bQuiet))
198 : {
199 129 : GDALVectorTranslateOptionsSetProgress(psOptions, GDALTermProgress,
200 : nullptr);
201 : }
202 :
203 : {
204 : // TODO(schwehr): Remove scope after removing gotos
205 129 : int bUsageError = FALSE;
206 129 : hDstDS = GDALVectorTranslate(sOptionsForBinary.osDestDataSource.c_str(),
207 : hODS, 1, &hDS, psOptions, &bUsageError);
208 129 : if (bUsageError)
209 0 : Usage();
210 : else
211 129 : nRetCode = hDstDS ? 0 : 1;
212 : }
213 :
214 129 : GDALVectorTranslateOptionsFree(psOptions);
215 :
216 129 : if (hDS)
217 129 : GDALClose(hDS);
218 129 : if (bCloseODS)
219 : {
220 128 : if (nRetCode == 0)
221 125 : CPLErrorReset();
222 128 : if (GDALClose(hDstDS) != CE_None)
223 0 : nRetCode = 1;
224 : // TODO: Below code can be removed once all drivers have implemented
225 : // GDALDataset::Close()
226 128 : if (nRetCode == 0 && CPLGetLastErrorType() == CE_Failure)
227 0 : nRetCode = 1;
228 : }
229 :
230 1 : exit:
231 132 : CSLDestroy(papszArgv);
232 132 : GDALDestroy();
233 :
234 132 : return nRetCode;
235 : }
236 :
237 0 : MAIN_END
|