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  * 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 "gdal_version.h"
31 #include "gdal.h"
32 #include "cpl_string.h"
33 #include "cpl_multiproc.h"
34 #include "commonutils.h"
35 #include "gdal_utils_priv.h"
36 
37 CPL_CVSID("$Id: gdalinfo_bin.cpp d0052b5856982d5b0f42239ad15094f81c2b92d6 2020-12-18 19:11:05 +0100 Even Rouault $")
38 
39 /************************************************************************/
40 /*                               Usage()                                */
41 /************************************************************************/
42 
Usage(const char * pszErrorMsg=nullptr)43 static void Usage(const char* pszErrorMsg = nullptr)
44 
45 {
46     printf( "Usage: gdalinfo [--help-general] [-json] [-mm] [-stats | -approx_stats] [-hist] [-nogcp] [-nomd]\n"
47             "                [-norat] [-noct] [-nofl] [-checksum] [-proj4]\n"
48             "                [-listmdd] [-mdd domain|`all`] [-wkt_format WKT1|WKT2|...]*\n"
49             "                [-sd subdataset] [-oo NAME=VALUE]* [-if format]* datasetname\n" );
50 
51     if( pszErrorMsg != nullptr )
52         fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
53 
54     exit( 1 );
55 }
56 
57 /************************************************************************/
58 /*                         GDALInfoOptionsForBinary()                   */
59 /************************************************************************/
60 
GDALInfoOptionsForBinaryNew(void)61 static GDALInfoOptionsForBinary *GDALInfoOptionsForBinaryNew(void)
62 {
63     return static_cast<GDALInfoOptionsForBinary *>(
64         CPLCalloc(1, sizeof(GDALInfoOptionsForBinary)));
65 }
66 
67 /************************************************************************/
68 /*                       GDALInfoOptionsForBinaryFree()                 */
69 /************************************************************************/
70 
GDALInfoOptionsForBinaryFree(GDALInfoOptionsForBinary * psOptionsForBinary)71 static void GDALInfoOptionsForBinaryFree( GDALInfoOptionsForBinary* psOptionsForBinary )
72 {
73     if( psOptionsForBinary )
74     {
75         CPLFree(psOptionsForBinary->pszFilename);
76         CSLDestroy(psOptionsForBinary->papszOpenOptions);
77         CSLDestroy(psOptionsForBinary->papszAllowInputDrivers);
78         CPLFree(psOptionsForBinary);
79     }
80 }
81 
82 /************************************************************************/
83 /*                                main()                                */
84 /************************************************************************/
85 
MAIN_START(argc,argv)86 MAIN_START(argc, argv)
87 
88 {
89     EarlySetConfigOptions(argc, argv);
90 
91     GDALAllRegister();
92 
93     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
94     if( argc < 1 )
95         exit( -argc );
96 
97     for( int i = 0; argv != nullptr && argv[i] != nullptr; i++ )
98     {
99         if( EQUAL(argv[i], "--utility_version") )
100         {
101             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
102                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
103             CSLDestroy( argv );
104             return 0;
105         }
106         else if( EQUAL(argv[i],"--help") )
107         {
108             Usage();
109         }
110     }
111     argv = CSLAddString(argv, "-stdout");
112 
113     GDALInfoOptionsForBinary* psOptionsForBinary = GDALInfoOptionsForBinaryNew();
114 
115     GDALInfoOptions *psOptions
116         = GDALInfoOptionsNew(argv + 1, psOptionsForBinary);
117     if( psOptions == nullptr )
118         Usage();
119 
120     if( psOptionsForBinary->pszFilename == nullptr )
121         Usage("No datasource specified.");
122 
123 /* -------------------------------------------------------------------- */
124 /*      Open dataset.                                                   */
125 /* -------------------------------------------------------------------- */
126 #ifdef __AFL_HAVE_MANUAL_CONTROL
127     int iIter = 0;
128     while (__AFL_LOOP(1000)) {
129         iIter ++;
130 #endif
131 
132     GDALDatasetH hDataset
133         = GDALOpenEx( psOptionsForBinary->pszFilename,
134                       GDAL_OF_READONLY | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
135                       psOptionsForBinary->papszAllowInputDrivers,
136                       psOptionsForBinary->papszOpenOptions, nullptr );
137 
138     if( hDataset == nullptr )
139     {
140 #ifdef __AFL_HAVE_MANUAL_CONTROL
141         continue;
142 #else
143         fprintf( stderr,
144                  "gdalinfo failed - unable to open '%s'.\n",
145                  psOptionsForBinary->pszFilename );
146 
147 /* -------------------------------------------------------------------- */
148 /*      If argument is a VSIFILE, then print its contents               */
149 /* -------------------------------------------------------------------- */
150         if ( STARTS_WITH(psOptionsForBinary->pszFilename, "/vsizip/") ||
151              STARTS_WITH(psOptionsForBinary->pszFilename, "/vsitar/") )
152         {
153             char** papszFileList = VSIReadDirRecursive( psOptionsForBinary->pszFilename );
154             if ( papszFileList )
155             {
156                 int nCount = CSLCount( papszFileList );
157                 fprintf( stdout,
158                          "Unable to open source `%s' directly.\n"
159                          "The archive contains %d files:\n",
160                          psOptionsForBinary->pszFilename, nCount );
161                 for ( int i = 0; i < nCount; i++ )
162                 {
163                     fprintf( stdout, "       %s/%s\n", psOptionsForBinary->pszFilename, papszFileList[i] );
164                 }
165                 CSLDestroy( papszFileList );
166             }
167         }
168 
169         CSLDestroy( argv );
170 
171         GDALInfoOptionsForBinaryFree(psOptionsForBinary);
172 
173         GDALInfoOptionsFree( psOptions );
174 
175         GDALDumpOpenDatasets( stderr );
176 
177         GDALDestroyDriverManager();
178 
179         CPLDumpSharedList( nullptr );
180 
181         exit( 1 );
182 #endif
183     }
184 
185 /* -------------------------------------------------------------------- */
186 /*      Read specified subdataset if requested.                         */
187 /* -------------------------------------------------------------------- */
188     if ( psOptionsForBinary->nSubdataset > 0 )
189     {
190         char **papszSubdatasets = GDALGetMetadata( hDataset, "SUBDATASETS" );
191         int nSubdatasets = CSLCount( papszSubdatasets );
192 
193         if ( nSubdatasets > 0 && psOptionsForBinary->nSubdataset <= nSubdatasets )
194         {
195             char szKeyName[1024];
196             char *pszSubdatasetName;
197 
198             snprintf( szKeyName, sizeof(szKeyName),
199                       "SUBDATASET_%d_NAME", psOptionsForBinary->nSubdataset );
200             szKeyName[sizeof(szKeyName) - 1] = '\0';
201             pszSubdatasetName =
202                 CPLStrdup( CSLFetchNameValue( papszSubdatasets, szKeyName ) );
203             GDALClose( hDataset );
204             hDataset = GDALOpen( pszSubdatasetName, GA_ReadOnly );
205             CPLFree( pszSubdatasetName );
206         }
207         else
208         {
209             fprintf( stderr,
210                      "gdalinfo warning: subdataset %d of %d requested. "
211                      "Reading the main dataset.\n",
212                      psOptionsForBinary->nSubdataset, nSubdatasets );
213         }
214     }
215 
216     char* pszGDALInfoOutput = GDALInfo( hDataset, psOptions );
217 
218     if( pszGDALInfoOutput )
219         printf( "%s", pszGDALInfoOutput );
220 
221     CPLFree( pszGDALInfoOutput );
222 
223     GDALClose( hDataset );
224 #ifdef __AFL_HAVE_MANUAL_CONTROL
225     }
226 #endif
227 
228     GDALInfoOptionsForBinaryFree(psOptionsForBinary);
229 
230     GDALInfoOptionsFree( psOptions );
231 
232     CSLDestroy( argv );
233 
234     GDALDumpOpenDatasets( stderr );
235 
236     GDALDestroyDriverManager();
237 
238     CPLDumpSharedList( nullptr );
239     GDALDestroy();
240 
241     exit( 0 );
242 }
243 MAIN_END
244