1 : /******************************************************************************
2 : * $Id: gdalopeninfo.cpp 23717 2012-01-07 14:58:34Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALOpenInfo class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : **********************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
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_priv.h"
31 : #include "cpl_conv.h"
32 :
33 : #ifdef HAVE_UNISTD_H
34 : #include <unistd.h>
35 : #endif
36 :
37 : CPL_CVSID("$Id: gdalopeninfo.cpp 23717 2012-01-07 14:58:34Z rouault $");
38 :
39 : /************************************************************************/
40 : /* ==================================================================== */
41 : /* GDALOpenInfo */
42 : /* ==================================================================== */
43 : /************************************************************************/
44 :
45 : /************************************************************************/
46 : /* GDALOpenInfo() */
47 : /************************************************************************/
48 :
49 20108 : GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, GDALAccess eAccessIn,
50 : char **papszSiblingsIn )
51 :
52 : {
53 : /* -------------------------------------------------------------------- */
54 : /* Ensure that C: is treated as C:\ so we can stat it on */
55 : /* Windows. Similar to what is done in CPLStat(). */
56 : /* -------------------------------------------------------------------- */
57 : #ifdef WIN32
58 : if( strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':' )
59 : {
60 : char szAltPath[10];
61 :
62 : strcpy( szAltPath, pszFilenameIn );
63 : strcat( szAltPath, "\\" );
64 : pszFilename = CPLStrdup( szAltPath );
65 : }
66 : else
67 : #endif
68 20108 : pszFilename = CPLStrdup( pszFilenameIn );
69 :
70 : /* -------------------------------------------------------------------- */
71 : /* Initialize. */
72 : /* -------------------------------------------------------------------- */
73 :
74 20108 : nHeaderBytes = 0;
75 20108 : pabyHeader = NULL;
76 20108 : bIsDirectory = FALSE;
77 20108 : bStatOK = FALSE;
78 20108 : eAccess = eAccessIn;
79 20108 : fp = NULL;
80 :
81 : #ifdef HAVE_READLINK
82 20108 : int bHasRetried = FALSE;
83 : #endif
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Collect information about the file. */
87 : /* -------------------------------------------------------------------- */
88 : VSIStatBufL sStat;
89 :
90 : #ifdef HAVE_READLINK
91 : retry:
92 : #endif
93 20109 : if( VSIStatExL( pszFilename, &sStat,
94 : VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 )
95 : {
96 8106 : bStatOK = TRUE;
97 :
98 8106 : if( VSI_ISREG( sStat.st_mode ) )
99 : {
100 8060 : pabyHeader = (GByte *) CPLCalloc(1025,1);
101 :
102 8060 : fp = VSIFOpen( pszFilename, "rb" );
103 :
104 8060 : if( fp != NULL )
105 : {
106 7371 : nHeaderBytes = (int) VSIFRead( pabyHeader, 1, 1024, fp );
107 :
108 7371 : VSIRewind( fp );
109 : }
110 : /* XXX: ENOENT is used to catch the case of virtual filesystem
111 : * when we do not have a real file with such a name. Under some
112 : * circumstances EINVAL reported instead of ENOENT in Windows
113 : * (for filenames containing colon, e.g. "smth://name").
114 : * See also: #2437 */
115 689 : else if( errno == 27 /* "File to large" */
116 : || errno == ENOENT || errno == EINVAL
117 : #ifdef EOVERFLOW
118 : || errno == EOVERFLOW
119 : #else
120 : || errno == 75 /* Linux EOVERFLOW */
121 : || errno == 79 /* Solaris EOVERFLOW */
122 : #endif
123 : )
124 : {
125 689 : VSILFILE* fpL = VSIFOpenL( pszFilename, "rb" );
126 689 : if( fpL != NULL )
127 : {
128 689 : nHeaderBytes = (int) VSIFReadL( pabyHeader, 1, 1024, fpL );
129 689 : VSIFCloseL( fpL );
130 : }
131 : }
132 : }
133 46 : else if( VSI_ISDIR( sStat.st_mode ) )
134 46 : bIsDirectory = TRUE;
135 : }
136 : #ifdef HAVE_READLINK
137 12003 : else if (!bHasRetried)
138 : {
139 : /* If someone creates a file with "ln -sf /vsicurl/http://download.osgeo.org/gdal/data/gtiff/utm.tif my_remote_utm.tif" */
140 : /* we will be able to open it by passing my_remote_utm.tif */
141 : /* This helps a lot for GDAL based readers that only provide file explorers to open datasets */
142 : char szPointerFilename[2048];
143 12002 : int nBytes = readlink(pszFilename, szPointerFilename, sizeof(szPointerFilename));
144 12002 : if (nBytes != -1)
145 : {
146 1 : szPointerFilename[MIN(nBytes, (int)sizeof(szPointerFilename)-1)] = 0;
147 1 : CPLFree(pszFilename);
148 1 : pszFilename = CPLStrdup(szPointerFilename);
149 1 : papszSiblingsIn = NULL;
150 1 : bHasRetried = TRUE;
151 1 : goto retry;
152 : }
153 : }
154 : #endif
155 :
156 : /* -------------------------------------------------------------------- */
157 : /* Capture sibling list either from passed in values, or by */
158 : /* scanning for them. */
159 : /* -------------------------------------------------------------------- */
160 20108 : if( papszSiblingsIn != NULL )
161 : {
162 107 : papszSiblingFiles = CSLDuplicate( papszSiblingsIn );
163 : }
164 27954 : else if( bStatOK && !bIsDirectory )
165 : {
166 : const char* pszOptionVal =
167 7953 : CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
168 7953 : if (EQUAL(pszOptionVal, "EMPTY_DIR"))
169 : {
170 1 : papszSiblingFiles = CSLAddString( NULL, CPLGetFilename(pszFilename) );
171 : }
172 7952 : else if( CSLTestBoolean(pszOptionVal) )
173 : {
174 : /* skip reading the directory */
175 11 : papszSiblingFiles = NULL;
176 : }
177 : else
178 : {
179 7941 : CPLString osDir = CPLGetDirname( pszFilename );
180 7941 : papszSiblingFiles = VSIReadDir( osDir );
181 :
182 : /* Small optimization to avoid unnecessary stat'ing from PAux or ENVI */
183 : /* drivers. The MBTiles driver needs no companion file. */
184 7941 : if( papszSiblingFiles == NULL &&
185 : strncmp(pszFilename, "/vsicurl/", 9) == 0 &&
186 : EQUAL(CPLGetExtension( pszFilename ),"mbtiles") )
187 : {
188 1 : papszSiblingFiles = CSLAddString( NULL, CPLGetFilename(pszFilename) );
189 7941 : }
190 : }
191 : }
192 : else
193 12048 : papszSiblingFiles = NULL;
194 20108 : }
195 :
196 : /************************************************************************/
197 : /* ~GDALOpenInfo() */
198 : /************************************************************************/
199 :
200 20108 : GDALOpenInfo::~GDALOpenInfo()
201 :
202 : {
203 20108 : VSIFree( pabyHeader );
204 20108 : CPLFree( pszFilename );
205 :
206 20108 : if( fp != NULL )
207 7074 : VSIFClose( fp );
208 20108 : CSLDestroy( papszSiblingFiles );
209 20108 : }
210 :
|