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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_port.h"
31 :
32 : #include <cstddef>
33 : #include <cstdio>
34 : #include <cstdlib>
35 : #include <cstring>
36 : #include <algorithm>
37 : #include <memory>
38 : #include <vector>
39 :
40 : #include "commonutils.h"
41 : #include "cpl_conv.h"
42 : #include "cpl_error.h"
43 : #include "cpl_progress.h"
44 : #include "cpl_string.h"
45 : #include "gdal_version.h"
46 : #include "gdal.h"
47 : #include "gdal_priv.h"
48 : #include "gdal_utils.h"
49 : #include "gdal_utils_priv.h"
50 : #include "gdal_version.h"
51 : #include "ogr_api.h"
52 : #include "ogr_core.h"
53 : #include "ogr_p.h"
54 : #include "ogrsf_frmts.h"
55 :
56 : /************************************************************************/
57 : /* Usage() */
58 : /************************************************************************/
59 :
60 0 : static void Usage()
61 : {
62 0 : fprintf(stderr, "%s\n", GDALVectorTranslateGetParserUsage().c_str());
63 0 : }
64 :
65 : /************************************************************************/
66 : /* main() */
67 : /************************************************************************/
68 :
69 132 : MAIN_START(nArgc, papszArgv)
70 : {
71 : // Check strict compilation and runtime library version as we use C++ API.
72 132 : if (!GDAL_CHECK_VERSION(papszArgv[0]))
73 0 : exit(1);
74 :
75 132 : EarlySetConfigOptions(nArgc, papszArgv);
76 :
77 : /* -------------------------------------------------------------------- */
78 : /* Register format(s). */
79 : /* -------------------------------------------------------------------- */
80 132 : OGRRegisterAll();
81 :
82 : /* -------------------------------------------------------------------- */
83 : /* Processing command line arguments. */
84 : /* -------------------------------------------------------------------- */
85 132 : GDALDatasetH hDS = nullptr;
86 132 : GDALDatasetH hODS = nullptr;
87 132 : bool bCloseODS = true;
88 132 : GDALDatasetH hDstDS = nullptr;
89 132 : int nRetCode = 1;
90 132 : GDALVectorTranslateOptions *psOptions = nullptr;
91 132 : GDALVectorTranslateOptionsForBinary sOptionsForBinary;
92 :
93 132 : nArgc = OGRGeneralCmdLineProcessor(nArgc, &papszArgv, 0);
94 :
95 132 : if (nArgc < 1)
96 : {
97 1 : papszArgv = nullptr;
98 1 : nRetCode = -nArgc;
99 1 : goto exit;
100 : }
101 :
102 : psOptions =
103 131 : GDALVectorTranslateOptionsNew(papszArgv + 1, &sOptionsForBinary);
104 :
105 128 : if (psOptions == nullptr)
106 : {
107 0 : Usage();
108 0 : goto exit;
109 : }
110 :
111 128 : if (sOptionsForBinary.osDestDataSource == "/vsistdout/")
112 0 : sOptionsForBinary.bQuiet = true;
113 :
114 : /* -------------------------------------------------------------------- */
115 : /* Open data source. */
116 : /* -------------------------------------------------------------------- */
117 :
118 : // Avoid opening twice the same datasource if it is both the input and
119 : // output Known to cause problems with at least FGdb, SQlite and GPKG
120 : // drivers. See #4270
121 153 : if (sOptionsForBinary.eAccessMode != ACCESS_CREATION &&
122 25 : sOptionsForBinary.osDestDataSource == sOptionsForBinary.osDataSource)
123 : {
124 2 : hODS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
125 : GDAL_OF_UPDATE | GDAL_OF_VECTOR,
126 2 : sOptionsForBinary.aosAllowInputDrivers.List(),
127 2 : sOptionsForBinary.aosOpenOptions.List(), nullptr);
128 :
129 : GDALDriverH hDriver =
130 2 : hODS != nullptr ? GDALGetDatasetDriver(hODS) : nullptr;
131 :
132 : // Restrict to those 3 drivers. For example it is known to break with
133 : // the PG driver due to the way it manages transactions.
134 4 : if (hDriver && !(EQUAL(GDALGetDescription(hDriver), "FileGDB") ||
135 2 : EQUAL(GDALGetDescription(hDriver), "SQLite") ||
136 1 : EQUAL(GDALGetDescription(hDriver), "GPKG")))
137 : {
138 1 : hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(),
139 : GDAL_OF_VECTOR,
140 1 : sOptionsForBinary.aosAllowInputDrivers.List(),
141 1 : sOptionsForBinary.aosOpenOptions.List(), nullptr);
142 : }
143 : else
144 : {
145 1 : hDS = hODS;
146 1 : bCloseODS = false;
147 : }
148 : }
149 : else
150 : {
151 126 : hDS = GDALOpenEx(sOptionsForBinary.osDataSource.c_str(), GDAL_OF_VECTOR,
152 126 : sOptionsForBinary.aosAllowInputDrivers.List(),
153 126 : sOptionsForBinary.aosOpenOptions.List(), nullptr);
154 : }
155 :
156 : /* -------------------------------------------------------------------- */
157 : /* Report failure */
158 : /* -------------------------------------------------------------------- */
159 128 : if (hDS == nullptr)
160 : {
161 1 : GDALDriverManager *poDM = GetGDALDriverManager();
162 :
163 1 : CPLError(CE_Failure, CPLE_AppDefined,
164 : "Unable to open datasource `%s' with the following drivers.",
165 : sOptionsForBinary.osDataSource.c_str());
166 :
167 234 : for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
168 : {
169 233 : GDALDriver *poIter = poDM->GetDriver(iDriver);
170 233 : char **papszDriverMD = poIter->GetMetadata();
171 233 : if (CPLTestBool(CSLFetchNameValueDef(papszDriverMD,
172 : GDAL_DCAP_VECTOR, "FALSE")))
173 : {
174 90 : fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
175 : }
176 : }
177 :
178 1 : GDALVectorTranslateOptionsFree(psOptions);
179 1 : goto exit;
180 : }
181 :
182 127 : if (hODS != nullptr && !sOptionsForBinary.osFormat.empty())
183 : {
184 0 : GDALDriverManager *poDM = GetGDALDriverManager();
185 :
186 : GDALDriver *poDriver =
187 0 : poDM->GetDriverByName(sOptionsForBinary.osFormat.c_str());
188 0 : if (poDriver == nullptr)
189 : {
190 0 : fprintf(stderr, "Unable to find driver `%s'.\n",
191 : sOptionsForBinary.osFormat.c_str());
192 0 : fprintf(stderr, "The following drivers are available:\n");
193 :
194 0 : for (int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++)
195 : {
196 0 : GDALDriver *poIter = poDM->GetDriver(iDriver);
197 0 : char **papszDriverMD = poIter->GetMetadata();
198 0 : if (CPLTestBool(CSLFetchNameValueDef(
199 0 : papszDriverMD, GDAL_DCAP_VECTOR, "FALSE")) &&
200 0 : (CPLTestBool(CSLFetchNameValueDef(
201 0 : papszDriverMD, GDAL_DCAP_CREATE, "FALSE")) ||
202 0 : CPLTestBool(CSLFetchNameValueDef(
203 : papszDriverMD, GDAL_DCAP_CREATECOPY, "FALSE"))))
204 : {
205 0 : fprintf(stderr, " -> `%s'\n", poIter->GetDescription());
206 : }
207 : }
208 0 : GDALVectorTranslateOptionsFree(psOptions);
209 0 : goto exit;
210 : }
211 : }
212 :
213 127 : if (!(sOptionsForBinary.bQuiet))
214 : {
215 127 : GDALVectorTranslateOptionsSetProgress(psOptions, GDALTermProgress,
216 : nullptr);
217 : }
218 :
219 : {
220 : // TODO(schwehr): Remove scope after removing gotos
221 127 : int bUsageError = FALSE;
222 127 : hDstDS = GDALVectorTranslate(sOptionsForBinary.osDestDataSource.c_str(),
223 : hODS, 1, &hDS, psOptions, &bUsageError);
224 127 : if (bUsageError)
225 0 : Usage();
226 : else
227 127 : nRetCode = hDstDS ? 0 : 1;
228 : }
229 :
230 127 : GDALVectorTranslateOptionsFree(psOptions);
231 :
232 127 : if (hDS)
233 127 : GDALClose(hDS);
234 127 : if (bCloseODS)
235 : {
236 126 : if (nRetCode == 0)
237 124 : CPLErrorReset();
238 126 : if (GDALClose(hDstDS) != CE_None)
239 0 : nRetCode = 1;
240 : // TODO: Below code can be removed once all drivers have implemented
241 : // GDALDataset::Close()
242 126 : if (nRetCode == 0 && CPLGetLastErrorType() == CE_Failure)
243 0 : nRetCode = 1;
244 : }
245 :
246 1 : exit:
247 129 : CSLDestroy(papszArgv);
248 129 : GDALDestroy();
249 :
250 129 : return nRetCode;
251 : }
252 :
253 0 : MAIN_END
|