00001 /****************************************************************************** 00002 * $Id: gdalopen_cpp-source.html,v 1.13 2002/12/21 19:13:13 warmerda Exp $ 00003 * 00004 * Project: GDAL Core 00005 * Purpose: Implementation of GDALOpen(), GDALOpenShared(), GDALOpenInfo and 00006 * related services. 00007 * Author: Frank Warmerdam, warmerdam@pobox.com 00008 * 00009 ********************************************************************** 00010 * Copyright (c) 2002, Frank Warmerdam 00011 * 00012 * Permission is hereby granted, free of charge, to any person obtaining a 00013 * copy of this software and associated documentation files (the "Software"), 00014 * to deal in the Software without restriction, including without limitation 00015 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00016 * and/or sell copies of the Software, and to permit persons to whom the 00017 * Software is furnished to do so, subject to the following conditions: 00018 * 00019 * The above copyright notice and this permission notice shall be included 00020 * in all copies or substantial portions of the Software. 00021 * 00022 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00023 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00024 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00025 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00026 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00027 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00028 * DEALINGS IN THE SOFTWARE. 00029 ****************************************************************************** 00030 * 00031 * $Log: gdalopen_cpp-source.html,v $ 00031 * Revision 1.13 2002/12/21 19:13:13 warmerda 00031 * updated 00031 * 00032 * Revision 1.17 2002/07/09 20:33:12 warmerda 00033 * expand tabs 00034 * 00035 * Revision 1.16 2002/06/19 18:20:21 warmerda 00036 * use VSIStatL() so it works on large files, dont keep stat in openinfo. 00037 * 00038 * Revision 1.15 2002/06/15 00:07:23 aubin 00039 * mods to enable 64bit file i/o 00040 * 00041 * Revision 1.14 2002/06/12 21:13:27 warmerda 00042 * use metadata based driver info 00043 * 00044 * Revision 1.13 2002/05/28 18:56:22 warmerda 00045 * added shared dataset concept 00046 * 00047 * Revision 1.12 2001/12/12 17:21:21 warmerda 00048 * Use CPLStat instead of VSIStat(). 00049 * 00050 * Revision 1.11 2001/08/20 13:40:28 warmerda 00051 * modified message on failure to open if not a file 00052 * 00053 * Revision 1.10 2001/07/18 04:04:30 warmerda 00054 * added CPL_CVSID 00055 * 00056 * Revision 1.9 2001/01/03 05:32:20 warmerda 00057 * avoid depending on VSIStatBuf file size for 2GB issues 00058 * 00059 * Revision 1.8 2000/04/21 21:55:53 warmerda 00060 * set filename as description of GDALDatasets. 00061 * 00062 * Revision 1.7 2000/01/10 15:43:06 warmerda 00063 * Fixed debug statement. 00064 * 00065 * Revision 1.6 2000/01/10 15:31:02 warmerda 00066 * Added debug statement in GDALOpen. 00067 * 00068 * Revision 1.5 1999/11/11 21:59:07 warmerda 00069 * added GetDriver() for datasets 00070 * 00071 * Revision 1.4 1999/10/01 14:44:02 warmerda 00072 * added documentation 00073 * 00074 * Revision 1.3 1999/04/21 04:00:34 warmerda 00075 * Initialize fp to NULL. 00076 * 00077 * Revision 1.2 1998/12/31 18:52:45 warmerda 00078 * Use CPL memory functions (they are safe), and fixed up header reading. 00079 * 00080 * Revision 1.1 1998/12/03 18:31:45 warmerda 00081 * New 00082 * 00083 */ 00084 00085 #include "gdal_priv.h" 00086 #include "cpl_conv.h" 00087 00088 CPL_CVSID("$Id: gdalopen_cpp-source.html,v 1.13 2002/12/21 19:13:13 warmerda Exp $"); 00089 00090 /************************************************************************/ 00091 /* ==================================================================== */ 00092 /* GDALOpenInfo */ 00093 /* ==================================================================== */ 00094 /************************************************************************/ 00095 00096 /************************************************************************/ 00097 /* GDALOpenInfo() */ 00098 /************************************************************************/ 00099 00100 GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, GDALAccess eAccessIn ) 00101 00102 { 00103 /* -------------------------------------------------------------------- */ 00104 /* Ensure that C: is treated as C:\ so we can stat it on */ 00105 /* Windows. Similar to what is done in CPLStat(). */ 00106 /* -------------------------------------------------------------------- */ 00107 #ifdef WIN32 00108 if( strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':' ) 00109 { 00110 char szAltPath[10]; 00111 00112 strcpy( szAltPath, pszFilenameIn ); 00113 strcat( szAltPath, "\\" ); 00114 pszFilename = CPLStrdup( szAltPath ); 00115 } 00116 else 00117 #endif 00118 pszFilename = CPLStrdup( pszFilenameIn ); 00119 00120 /* -------------------------------------------------------------------- */ 00121 /* Initialize. */ 00122 /* -------------------------------------------------------------------- */ 00123 00124 nHeaderBytes = 0; 00125 pabyHeader = NULL; 00126 bIsDirectory = FALSE; 00127 bStatOK = FALSE; 00128 eAccess = eAccessIn; 00129 fp = NULL; 00130 00131 /* -------------------------------------------------------------------- */ 00132 /* Collect information about the file. */ 00133 /* -------------------------------------------------------------------- */ 00134 VSIStatBufL sStat; 00135 00136 if( VSIStatL( pszFilename, &sStat ) == 0 ) 00137 { 00138 bStatOK = TRUE; 00139 00140 if( VSI_ISREG( sStat.st_mode ) ) 00141 { 00142 pabyHeader = (GByte *) CPLCalloc(1025,1); 00143 00144 fp = VSIFOpen( pszFilename, "rb" ); 00145 00146 if( fp != NULL ) 00147 { 00148 nHeaderBytes = VSIFRead( pabyHeader, 1, 1024, fp ); 00149 00150 VSIRewind( fp ); 00151 } 00152 } 00153 else if( VSI_ISDIR( sStat.st_mode ) ) 00154 bIsDirectory = TRUE; 00155 } 00156 } 00157 00158 /************************************************************************/ 00159 /* ~GDALOpenInfo() */ 00160 /************************************************************************/ 00161 00162 GDALOpenInfo::~GDALOpenInfo() 00163 00164 { 00165 VSIFree( pabyHeader ); 00166 CPLFree( pszFilename ); 00167 00168 if( fp != NULL ) 00169 VSIFClose( fp ); 00170 } 00171 00172 /************************************************************************/ 00173 /* GDALOpen() */ 00174 /************************************************************************/ 00175 00193 GDALDatasetH GDALOpen( const char * pszFilename, GDALAccess eAccess ) 00194 00195 { 00196 int iDriver; 00197 GDALDriverManager *poDM = GetGDALDriverManager(); 00198 GDALOpenInfo oOpenInfo( pszFilename, eAccess ); 00199 00200 CPLErrorReset(); 00201 00202 for( iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++ ) 00203 { 00204 GDALDriver *poDriver = poDM->GetDriver( iDriver ); 00205 GDALDataset *poDS; 00206 00207 poDS = poDriver->pfnOpen( &oOpenInfo ); 00208 if( poDS != NULL ) 00209 { 00210 poDS->SetDescription( pszFilename ); 00211 00212 if( poDS->poDriver == NULL ) 00213 poDS->poDriver = poDriver; 00214 00215 00216 CPLDebug( "GDAL", "GDALOpen(%s) succeeds as %s.\n", 00217 pszFilename, poDriver->GetDescription() ); 00218 00219 return (GDALDatasetH) poDS; 00220 } 00221 00222 if( CPLGetLastErrorNo() != 0 ) 00223 return NULL; 00224 } 00225 00226 if( oOpenInfo.bStatOK ) 00227 CPLError( CE_Failure, CPLE_OpenFailed, 00228 "`%s' not recognised as a supported file format.\n", 00229 pszFilename ); 00230 else 00231 CPLError( CE_Failure, CPLE_OpenFailed, 00232 "`%s' does not exist in the file system,\n" 00233 "and is not recognised as a supported dataset name.\n", 00234 pszFilename ); 00235 00236 return NULL; 00237 } 00238 00239 /************************************************************************/ 00240 /* GDALOpenShared() */ 00241 /************************************************************************/ 00242 00264 GDALDatasetH GDALOpenShared( const char *pszFilename, GDALAccess eAccess ) 00265 00266 { 00267 /* -------------------------------------------------------------------- */ 00268 /* First scan the existing list to see if it could already */ 00269 /* contain the requested dataset. */ 00270 /* -------------------------------------------------------------------- */ 00271 int i, nSharedDatasetCount; 00272 GDALDataset **papoSharedDatasets 00273 = GDALDataset::GetOpenDatasets(&nSharedDatasetCount); 00274 00275 for( i = 0; i < nSharedDatasetCount; i++ ) 00276 { 00277 if( strcmp(pszFilename,papoSharedDatasets[i]->GetDescription()) == 0 00278 && (eAccess == GA_ReadOnly 00279 || papoSharedDatasets[i]->GetAccess() == eAccess ) ) 00280 00281 { 00282 papoSharedDatasets[i]->Reference(); 00283 return papoSharedDatasets[i]; 00284 } 00285 } 00286 00287 /* -------------------------------------------------------------------- */ 00288 /* Try opening the the requested dataset. */ 00289 /* -------------------------------------------------------------------- */ 00290 GDALDataset *poDataset; 00291 00292 poDataset = (GDALDataset *) GDALOpen( pszFilename, eAccess ); 00293 if( poDataset != NULL ) 00294 poDataset->MarkAsShared(); 00295 00296 return (GDALDatasetH) poDataset; 00297 } 00298 00299 /************************************************************************/ 00300 /* GDALClose() */ 00301 /************************************************************************/ 00302 00303 void GDALClose( GDALDatasetH hDS ) 00304 00305 { 00306 GDALDataset *poDS = (GDALDataset *) hDS; 00307 int i, nSharedDatasetCount; 00308 GDALDataset **papoSharedDatasets 00309 = GDALDataset::GetOpenDatasets(&nSharedDatasetCount); 00310 00311 /* -------------------------------------------------------------------- */ 00312 /* If this file is in the shared dataset list then dereference */ 00313 /* it, and only delete/remote it if the reference count has */ 00314 /* dropped to zero. */ 00315 /* -------------------------------------------------------------------- */ 00316 for( i = 0; i < nSharedDatasetCount; i++ ) 00317 { 00318 if( papoSharedDatasets[i] == poDS ) 00319 { 00320 if( poDS->Dereference() > 0 ) 00321 return; 00322 00323 delete poDS; 00324 return; 00325 } 00326 } 00327 00328 /* -------------------------------------------------------------------- */ 00329 /* This is not shared dataset, so directly delete it. */ 00330 /* -------------------------------------------------------------------- */ 00331 delete poDS; 00332 } 00333 00334 /************************************************************************/ 00335 /* GDALDumpOpenDataset() */ 00336 /************************************************************************/ 00337 00338 int GDALDumpOpenDatasets( FILE *fp ) 00339 00340 { 00341 int i, nSharedDatasetCount; 00342 GDALDataset **papoSharedDatasets 00343 = GDALDataset::GetOpenDatasets(&nSharedDatasetCount); 00344 00345 if( nSharedDatasetCount > 0 ) 00346 VSIFPrintf( fp, "Open GDAL Datasets:\n" ); 00347 00348 for( i = 0; i < nSharedDatasetCount; i++ ) 00349 { 00350 const char *pszDriverName; 00351 GDALDataset *poDS = papoSharedDatasets[i]; 00352 00353 if( poDS->GetDriver() == NULL ) 00354 pszDriverName = "DriverIsNULL"; 00355 else 00356 pszDriverName = poDS->GetDriver()->GetDescription(); 00357 00358 poDS->Reference(); 00359 VSIFPrintf( fp, " %d %c %-6s %dx%dx%d %s\n", 00360 poDS->Dereference(), 00361 poDS->GetShared() ? 'S' : 'N', 00362 pszDriverName, 00363 poDS->GetRasterXSize(), 00364 poDS->GetRasterYSize(), 00365 poDS->GetRasterCount(), 00366 poDS->GetDescription() ); 00367 } 00368 00369 return nSharedDatasetCount; 00370 }