Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Utilities
4 : * Purpose: Command line application to list info about a file.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : * ****************************************************************************
8 : * Copyright (c) 1998, Frank Warmerdam
9 : * Copyright (c) 2007-2015, Even Rouault <even.rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "gdal_version.h"
15 : #include "gdal.h"
16 : #include "cpl_string.h"
17 : #include "cpl_multiproc.h"
18 : #include "cpl_vsi_virtual.h"
19 : #include "commonutils.h"
20 : #include "gdal_utils_priv.h"
21 :
22 : /************************************************************************/
23 : /* GDALExit() */
24 : /* This function exits and cleans up GDAL and OGR resources */
25 : /* Perhaps it should be added to C api and used in all apps? */
26 : /************************************************************************/
27 :
28 18 : static int GDALExit(int nCode)
29 : {
30 18 : const char *pszDebug = CPLGetConfigOption("CPL_DEBUG", nullptr);
31 18 : if (pszDebug && (EQUAL(pszDebug, "ON") || EQUAL(pszDebug, "")))
32 : {
33 0 : GDALDumpOpenDatasets(stderr);
34 0 : CPLDumpSharedList(nullptr);
35 : }
36 :
37 18 : GDALDestroyDriverManager();
38 :
39 18 : OGRCleanupAll();
40 :
41 18 : exit(nCode);
42 : }
43 :
44 : /************************************************************************/
45 : /* Usage() */
46 : /************************************************************************/
47 :
48 0 : static void Usage()
49 :
50 : {
51 0 : fprintf(stderr, "%s\n", GDALInfoAppGetParserUsage().c_str());
52 0 : GDALExit(1);
53 0 : }
54 :
55 : /************************************************************************/
56 : /* main() */
57 : /************************************************************************/
58 :
59 77 : MAIN_START(argc, argv)
60 :
61 : {
62 77 : EarlySetConfigOptions(argc, argv);
63 :
64 : /* -------------------------------------------------------------------- */
65 : /* Register standard GDAL drivers, and process generic GDAL */
66 : /* command options. */
67 : /* -------------------------------------------------------------------- */
68 :
69 77 : GDALAllRegister();
70 77 : argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
71 77 : if (argc < 1)
72 18 : GDALExit(-argc);
73 :
74 : /* -------------------------------------------------------------------- */
75 : /* Parse command line */
76 : /* -------------------------------------------------------------------- */
77 :
78 59 : GDALInfoOptionsForBinary sOptionsForBinary;
79 :
80 59 : if (CSLFindString(argv, "-stdout") < 0)
81 : {
82 59 : argv = CSLAddString(argv, "-stdout");
83 : }
84 :
85 : std::unique_ptr<GDALInfoOptions, decltype(&GDALInfoOptionsFree)> psOptions{
86 59 : GDALInfoOptionsNew(argv + 1, &sOptionsForBinary), GDALInfoOptionsFree};
87 59 : CSLDestroy(argv);
88 :
89 59 : if (!psOptions)
90 : {
91 0 : Usage();
92 : }
93 :
94 : /* -------------------------------------------------------------------- */
95 : /* Open dataset. */
96 : /* -------------------------------------------------------------------- */
97 : #ifdef __AFL_HAVE_MANUAL_CONTROL
98 : int iIter = 0;
99 : while (__AFL_LOOP(1000))
100 : {
101 : iIter++;
102 : #endif
103 :
104 59 : GDALDatasetH hDataset = GDALOpenEx(
105 : sOptionsForBinary.osFilename.c_str(),
106 : GDAL_OF_READONLY | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
107 : sOptionsForBinary.aosAllowedInputDrivers,
108 59 : sOptionsForBinary.aosOpenOptions, nullptr);
109 :
110 59 : if (hDataset == nullptr)
111 : {
112 : #ifdef __AFL_HAVE_MANUAL_CONTROL
113 : continue;
114 : #else
115 : VSIStatBuf sStat;
116 5 : CPLString message;
117 : message.Printf("gdalinfo failed - unable to open '%s'.",
118 5 : sOptionsForBinary.osFilename.c_str());
119 5 : if (VSIStat(sOptionsForBinary.osFilename.c_str(), &sStat) == 0)
120 : {
121 : GDALDriverH drv =
122 4 : GDALIdentifyDriverEx(sOptionsForBinary.osFilename.c_str(),
123 : GDAL_OF_VECTOR, nullptr, nullptr);
124 4 : if (drv)
125 : {
126 1 : message += " Did you intend to call ogrinfo?";
127 : }
128 : }
129 5 : fprintf(stderr, "%s\n", message.c_str());
130 :
131 : /* --------------------------------------------------------------------
132 : */
133 : /* If argument is a VSIFILE, then print its contents */
134 : /* --------------------------------------------------------------------
135 : */
136 5 : if (VSIFileManager::GetHandler(sOptionsForBinary.osFilename.c_str())
137 5 : ->IsArchive(sOptionsForBinary.osFilename.c_str()))
138 : {
139 0 : const char *const apszOptions[] = {"NAME_AND_TYPE_ONLY=YES",
140 : nullptr};
141 0 : VSIDIR *psDir = VSIOpenDir(sOptionsForBinary.osFilename.c_str(), -1,
142 : apszOptions);
143 0 : if (psDir)
144 : {
145 0 : fprintf(stdout,
146 : "Unable to open source `%s' directly.\n"
147 : "The archive contains several files:\n",
148 : sOptionsForBinary.osFilename.c_str());
149 0 : int nCount = 0;
150 0 : while (auto psEntry = VSIGetNextDirEntry(psDir))
151 : {
152 0 : if (VSI_ISDIR(psEntry->nMode) && psEntry->pszName[0] &&
153 0 : psEntry->pszName[strlen(psEntry->pszName) - 1] != '/')
154 : {
155 0 : fprintf(stdout, " %s/%s/\n",
156 : sOptionsForBinary.osFilename.c_str(),
157 0 : psEntry->pszName);
158 : }
159 : else
160 : {
161 0 : fprintf(stdout, " %s/%s\n",
162 : sOptionsForBinary.osFilename.c_str(),
163 0 : psEntry->pszName);
164 : }
165 0 : nCount++;
166 0 : if (nCount == 100)
167 : {
168 0 : fprintf(stdout, "[...trimmed...]\n");
169 0 : break;
170 : }
171 0 : }
172 0 : VSICloseDir(psDir);
173 : }
174 : }
175 :
176 5 : GDALDumpOpenDatasets(stderr);
177 :
178 5 : GDALDestroyDriverManager();
179 :
180 5 : CPLDumpSharedList(nullptr);
181 :
182 5 : exit(1);
183 : #endif
184 : }
185 :
186 : /* --------------------------------------------------------------------
187 : */
188 : /* Read specified subdataset if requested. */
189 : /* --------------------------------------------------------------------
190 : */
191 54 : if (sOptionsForBinary.nSubdataset > 0)
192 : {
193 0 : char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS");
194 0 : const int nSubdatasets = CSLCount(papszSubdatasets) / 2;
195 :
196 0 : if (nSubdatasets > 0 &&
197 0 : sOptionsForBinary.nSubdataset <= nSubdatasets)
198 : {
199 : char szKeyName[1024];
200 : char *pszSubdatasetName;
201 :
202 0 : snprintf(szKeyName, sizeof(szKeyName), "SUBDATASET_%d_NAME",
203 : sOptionsForBinary.nSubdataset);
204 0 : szKeyName[sizeof(szKeyName) - 1] = '\0';
205 : pszSubdatasetName =
206 0 : CPLStrdup(CSLFetchNameValue(papszSubdatasets, szKeyName));
207 0 : GDALClose(hDataset);
208 0 : hDataset = GDALOpen(pszSubdatasetName, GA_ReadOnly);
209 0 : CPLFree(pszSubdatasetName);
210 : }
211 : else
212 : {
213 0 : fprintf(stderr,
214 : "gdalinfo warning: subdataset %d of %d requested. "
215 : "Reading the main dataset.\n",
216 : sOptionsForBinary.nSubdataset, nSubdatasets);
217 : }
218 : }
219 :
220 54 : char *pszGDALInfoOutput = GDALInfo(hDataset, psOptions.get());
221 :
222 54 : if (pszGDALInfoOutput)
223 54 : printf("%s", pszGDALInfoOutput);
224 :
225 54 : CPLFree(pszGDALInfoOutput);
226 :
227 54 : GDALClose(hDataset);
228 : #ifdef __AFL_HAVE_MANUAL_CONTROL
229 : }
230 : #endif
231 :
232 54 : GDALDumpOpenDatasets(stderr);
233 :
234 54 : GDALDestroyDriverManager();
235 :
236 54 : CPLDumpSharedList(nullptr);
237 :
238 54 : GDALDestroy();
239 :
240 54 : exit(0);
241 : }
242 :
243 0 : MAIN_END
|