From 9164eb1ccf8b18afe87d1771b9055e88bafa110f Mon Sep 17 00:00:00 2001 From: lossyrob Date: Fri, 26 Feb 2016 16:19:29 +0100 Subject: [PATCH] Created VSIError to report VSI errors. --- gdal/apps/gdalinfo_bin.cpp | 13 +- gdal/gcore/gdaldataset.cpp | 535 +++++++++++++------------- gdal/gcore/gdalopeninfo.cpp | 19 +- gdal/port/GNUmakefile | 14 +- gdal/port/cpl_aws.cpp | 43 ++- gdal/port/cpl_aws.h | 3 +- gdal/port/cpl_error.cpp | 84 ++-- gdal/port/cpl_error.h | 45 ++- gdal/port/cpl_multiproc.h | 41 +- gdal/port/cpl_vsi.h | 17 +- gdal/port/cpl_vsi_error.cpp | 294 ++++++++++++++ gdal/port/cpl_vsi_error.h | 68 ++++ gdal/port/cpl_vsi_mem.cpp | 79 ++-- gdal/port/cpl_vsi_virtual.h | 30 +- gdal/port/cpl_vsil.cpp | 41 +- gdal/port/cpl_vsil_crypt.cpp | 26 +- gdal/port/cpl_vsil_curl.cpp | 83 ++-- gdal/port/cpl_vsil_curl_streaming.cpp | 17 +- gdal/port/cpl_vsil_gzip.cpp | 60 +-- gdal/port/cpl_vsil_sparsefile.cpp | 70 ++-- gdal/port/cpl_vsil_stdin.cpp | 18 +- gdal/port/cpl_vsil_stdout.cpp | 30 +- gdal/port/cpl_vsil_subfile.cpp | 43 ++- gdal/port/cpl_vsil_tar.cpp | 14 +- gdal/port/cpl_vsil_unix_stdio_64.cpp | 12 +- gdal/port/cpl_vsil_win32.cpp | 71 ++-- 26 files changed, 1142 insertions(+), 628 deletions(-) create mode 100644 gdal/port/cpl_vsi_error.cpp create mode 100644 gdal/port/cpl_vsi_error.h diff --git a/gdal/apps/gdalinfo_bin.cpp b/gdal/apps/gdalinfo_bin.cpp index e47e64b2e19f..0a32811198ba 100644 --- a/gdal/apps/gdalinfo_bin.cpp +++ b/gdal/apps/gdalinfo_bin.cpp @@ -82,7 +82,7 @@ static void GDALInfoOptionsForBinaryFree( GDALInfoOptionsForBinary* psOptionsFor /* main() */ /************************************************************************/ -int main( int argc, char ** argv ) +int main( int argc, char ** argv ) { EarlySetConfigOptions(argc, argv); @@ -127,8 +127,9 @@ int main( int argc, char ** argv ) while (__AFL_LOOP(1000)) { iIter ++; #endif + GDALDatasetH hDataset - = GDALOpenEx( psOptionsForBinary->pszFilename, GDAL_OF_READONLY | GDAL_OF_RASTER, NULL, + = GDALOpenEx( psOptionsForBinary->pszFilename, GDAL_OF_READONLY | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL, (const char* const* )psOptionsForBinary->papszOpenOptions, NULL ); if( hDataset == NULL ) @@ -143,16 +144,16 @@ int main( int argc, char ** argv ) /* -------------------------------------------------------------------- */ /* If argument is a VSIFILE, then print its contents */ /* -------------------------------------------------------------------- */ - if ( STARTS_WITH(psOptionsForBinary->pszFilename, "/vsizip/") || - STARTS_WITH(psOptionsForBinary->pszFilename, "/vsitar/") ) + if ( STARTS_WITH(psOptionsForBinary->pszFilename, "/vsizip/") || + STARTS_WITH(psOptionsForBinary->pszFilename, "/vsitar/") ) { char** papszFileList = VSIReadDirRecursive( psOptionsForBinary->pszFilename ); if ( papszFileList ) { int nCount = CSLCount( papszFileList ); - fprintf( stdout, + fprintf( stdout, "Unable to open source `%s' directly.\n" - "The archive contains %d files:\n", + "The archive contains %d files:\n", psOptionsForBinary->pszFilename, nCount ); for ( int i = 0; i < nCount; i++ ) { diff --git a/gdal/gcore/gdaldataset.cpp b/gdal/gcore/gdaldataset.cpp index 3eef0ed63524..b14b063f9a2e 100644 --- a/gdal/gcore/gdaldataset.cpp +++ b/gdal/gcore/gdaldataset.cpp @@ -2,7 +2,7 @@ * $Id$ * * Project: GDAL Core - * Purpose: Base class for raster file formats. + * Purpose: Base class for raster file formats. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** @@ -32,6 +32,7 @@ #include "cpl_string.h" #include "cpl_hash_set.h" #include "cpl_multiproc.h" +#include "cpl_vsi_error.h" #include "ogr_featurestyle.h" #include "swq.h" #include "ogr_gensql.h" @@ -80,7 +81,7 @@ typedef struct /* Set of datasets opened as shared datasets (with GDALOpenShared) */ /* The values in the set are of type SharedDatasetCtxt */ -static CPLHashSet* phSharedDatasetSet = NULL; +static CPLHashSet* phSharedDatasetSet = NULL; /* Set of all datasets created in the constructor of GDALDataset */ /* In the case of a shared dataset, memorize the PID of the thread */ @@ -164,7 +165,7 @@ GIntBig GDALGetResponsiblePIDForCurrentThread() * Data Model. * * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file, - * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new + * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new * dataset. */ @@ -175,7 +176,7 @@ GIntBig GDALGetResponsiblePIDForCurrentThread() GDALDataset::GDALDataset() { - Init( CPLTestBool( + Init( CPLTestBool( CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") ) ); } @@ -236,12 +237,12 @@ GDALDataset::~GDALDataset() if( !bIsInternal && ( nBands != 0 || !EQUAL(GetDescription(),"") ) ) { if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() ) - CPLDebug( "GDAL", + CPLDebug( "GDAL", "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)", GetDescription(), this, - (int)CPLGetPID(), + (int)CPLGetPID(), (int)GDALGetResponsiblePIDForCurrentThread() ); else - CPLDebug( "GDAL", + CPLDebug( "GDAL", "GDALClose(%s, this=%p)", GetDescription(), this ); } @@ -364,7 +365,7 @@ void GDALDataset::FlushCache() { // This sometimes happens if a dataset is destroyed before completely - // built. + // built. if( papoBands != NULL ) { @@ -495,19 +496,19 @@ void GDALDataset::RasterInitialize( int nXSize, int nYSize ) * \brief Add a band to a dataset. * * This method will add a new band to the dataset if the underlying format - * supports this action. Most formats do not. + * supports this action. Most formats do not. * * Note that the new GDALRasterBand is not returned. It may be fetched - * after successful completion of the method by calling + * after successful completion of the method by calling * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()) as the newest * band will always be the last band. * - * @param eType the data type of the pixels in the new band. + * @param eType the data type of the pixels in the new band. * * @param papszOptions a list of NAME=VALUE option strings. The supported * options are format specific. NULL may be passed by default. * - * @return CE_None on success or CE_Failure on failure. + * @return CE_None on success or CE_Failure on failure. */ CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions ) @@ -532,7 +533,7 @@ CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions ) * @see GDALDataset::AddBand(). */ -CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset, +CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset, GDALDataType eType, char **papszOptions ) { @@ -777,14 +778,14 @@ int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS ) * Same as the C function GDALGetProjectionRef(). * * The returned string defines the projection coordinate system of the - * image in OpenGIS WKT format. It should be suitable for use with the + * image in OpenGIS WKT format. It should be suitable for use with the * OGRSpatialReference class. * * When a projection definition is not available an empty (but not NULL) * string is returned. * * @return a pointer to an internal projection reference string. It should - * not be altered, freed or expected to last for long. + * not be altered, freed or expected to last for long. * * @see http://www.gdal.org/osr_tutorial.html */ @@ -899,7 +900,7 @@ CPLErr GDALDataset::GetGeoTransform( double * padfTransform ) padfTransform[2] = 0.0; padfTransform[3] = 0.0; /* Y Origin (top left corner) */ - padfTransform[4] = 0.0; + padfTransform[4] = 0.0; padfTransform[5] = 1.0; /* Y Pixel Size */ return( CE_Failure ); @@ -962,7 +963,7 @@ CPLErr GDALDataset::SetGeoTransform( CPL_UNUSED double * padfTransform ) * @see GDALDataset::SetGeoTransform() */ -CPLErr CPL_STDCALL +CPLErr CPL_STDCALL GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform ) { @@ -1002,7 +1003,7 @@ void *GDALDataset::GetInternalHandle( CPL_UNUSED const char * pszHandleName ) * @see GDALDataset::GetInternalHandle() */ -void * CPL_STDCALL +void * CPL_STDCALL GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest ) { @@ -1190,9 +1191,9 @@ void GDALDataset::MarkAsShared() /************************************************************************/ /** - * \brief Get number of GCPs. + * \brief Get number of GCPs. * - * This method is the same as the C function GDALGetGCPCount(). + * This method is the same as the C function GDALGetGCPCount(). * * @return number of GCPs for this dataset. Zero if there are none. */ @@ -1208,7 +1209,7 @@ int GDALDataset::GetGCPCount() /************************************************************************/ /** - * \brief Get number of GCPs. + * \brief Get number of GCPs. * * @see GDALDataset::GetGCPCount() */ @@ -1226,13 +1227,13 @@ int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS ) /************************************************************************/ /** - * \brief Get output projection for GCPs. + * \brief Get output projection for GCPs. * - * This method is the same as the C function GDALGetGCPProjection(). + * This method is the same as the C function GDALGetGCPProjection(). * * The projection string follows the normal rules from GetProjectionRef(). * - * @return internal projection string or "" if there are no GCPs. + * @return internal projection string or "" if there are no GCPs. * It should not be altered, freed or expected to last for long. */ @@ -1247,7 +1248,7 @@ const char *GDALDataset::GetGCPProjection() /************************************************************************/ /** - * \brief Get output projection for GCPs. + * \brief Get output projection for GCPs. * * @see GDALDataset::GetGCPProjection() */ @@ -1267,11 +1268,11 @@ const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS ) /** * \brief Fetch GCPs. * - * This method is the same as the C function GDALGetGCPs(). + * This method is the same as the C function GDALGetGCPs(). * - * @return pointer to internal GCP structure list. It should not be modified, - * and may change on the next GDAL call. - */ + * @return pointer to internal GCP structure list. It should not be modified, + * and may change on the next GDAL call. + */ const GDAL_GCP *GDALDataset::GetGCPs() @@ -1305,29 +1306,29 @@ const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS ) /** * \brief Assign GCPs. * - * This method is the same as the C function GDALSetGCPs(). + * This method is the same as the C function GDALSetGCPs(). * * This method assigns the passed set of GCPs to this dataset, as well as * setting their coordinate system. Internally copies are made of the * coordinate system and list of points, so the caller remains responsible for - * deallocating these arguments if appropriate. + * deallocating these arguments if appropriate. * - * Most formats do not support setting of GCPs, even formats that can - * handle GCPs. These formats will return CE_Failure. + * Most formats do not support setting of GCPs, even formats that can + * handle GCPs. These formats will return CE_Failure. * - * @param nGCPCount number of GCPs being assigned. + * @param nGCPCount number of GCPs being assigned. * * @param pasGCPList array of GCP structures being assign (nGCPCount in array). * - * @param pszGCPProjection the new OGC WKT coordinate system to assign for the + * @param pszGCPProjection the new OGC WKT coordinate system to assign for the * GCP output coordinates. This parameter should be "" if no output coordinate * system is known. * * @return CE_None on success, CE_Failure on failure (including if action is - * not supported for this format). - */ + * not supported for this format). + */ -CPLErr GDALDataset::SetGCPs( int nGCPCount, +CPLErr GDALDataset::SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList, const char * pszGCPProjection ) @@ -1353,14 +1354,14 @@ CPLErr GDALDataset::SetGCPs( int nGCPCount, * @see GDALDataset::SetGCPs() */ -CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount, - const GDAL_GCP *pasGCPList, +CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount, + const GDAL_GCP *pasGCPList, const char *pszGCPProjection ) { VALIDATE_POINTER1( hDS, "GDALSetGCPs", CE_Failure ); - return ((GDALDataset *) hDS)->SetGCPs( nGCPCount, pasGCPList, + return ((GDALDataset *) hDS)->SetGCPs( nGCPCount, pasGCPList, pszGCPProjection ); } @@ -1371,19 +1372,19 @@ CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount, /** * \brief Build raster overview(s) * - * If the operation is unsupported for the indicated dataset, then - * CE_Failure is returned, and CPLGetLastErrorNo() will return + * If the operation is unsupported for the indicated dataset, then + * CE_Failure is returned, and CPLGetLastErrorNo() will return * CPLE_NotSupported. * * This method is the same as the C function GDALBuildOverviews(). * * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE", * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied. - * @param nOverviews number of overviews to build. - * @param panOverviewList the list of overview decimation factors to build. + * @param nOverviews number of overviews to build. + * @param panOverviewList the list of overview decimation factors to build. * @param nListBands number of bands to build overviews for in panBandList. Build - * for all bands if this is 0. - * @param panBandList list of band numbers. + * for all bands if this is 0. + * @param panBandList list of band numbers. * @param pfnProgress a function to call to report progress, or NULL. * @param pProgressData application data to pass to the progress function. * @@ -1393,18 +1394,18 @@ CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount, * call could be made: *
  *   int       anOverviewList[3] = { 2, 4, 8 };
- *   
- *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL, 
+ *
+ *   poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL,
  *                              GDALDummyProgress, NULL );
  * 
* * @see GDALRegenerateOverviews() */ -CPLErr GDALDataset::BuildOverviews( const char *pszResampling, - int nOverviews, int *panOverviewList, +CPLErr GDALDataset::BuildOverviews( const char *pszResampling, + int nOverviews, int *panOverviewList, int nListBands, int *panBandList, - GDALProgressFunc pfnProgress, + GDALProgressFunc pfnProgress, void * pProgressData ) { @@ -1424,7 +1425,7 @@ CPLErr GDALDataset::BuildOverviews( const char *pszResampling, if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; - eErr = IBuildOverviews( pszResampling, nOverviews, panOverviewList, + eErr = IBuildOverviews( pszResampling, nOverviews, panOverviewList, nListBands, panBandList, pfnProgress, pProgressData ); if( panAllBandList != NULL ) @@ -1444,17 +1445,17 @@ CPLErr GDALDataset::BuildOverviews( const char *pszResampling, */ CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset, - const char *pszResampling, - int nOverviews, int *panOverviewList, + const char *pszResampling, + int nOverviews, int *panOverviewList, int nListBands, int *panBandList, - GDALProgressFunc pfnProgress, + GDALProgressFunc pfnProgress, void * pProgressData ) { VALIDATE_POINTER1( hDataset, "GDALBuildOverviews", CE_Failure ); return ((GDALDataset *) hDataset)->BuildOverviews( - pszResampling, nOverviews, panOverviewList, nListBands, panBandList, + pszResampling, nOverviews, panOverviewList, nListBands, panBandList, pfnProgress, pProgressData ); } @@ -1464,15 +1465,15 @@ CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset, /* Default implementation. */ /************************************************************************/ -CPLErr GDALDataset::IBuildOverviews( const char *pszResampling, - int nOverviews, int *panOverviewList, +CPLErr GDALDataset::IBuildOverviews( const char *pszResampling, + int nOverviews, int *panOverviewList, int nListBands, int *panBandList, - GDALProgressFunc pfnProgress, + GDALProgressFunc pfnProgress, void * pProgressData ) { if( oOvManager.IsInitialized() ) - return oOvManager.BuildOverviews( NULL, pszResampling, + return oOvManager.BuildOverviews( NULL, pszResampling, nOverviews, panOverviewList, nListBands, panBandList, pfnProgress, pProgressData ); @@ -1497,7 +1498,7 @@ CPLErr GDALDataset::IBuildOverviews( const char *pszResampling, CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, - GDALDataType eBufType, + GDALDataType eBufType, int nBandCount, int *panBandMap, GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace, @@ -1513,7 +1514,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag, (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL && EQUAL(pszInterleave, "PIXEL")) { - return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, + return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, @@ -1589,7 +1590,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag, if( nOKBands < nBandCount ) { psExtraArg->pfnProgress = GDALScaledProgress; - psExtraArg->pProgressData = + psExtraArg->pProgressData = GDALCreateScaledProgress( 0.0, (double)nOKBands / nBandCount, pfnProgressGlobal, pProgressDataGlobal ); @@ -1597,7 +1598,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag, psExtraArg->pfnProgress = NULL; } - eErr = RasterIOResampled( eRWFlag, nXOff, nYOff, nXSize, nYSize, + eErr = RasterIOResampled( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nOKBands, panBandMap, nPixelSpace, nLineSpace, nBandSpace, @@ -1613,14 +1614,14 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag, if( nOKBands > 0 ) { psExtraArg->pfnProgress = GDALScaledProgress; - psExtraArg->pProgressData = + psExtraArg->pProgressData = GDALCreateScaledProgress( (double)nOKBands / nBandCount, 1.0, pfnProgressGlobal, pProgressDataGlobal ); if( psExtraArg->pProgressData == NULL ) psExtraArg->pfnProgress = NULL; } - eErr = BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, + eErr = BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, (GByte*)pData + nBandSpace * nOKBands, nBufXSize, nBufYSize, eBufType, nBandCount - nOKBands, panBandMap + nOKBands, nPixelSpace, nLineSpace, nBandSpace, @@ -1637,7 +1638,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag, return eErr; } - return BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, + return BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, @@ -1654,21 +1655,21 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag, CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, - GDALDataType eBufType, + GDALDataType eBufType, int nBandCount, int *panBandMap, GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace, GDALRasterIOExtraArg* psExtraArg ) { - int iBandIndex; + int iBandIndex; CPLErr eErr = CE_None; GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress; void *pProgressDataGlobal = psExtraArg->pProgressData; - for( iBandIndex = 0; - iBandIndex < nBandCount && eErr == CE_None; + for( iBandIndex = 0; + iBandIndex < nBandCount && eErr == CE_None; iBandIndex++ ) { GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]); @@ -1685,7 +1686,7 @@ CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag, if( nBandCount > 1 ) { psExtraArg->pfnProgress = GDALScaledProgress; - psExtraArg->pProgressData = + psExtraArg->pProgressData = GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount, 1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal, @@ -1694,7 +1695,7 @@ CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag, psExtraArg->pfnProgress = NULL; } - eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, + eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, (void *) pabyBandData, nBufXSize, nBufYSize, eBufType, nPixelSpace, nLineSpace, psExtraArg ); @@ -1717,7 +1718,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters( const char* pszCallingFunc, int* pbStopProcessingOnCENone, int nXOff, int nYOff, int nXSize, int nYSize, - int nBufXSize, int nBufYSize, + int nBufXSize, int nBufYSize, int nBandCount, int *panBandMap) { @@ -1727,12 +1728,12 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters( /* -------------------------------------------------------------------- */ if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 ) { - CPLDebug( "GDAL", + CPLDebug( "GDAL", "%s skipped for odd window or buffer size.\n" " Window = (%d,%d)x%dx%d\n" " Buffer = %dx%d\n", pszCallingFunc, - nXOff, nYOff, nXSize, nYSize, + nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize ); *pbStopProcessingOnCENone = TRUE; @@ -1791,7 +1792,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters( * \brief Read/write a region of image data from multiple bands. * * This method allows reading a region of one or more GDALRasterBands from - * this dataset into a buffer, or writing data from a buffer into a region + * this dataset into a buffer, or writing data from a buffer into a region * of the GDALRasterBands. It automatically takes care of data type * translation if the data type (eBufType) of the buffer is different than * that of the GDALRasterBand. @@ -1800,7 +1801,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters( * region being accessed (nXSize x nYSize). * * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or - * writing from various organization of buffers. + * writing from various organization of buffers. * * For highest performance full resolution data access, read and write * on "block boundaries" as returned by GetBlockSize(), or use the @@ -1838,10 +1839,10 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters( * pixel values will automatically be translated to/from the GDALRasterBand * data type as needed. * - * @param nBandCount the number of bands being read or written. + * @param nBandCount the number of bands being read or written. * * @param panBandMap the list of nBandCount band numbers being read/written. - * Note band numbers are 1 based. This may be NULL to select the first + * Note band numbers are 1 based. This may be NULL to select the first * nBandCount bands. * * @param nPixelSpace The byte offset from the start of one pixel value in @@ -1853,9 +1854,9 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters( * eBufType * nBufXSize is used. * * @param nBandSpace the byte offset from the start of one bands data to the - * start of the next. If defaulted (0) the value will be + * start of the next. If defaulted (0) the value will be * nLineSpace * nBufYSize implying band sequential organization - * of the data buffer. + * of the data buffer. * * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg structure with additional * arguments to specify resampling and progress callback, or NULL for default @@ -1869,7 +1870,7 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters( CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, void * pData, int nBufXSize, int nBufYSize, - GDALDataType eBufType, + GDALDataType eBufType, int nBandCount, int *panBandMap, GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace, @@ -1918,7 +1919,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag, int bStopProcessing = FALSE; eErr = ValidateRasterIOOrAdviseReadParameters( "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, - nBufXSize, nBufYSize, + nBufXSize, nBufYSize, nBandCount, panBandMap); if( eErr != CE_None || bStopProcessing ) return eErr; @@ -1970,7 +1971,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag, /* -------------------------------------------------------------------- */ if( bForceCachedIO ) { - eErr = + eErr = BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap, @@ -1983,7 +1984,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag, /* -------------------------------------------------------------------- */ else if( eErr == CE_None ) { - eErr = + eErr = IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap, @@ -2030,7 +2031,7 @@ GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag, return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, - nBandCount, panBandMap, + nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, NULL ) ); } @@ -2062,7 +2063,7 @@ GDALDatasetRasterIOEx( GDALDatasetH hDS, GDALRWFlag eRWFlag, return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize, eBufType, - nBandCount, panBandMap, + nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg ) ); } /************************************************************************/ @@ -2080,7 +2081,7 @@ GDALDatasetRasterIOEx( GDALDatasetH hDS, GDALRWFlag eRWFlag, * @param pnCount integer into which to place the count of dataset pointers * being returned. * - * @return a pointer to an array of dataset handles. + * @return a pointer to an array of dataset handles. */ GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount ) @@ -2163,13 +2164,13 @@ int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS ) /** * \brief Advise driver of upcoming read requests. * - * Some GDAL drivers operate more efficiently if they know in advance what + * Some GDAL drivers operate more efficiently if they know in advance what * set of upcoming read requests will be made. The AdviseRead() method allows - * an application to notify the driver of the region and bands of interest, - * and at what resolution the region will be read. + * an application to notify the driver of the region and bands of interest, + * and at what resolution the region will be read. * * Many drivers just ignore the AdviseRead() call, but it can dramatically - * accelerate access via some drivers. + * accelerate access via some drivers. * * @param nXOff The pixel offset to the top left corner of the region * of the band to be accessed. This would be zero to start from the left side. @@ -2191,22 +2192,22 @@ int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS ) * pixel values will automatically be translated to/from the GDALRasterBand * data type as needed. * - * @param nBandCount the number of bands being read or written. + * @param nBandCount the number of bands being read or written. * * @param panBandMap the list of nBandCount band numbers being read/written. - * Note band numbers are 1 based. This may be NULL to select the first + * Note band numbers are 1 based. This may be NULL to select the first * nBandCount bands. * - * @param papszOptions a list of name=value strings with special control + * @param papszOptions a list of name=value strings with special control * options. Normally this is NULL. * * @return CE_Failure if the request is invalid and CE_None if it works or - * is ignored. + * is ignored. */ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize, - int nBufXSize, int nBufYSize, - GDALDataType eBufType, + int nBufXSize, int nBufYSize, + GDALDataType eBufType, int nBandCount, int *panBandMap, char **papszOptions ) @@ -2219,7 +2220,7 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize, int bStopProcessing = FALSE; CPLErr eErr = ValidateRasterIOOrAdviseReadParameters( "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, - nBufXSize, nBufYSize, + nBufXSize, nBufYSize, nBandCount, panBandMap); if( eErr != CE_None || bStopProcessing ) return eErr; @@ -2252,18 +2253,18 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize, * * @see GDALDataset::AdviseRead() */ -CPLErr CPL_STDCALL -GDALDatasetAdviseRead( GDALDatasetH hDS, +CPLErr CPL_STDCALL +GDALDatasetAdviseRead( GDALDatasetH hDS, int nXOff, int nYOff, int nXSize, int nYSize, - int nBufXSize, int nBufYSize, GDALDataType eDT, + int nBufXSize, int nBufYSize, GDALDataType eDT, int nBandCount, int *panBandMap,char **papszOptions ) { VALIDATE_POINTER1( hDS, "GDALDatasetAdviseRead", CE_Failure ); - return ((GDALDataset *) hDS)->AdviseRead( nXOff, nYOff, nXSize, nYSize, - nBufXSize, nBufYSize, eDT, - nBandCount, panBandMap, + return ((GDALDataset *) hDS)->AdviseRead( nXOff, nYOff, nXSize, nYSize, + nBufXSize, nBufYSize, eDT, + nBandCount, panBandMap, papszOptions ); } @@ -2279,14 +2280,14 @@ GDALDatasetAdviseRead( GDALDatasetH hDS, * system files associated with the dataset (for instance a virtual dataset). * The returned file list is owned by the caller and should be deallocated * with CSLDestroy(). - * - * The returned filenames will normally be relative or absolute paths + * + * The returned filenames will normally be relative or absolute paths * depending on the path used to originally open the dataset. The strings * will be UTF-8 encoded. * * This method is the same as the C GDALGetFileList() function. * - * @return NULL or a NULL terminated array of file names. + * @return NULL or a NULL terminated array of file names. */ char **GDALDataset::GetFileList() @@ -2470,7 +2471,7 @@ CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags ) * \brief Open a raster file as a GDALDataset. * * This function will try to open the passed file, or virtual dataset - * name by invoking the Open method of each registered GDALDriver in turn. + * name by invoking the Open method of each registered GDALDriver in turn. * The first successful open will result in a returned dataset. If all * drivers fail then NULL is returned and an error is issued. * @@ -2504,10 +2505,10 @@ CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags ) * drivers support only read only access. * * @return A GDALDatasetH handle or NULL on failure. For C++ applications - * this handle can be cast to a GDALDataset *. + * this handle can be cast to a GDALDataset *. */ -GDALDatasetH CPL_STDCALL +GDALDatasetH CPL_STDCALL GDALOpen( const char * pszFilename, GDALAccess eAccess ) { @@ -2527,7 +2528,7 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess ) * \brief Open a raster or vector file as a GDALDataset. * * This function will try to open the passed file, or virtual dataset - * name by invoking the Open method of each registered GDALDriver in turn. + * name by invoking the Open method of each registered GDALDriver in turn. * The first successful open will result in a returned dataset. If all * drivers fail then NULL is returned and an error is issued. * @@ -2599,7 +2600,7 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess ) * of the file system will be done. * * @return A GDALDatasetH handle or NULL on failure. For C++ applications - * this handle can be cast to a GDALDataset *. + * this handle can be cast to a GDALDataset *. * * @since GDAL 2.0 */ @@ -2653,6 +2654,21 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename, if( (nOpenFlags & GDAL_OF_KIND_MASK) == 0 ) nOpenFlags |= GDAL_OF_KIND_MASK; + int iDriver; + GDALDriverManager *poDM = GetGDALDriverManager(); + //CPLLocaleC oLocaleForcer; + + CPLErrorReset(); + VSIErrorReset(); + CPLAssert( NULL != poDM ); + + /* Build GDALOpenInfo just now to avoid useless file stat'ing if a */ + /* shared dataset was asked before */ + GDALOpenInfo oOpenInfo(pszFilename, + nOpenFlags, + (char**) papszSiblingFiles); + + // Prevent infinite recursion { int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP ); if( pnRecCount == NULL ) @@ -2670,19 +2686,6 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename, (*pnRecCount) ++; } - int iDriver; - GDALDriverManager *poDM = GetGDALDriverManager(); - //CPLLocaleC oLocaleForcer; - - CPLErrorReset(); - CPLAssert( NULL != poDM ); - - /* Build GDALOpenInfo just now to avoid useless file stat'ing if a */ - /* shared dataset was asked before */ - GDALOpenInfo oOpenInfo(pszFilename, - nOpenFlags, - (char**) papszSiblingFiles); - // Remove leading @ if present char** papszOpenOptionsCleaned = CSLDuplicate((char**)papszOpenOptions); for(char** papszIter = papszOpenOptionsCleaned; @@ -2842,6 +2845,7 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename, poDS = poOvrDS; } } + VSIErrorReset(); CSLDestroy(papszOpenOptionsCleaned); return (GDALDatasetH) poDS; @@ -2862,15 +2866,22 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename, if( nOpenFlags & GDAL_OF_VERBOSE_ERROR ) { - if( oOpenInfo.bStatOK ) - CPLError( CE_Failure, CPLE_OpenFailed, - "`%s' not recognized as a supported file format.\n", - pszFilename ); - else - CPLError( CE_Failure, CPLE_OpenFailed, - "`%s' does not exist in the file system,\n" - "and is not recognized as a supported dataset name.\n", - pszFilename ); + // Check to see if there was a filesystem error, and report it if so. + // If not, return a more generic error. + if(!VSIToCPLError(CE_Failure, CPLE_OpenFailed)) { + if( oOpenInfo.bStatOK ) + CPLError( CE_Failure, CPLE_OpenFailed, + "`%s' not recognized as a supported file format.\n", + pszFilename ); + else { + // If Stat failed and no VSI error was set, + // assume it is because the file did not exist on the filesystem. + CPLError( CE_Failure, CPLE_OpenFailed, + "`%s' does not exist in the file system,\n" + "and is not recognized as a supported dataset name.\n", + pszFilename ); + } + } } int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP ); @@ -2889,7 +2900,7 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename, * * This function works the same as GDALOpen(), but allows the sharing of * GDALDataset handles for a dataset with other callers to GDALOpenShared(). - * + * * In particular, GDALOpenShared() will first consult it's list of currently * open and shared GDALDataset's, and if the GetDescription() name for one * exactly matches the pszFilename passed to GDALOpenShared() it will be @@ -2912,17 +2923,17 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename, * * @param pszFilename the name of the file to access. In the case of * exotic drivers this may not refer to a physical file, but instead contain - * information for the driver on how to access a dataset. It should be in + * information for the driver on how to access a dataset. It should be in * UTF-8 encoding. * * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many * drivers support only read only access. * * @return A GDALDatasetH handle or NULL on failure. For C++ applications - * this handle can be cast to a GDALDataset *. + * this handle can be cast to a GDALDataset *. */ -GDALDatasetH CPL_STDCALL +GDALDatasetH CPL_STDCALL GDALOpenShared( const char *pszFilename, GDALAccess eAccess ) { VALIDATE_POINTER1( pszFilename, "GDALOpenShared", NULL ); @@ -2939,14 +2950,14 @@ GDALOpenShared( const char *pszFilename, GDALAccess eAccess ) /************************************************************************/ /** - * \brief Close GDAL dataset. + * \brief Close GDAL dataset. * * For non-shared datasets (opened with GDALOpen()) the dataset is closed - * using the C++ "delete" operator, recovering all dataset related resources. - * For shared datasets (opened with GDALOpenShared()) the dataset is + * using the C++ "delete" operator, recovering all dataset related resources. + * For shared datasets (opened with GDALOpenShared()) the dataset is * dereferenced, and closed only if the referenced count has dropped below 1. * - * @param hDS The dataset to close. May be cast from a "GDALDataset *". + * @param hDS The dataset to close. May be cast from a "GDALDataset *". */ void CPL_STDCALL GDALClose( GDALDatasetH hDS ) @@ -2994,10 +3005,10 @@ static int GDALDumpOpenSharedDatasetsForeach(void* elt, void* user_data) pszDriverName = poDS->GetDriver()->GetDescription(); poDS->Reference(); - CPL_IGNORE_RET_VAL(VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n", - poDS->Dereference(), + CPL_IGNORE_RET_VAL(VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n", + poDS->Dereference(), poDS->GetShared() ? 'S' : 'N', - pszDriverName, + pszDriverName, (int)psStruct->nPID, poDS->GetRasterXSize(), poDS->GetRasterYSize(), @@ -3023,10 +3034,10 @@ static int GDALDumpOpenDatasetsForeach(GDALDataset* poDS, FILE *fp) pszDriverName = poDS->GetDriver()->GetDescription(); poDS->Reference(); - CPL_IGNORE_RET_VAL(VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n", - poDS->Dereference(), + CPL_IGNORE_RET_VAL(VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n", + poDS->Dereference(), poDS->GetShared() ? 'S' : 'N', - pszDriverName, + pszDriverName, -1, poDS->GetRasterXSize(), poDS->GetRasterYSize(), @@ -3039,11 +3050,11 @@ static int GDALDumpOpenDatasetsForeach(GDALDataset* poDS, FILE *fp) /** * \brief List open datasets. * - * Dumps a list of all open datasets (shared or not) to the indicated + * Dumps a list of all open datasets (shared or not) to the indicated * text file (may be stdout or stderr). This function is primarily intended - * to assist in debugging "dataset leaks" and reference counting issues. - * The information reported includes the dataset name, referenced count, - * shared status, driver name, size, and band count. + * to assist in debugging "dataset leaks" and reference counting issues. + * The information reported includes the dataset name, referenced count, + * shared status, driver name, size, and band count. */ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp ) @@ -3084,21 +3095,21 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp ) * indicated window on the dataset into the indicated buffer. The parameters * for windowing, buffer size, buffer type and buffer organization are similar * to those for GDALDataset::RasterIO(); however, this call only launches - * the request and filling the buffer is accomplished via calls to + * the request and filling the buffer is accomplished via calls to * GetNextUpdatedRegion() on the return GDALAsyncReader session object. - * + * * Once all processing for the created session is complete, or if no further * refinement of the request is required, the GDALAsyncReader object should - * be destroyed with the GDALDataset::EndAsyncReader() method. - * - * Note that the data buffer (pData) will potentially continue to be + * be destroyed with the GDALDataset::EndAsyncReader() method. + * + * Note that the data buffer (pData) will potentially continue to be * updated as long as the session lives, but it is not deallocated when * the session (GDALAsyncReader) is destroyed with EndAsyncReader(). It - * should be deallocated by the application at that point. + * should be deallocated by the application at that point. * - * Additional information on asynchronous IO in GDAL may be found at: + * Additional information on asynchronous IO in GDAL may be found at: * http://trac.osgeo.org/gdal/wiki/rfc24_progressive_data_support - * + * * This method is the same as the C GDALBeginAsyncReader() function. * * @param nXOff The pixel offset to the top left corner of the region @@ -3111,9 +3122,9 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp ) * * @param nYSize The height of the region of the band to be accessed in lines. * - * @param pBuf The buffer into which the data should be read. This buffer must - * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType. - * It is organized in left to right,top to bottom pixel order. Spacing is + * @param pBuf The buffer into which the data should be read. This buffer must + * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType. + * It is organized in left to right,top to bottom pixel order. Spacing is * controlled by the nPixelSpace, and nLineSpace parameters. * * @param nBufXSize the width of the buffer image into which the desired region @@ -3126,10 +3137,10 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp ) * pixel values will automatically be translated to/from the GDALRasterBand * data type as needed. * - * @param nBandCount the number of bands being read or written. + * @param nBandCount the number of bands being read or written. * * @param panBandMap the list of nBandCount band numbers being read/written. - * Note band numbers are 1 based. This may be NULL to select the first + * Note band numbers are 1 based. This may be NULL to select the first * nBandCount bands. * * @param nPixelSpace The byte offset from the start of one pixel value in @@ -3141,17 +3152,17 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp ) * eBufType * nBufXSize is used. * * @param nBandSpace the byte offset from the start of one bands data to the - * start of the next. If defaulted (zero) the value will be + * start of the next. If defaulted (zero) the value will be * nLineSpace * nBufYSize implying band sequential organization - * of the data buffer. + * of the data buffer. * * @param papszOptions Driver specific control options in a string list or NULL. * Consult driver documentation for options supported. - * + * * @return The GDALAsyncReader object representing the request. */ -GDALAsyncReader* +GDALAsyncReader* GDALDataset::BeginAsyncReader(int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, @@ -3164,7 +3175,7 @@ GDALDataset::BeginAsyncReader(int nXOff, int nYOff, // See gdaldefaultasync.cpp return - GDALGetDefaultAsyncReader( this, + GDALGetDefaultAsyncReader( this, nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap, @@ -3176,7 +3187,7 @@ GDALDataset::BeginAsyncReader(int nXOff, int nYOff, /* GDALBeginAsyncReader() */ /************************************************************************/ -GDALAsyncReaderH CPL_STDCALL +GDALAsyncReaderH CPL_STDCALL GDALBeginAsyncReader(GDALDatasetH hDS, int xOff, int yOff, int xSize, int ySize, void *pBuf, @@ -3205,10 +3216,10 @@ GDALBeginAsyncReader(GDALDatasetH hDS, int xOff, int yOff, /** * End asynchronous request. * - * This method destroys an asynchronous io request and recovers all + * This method destroys an asynchronous io request and recovers all * resources associated with it. - * - * This method is the same as the C function GDALEndAsyncReader(). + * + * This method is the same as the C function GDALEndAsyncReader(). * * @param poARIO pointer to a GDALAsyncReader */ @@ -3225,7 +3236,7 @@ void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsyncRea { VALIDATE_POINTER0( hDS, "GDALDataset" ); VALIDATE_POINTER0( hAsyncReaderH, "GDALAsyncReader" ); - ((GDALDataset *) hDS) -> EndAsyncReader((GDALAsyncReader *)hAsyncReaderH); + ((GDALDataset *) hDS) -> EndAsyncReader((GDALAsyncReader *)hAsyncReaderH); } /************************************************************************/ @@ -3325,7 +3336,7 @@ const char* GDALDataset::GetDriverName() This function should only be used to deallocate OGRLayers resulting from an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a - results set before destroying the GDALDataset may cause errors. + results set before destroying the GDALDataset may cause errors. This function is the same as the C++ method GDALDataset::ReleaseResultSet() @@ -3334,7 +3345,7 @@ const char* GDALDataset::GetDriverName() @param hDS the dataset handle. @param hLayer the result of a previous ExecuteSQL() call. -*/ +*/ void GDALDatasetReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer ) { @@ -3415,7 +3426,7 @@ int GDALDatasetGetLayerCount( GDALDatasetH hDS ) /** \brief Fetch a layer by index. - The returned layer remains owned by the + The returned layer remains owned by the GDALDataset and should not be deleted by the application. This function is the same as the C++ method GDALDataset::GetLayer() @@ -3443,7 +3454,7 @@ OGRLayerH GDALDatasetGetLayer( GDALDatasetH hDS, int iLayer ) /** \brief Fetch a layer by name. - The returned layer remains owned by the + The returned layer remains owned by the GDALDataset and should not be deleted by the application. This function is the same as the C++ method GDALDataset::GetLayerByName() @@ -3479,7 +3490,7 @@ OGRLayerH GDALDatasetGetLayerByName( GDALDatasetH hDS, const char *pszName ) @since GDAL 2.0 @param hDS the dataset handle. - @param iLayer the index of the layer to delete. + @param iLayer the index of the layer to delete. @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting layers is not supported for this datasource. @@ -3502,32 +3513,32 @@ OGRErr GDALDatasetDeleteLayer( GDALDatasetH hDS, int iLayer ) The papszOptions argument can be used to control driver specific creation options. These options are -normally documented in the format specific documentation. +normally documented in the format specific documentation. In GDAL 2.0, drivers should extend the ICreateLayer() method and not CreateLayer(). CreateLayer() adds validation of layer creation options, before delegating the actual work to ICreateLayer(). This method is the same as the C function GDALDatasetCreateLayer() and the - deprecated OGR_DS_CreateLayer(). + deprecated OGR_DS_CreateLayer(). In GDAL 1.X, this method used to be in the OGRDataSource class. - @param pszName the name for the new layer. This should ideally not + @param pszName the name for the new layer. This should ideally not match any existing layer on the datasource. @param poSpatialRef the coordinate system to use for the new layer, or NULL if -no coordinate system is available. +no coordinate system is available. @param eGType the geometry type for the layer. Use wkbUnknown if there -are no constraints on the types geometry to be written. +are no constraints on the types geometry to be written. @param papszOptions a StringList of name=value options. Options are driver specific. - @return NULL is returned on failure, or a new OGRLayer handle on success. + @return NULL is returned on failure, or a new OGRLayer handle on success. Example: \code -#include "gdal.h" +#include "gdal.h" #include "cpl_string.h" ... @@ -3548,7 +3559,7 @@ specific. if( poLayer == NULL ) { ... - } + } \endcode */ @@ -3588,28 +3599,28 @@ OGRLayer *GDALDataset::CreateLayer( const char * pszName, The papszOptions argument can be used to control driver specific creation options. These options are -normally documented in the format specific documentation. +normally documented in the format specific documentation. This method is the same as the C++ method GDALDataset::CreateLayer(). @since GDAL 2.0 @param hDS the dataset handle - @param pszName the name for the new layer. This should ideally not + @param pszName the name for the new layer. This should ideally not match any existing layer on the datasource. @param hSpatialRef the coordinate system to use for the new layer, or NULL if -no coordinate system is available. +no coordinate system is available. @param eGType the geometry type for the layer. Use wkbUnknown if there -are no constraints on the types geometry to be written. +are no constraints on the types geometry to be written. @param papszOptions a StringList of name=value options. Options are driver specific. - @return NULL is returned on failure, or a new OGRLayer handle on success. + @return NULL is returned on failure, or a new OGRLayer handle on success. Example: \code -#include "gdal.h" +#include "gdal.h" #include "cpl_string.h" ... @@ -3630,11 +3641,11 @@ specific. if( poLayer == NULL ) { ... - } + } \endcode */ -OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS, +OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS, const char * pszName, OGRSpatialReferenceH hSpatialRef, OGRwkbGeometryType eGType, @@ -3648,7 +3659,7 @@ OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS, CPLError ( CE_Failure, CPLE_ObjectNull, "Name was NULL in GDALDatasetCreateLayer"); return NULL; } - return (OGRLayerH) ((GDALDataset *)hDS)->CreateLayer( + return (OGRLayerH) ((GDALDataset *)hDS)->CreateLayer( pszName, (OGRSpatialReference *) hSpatialRef, eGType, papszOptions ); } @@ -3671,7 +3682,7 @@ OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS, @since GDAL 2.0 - @param hDS the dataset handle. + @param hDS the dataset handle. @param hSrcLayer source layer. @param pszNewName the name of the layer to create. @param papszOptions a StringList of name=value options. Options are driver @@ -3679,7 +3690,7 @@ OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS, @return an handle to the layer, or NULL if an error occurs. */ -OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS, +OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS, OGRLayerH hSrcLayer, const char *pszNewName, char **papszOptions ) @@ -3688,8 +3699,8 @@ OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS, VALIDATE_POINTER1( hSrcLayer, "GDALDatasetCopyLayer", NULL ); VALIDATE_POINTER1( pszNewName, "GDALDatasetCopyLayer", NULL ); - return (OGRLayerH) - ((GDALDataset *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer, + return (OGRLayerH) + ((GDALDataset *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer, pszNewName, papszOptions ); } @@ -3698,14 +3709,14 @@ OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS, /************************************************************************/ /** - \brief Execute an SQL statement against the data store. + \brief Execute an SQL statement against the data store. The result of an SQL query is either NULL for statements that are in error, or that have no results set, or an OGRLayer pointer representing a results set from the query. Note that this OGRLayer is in addition to the layers - in the data store and must be destroyed with + in the data store and must be destroyed with ReleaseResultSet() before the dataset is closed - (destroyed). + (destroyed). This method is the same as the C++ method GDALDataset::ExecuteSQL() @@ -3719,7 +3730,7 @@ OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS, @since GDAL 2.0 @param hDS the dataset handle. - @param pszStatement the SQL statement to execute. + @param pszStatement the SQL statement to execute. @param hSpatialFilter geometry which represents a spatial filter. Can be NULL. @param pszDialect allows control of the statement dialect. If set to NULL, the OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine, @@ -3731,7 +3742,7 @@ can also be used. */ -OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS, +OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS, const char *pszStatement, OGRGeometryH hSpatialFilter, const char *pszDialect ) @@ -3739,7 +3750,7 @@ OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS, { VALIDATE_POINTER1( hDS, "GDALDatasetExecuteSQL", NULL ); - return (OGRLayerH) + return (OGRLayerH) ((GDALDataset *)hDS)->ExecuteSQL( pszStatement, (OGRGeometry *) hSpatialFilter, pszDialect ); @@ -3834,7 +3845,7 @@ int GDALDataset::ValidateLayerCreationOptions( const char* const* papszLCO ) const char *pszOptionList = GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST ); if( pszOptionList == NULL && poDriver != NULL ) { - pszOptionList = + pszOptionList = poDriver->GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST ); } CPLString osDataset; @@ -3855,7 +3866,7 @@ This method is the same as the C function OGRReleaseDataSource(). @deprecated. In GDAL 2, use GDALClose() instead -@return OGRERR_NONE on success or an error code. +@return OGRERR_NONE on success or an error code. */ OGRErr GDALDataset::Release() @@ -3928,18 +3939,18 @@ This method is reserved to implementation by drivers. The papszOptions argument can be used to control driver specific creation options. These options are -normally documented in the format specific documentation. +normally documented in the format specific documentation. - @param pszName the name for the new layer. This should ideally not + @param pszName the name for the new layer. This should ideally not match any existing layer on the datasource. @param poSpatialRef the coordinate system to use for the new layer, or NULL if -no coordinate system is available. +no coordinate system is available. @param eGType the geometry type for the layer. Use wkbUnknown if there -are no constraints on the types geometry to be written. +are no constraints on the types geometry to be written. @param papszOptions a StringList of name=value options. Options are driver specific. - @return NULL is returned on failure, or a new OGRLayer handle on success. + @return NULL is returned on failure, or a new OGRLayer handle on success. @since GDAL 2.0 */ @@ -3990,8 +4001,8 @@ OGRLayer *GDALDataset::ICreateLayer( const char * pszName, @return an handle to the layer, or NULL if an error occurs. */ -OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer, - const char *pszNewName, +OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer, + const char *pszNewName, char **papszOptions ) { @@ -4003,7 +4014,7 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer, /* -------------------------------------------------------------------- */ if( !TestCapability( ODsCCreateLayer ) ) { - CPLError( CE_Failure, CPLE_NotSupported, + CPLError( CE_Failure, CPLE_NotSupported, "This datasource does not support creation of layers." ); return NULL; } @@ -4056,7 +4067,7 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer, /* returns NULL until a field has been added */ OGRFeatureDefn* poDstFDefn = poDstLayer->GetLayerDefn(); if (poDstFDefn) - nDstFieldCount = poDstFDefn->GetFieldCount(); + nDstFieldCount = poDstFDefn->GetFieldCount(); for( iField = 0; iField < nSrcFieldCount; iField++ ) { OGRFieldDefn* poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField); @@ -4339,7 +4350,7 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer, In GDAL 1.X, this method used to be in the OGRDataSource class. - @param iLayer the index of the layer to delete. + @param iLayer the index of the layer to delete. @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting layers is not supported for this datasource. @@ -4362,7 +4373,7 @@ OGRErr GDALDataset::DeleteLayer( int iLayer ) /** \brief Fetch a layer by name. - The returned layer remains owned by the + The returned layer remains owned by the GDALDataset and should not be deleted by the application. This method is the same as the C function GDALDatasetGetLayerByName() and the @@ -4424,14 +4435,14 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand ) /* -------------------------------------------------------------------- */ /* Do some general syntax checking. */ /* -------------------------------------------------------------------- */ - if( CSLCount(papszTokens) != 6 + if( CSLCount(papszTokens) != 6 || !EQUAL(papszTokens[0],"CREATE") || !EQUAL(papszTokens[1],"INDEX") || !EQUAL(papszTokens[2],"ON") || !EQUAL(papszTokens[4],"USING") ) { CSLDestroy( papszTokens ); - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "Syntax error in CREATE INDEX command.\n" "Was '%s'\n" "Should be of form 'CREATE INDEX ON USING '", @@ -4460,7 +4471,7 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand ) if( poLayer == NULL ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "CREATE INDEX ON failed, no such layer as `%s'.", papszTokens[3] ); CSLDestroy( papszTokens ); @@ -4473,7 +4484,7 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand ) /* -------------------------------------------------------------------- */ if( poLayer->GetIndex() == NULL ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "CREATE INDEX ON not supported by this driver." ); CSLDestroy( papszTokens ); return OGRERR_FAILURE; @@ -4493,7 +4504,7 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand ) if( i >= poLayer->GetLayerDefn()->GetFieldCount() ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.", pszSQLCommand ); return OGRERR_FAILURE; @@ -4537,11 +4548,11 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand ) if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6) || !EQUAL(papszTokens[0],"DROP") || !EQUAL(papszTokens[1],"INDEX") - || !EQUAL(papszTokens[2],"ON") + || !EQUAL(papszTokens[2],"ON") || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4],"USING")) ) { CSLDestroy( papszTokens ); - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "Syntax error in DROP INDEX command.\n" "Was '%s'\n" "Should be of form 'DROP INDEX ON
[USING ]'", @@ -4570,7 +4581,7 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand ) if( poLayer == NULL ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "CREATE INDEX ON failed, no such layer as `%s'.", papszTokens[3] ); CSLDestroy( papszTokens ); @@ -4583,7 +4594,7 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand ) /* -------------------------------------------------------------------- */ if( poLayer->GetIndex() == NULL ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "Indexes not supported by this driver." ); CSLDestroy( papszTokens ); return OGRERR_FAILURE; @@ -4630,7 +4641,7 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand ) if( i >= poLayer->GetLayerDefn()->GetFieldCount() ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.", pszSQLCommand ); return OGRERR_FAILURE; @@ -4666,7 +4677,7 @@ OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand ) || !EQUAL(papszTokens[1],"TABLE") ) { CSLDestroy( papszTokens ); - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "Syntax error in DROP TABLE command.\n" "Was '%s'\n" "Should be of form 'DROP TABLE
'", @@ -4691,7 +4702,7 @@ OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand ) if( poLayer == NULL ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "DROP TABLE failed, no such layer as `%s'.", papszTokens[2] ); CSLDestroy( papszTokens ); @@ -5168,14 +5179,14 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand ) /************************************************************************/ /** - \brief Execute an SQL statement against the data store. + \brief Execute an SQL statement against the data store. The result of an SQL query is either NULL for statements that are in error, or that have no results set, or an OGRLayer pointer representing a results set from the query. Note that this OGRLayer is in addition to the layers - in the data store and must be destroyed with + in the data store and must be destroyed with ReleaseResultSet() before the dataset is closed - (destroyed). + (destroyed). This method is the same as the C function GDALDatasetExecuteSQL() and the deprecated OGR_DS_ExecuteSQL(). @@ -5189,7 +5200,7 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand ) In GDAL 1.X, this method used to be in the OGRDataSource class. - @param pszStatement the SQL statement to execute. + @param pszStatement the SQL statement to execute. @param poSpatialFilter geometry which represents a spatial filter. Can be NULL. @param pszDialect allows control of the statement dialect. If set to NULL, the OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine, @@ -5458,12 +5469,12 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo, if( psTableDef->data_source != NULL ) { - poTableDS = (GDALDataset *) + poTableDS = (GDALDataset *) OGROpenShared( psTableDef->data_source, FALSE, NULL ); if( poTableDS == NULL ) { if( strlen(CPLGetLastErrorMsg()) == 0 ) - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "Unable to open secondary datasource\n" "`%s' required by JOIN.", psTableDef->data_source ); @@ -5483,7 +5494,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo, if( poSrcLayer == NULL ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "SELECT from table %s failed, no such table/featureclass.", psTableDef->table_name ); @@ -5506,11 +5517,11 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo, psParseInfo->sFieldList.count = 0; psParseInfo->sFieldList.names = (char **) CPLMalloc( sizeof(char *) * (nFieldCount+SPECIAL_FIELD_COUNT) ); - psParseInfo->sFieldList.types = (swq_field_type *) + psParseInfo->sFieldList.types = (swq_field_type *) CPLMalloc( sizeof(swq_field_type) * (nFieldCount+SPECIAL_FIELD_COUNT) ); - psParseInfo->sFieldList.table_ids = (int *) + psParseInfo->sFieldList.table_ids = (int *) CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) ); - psParseInfo->sFieldList.ids = (int *) + psParseInfo->sFieldList.ids = (int *) CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) ); for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ ) @@ -5521,7 +5532,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo, if( psTableDef->data_source != NULL ) { - poTableDS = (GDALDataset *) + poTableDS = (GDALDataset *) OGROpenShared( psTableDef->data_source, FALSE, NULL ); CPLAssert( poTableDS != NULL ); poTableDS->Dereference(); @@ -5529,7 +5540,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo, poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name ); - for( iField = 0; + for( iField = 0; iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++ ) { @@ -5572,7 +5583,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo, { nFIDIndex = psParseInfo->sFieldList.count; - for( iField = 0; + for( iField = 0; iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount(); iField++ ) { @@ -5641,7 +5652,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo, This method should only be used to deallocate OGRLayers resulting from an ExecuteSQL() call on the same GDALDataset. Failure to deallocate a - results set before destroying the GDALDataset may cause errors. + results set before destroying the GDALDataset may cause errors. This method is the same as the C function GDALDatasetReleaseResultSet() and the deprecated OGR_DS_ReleaseResultSet(). @@ -5768,7 +5779,7 @@ int GDALDataset::GetLayerCount() /** \brief Fetch a layer by index. - The returned layer remains owned by the + The returned layer remains owned by the GDALDataset and should not be deleted by the application. This method is the same as the C function GDALDatasetGetLayer() and the @@ -5942,9 +5953,9 @@ OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce) /** \brief For datasources which support transactions, CommitTransaction commits a transaction. - If no transaction is active, or the commit fails, will return - OGRERR_FAILURE. Datasources which do not support transactions will - always return OGRERR_UNSUPPORTED_OPERATION. + If no transaction is active, or the commit fails, will return + OGRERR_FAILURE. Datasources which do not support transactions will + always return OGRERR_UNSUPPORTED_OPERATION. Depending on drivers, this may or may not abort layer sequential readings that are active. @@ -5966,9 +5977,9 @@ OGRErr GDALDataset::CommitTransaction() /** \brief For datasources which support transactions, CommitTransaction commits a transaction. - If no transaction is active, or the commit fails, will return - OGRERR_FAILURE. Datasources which do not support transactions will - always return OGRERR_UNSUPPORTED_OPERATION. + If no transaction is active, or the commit fails, will return + OGRERR_FAILURE. Datasources which do not support transactions will + always return OGRERR_UNSUPPORTED_OPERATION. Depending on drivers, this may or may not abort layer sequential readings that are active. @@ -5995,10 +6006,10 @@ OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS) /************************************************************************/ /** - \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction. - If no transaction is active, or the rollback fails, will return + \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction. + If no transaction is active, or the rollback fails, will return OGRERR_FAILURE. Datasources which do not support transactions will - always return OGRERR_UNSUPPORTED_OPERATION. + always return OGRERR_UNSUPPORTED_OPERATION. This function is the same as the C function GDALDatasetRollbackTransaction(). @@ -6015,10 +6026,10 @@ OGRErr GDALDataset::RollbackTransaction() /************************************************************************/ /** - \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction. - If no transaction is active, or the rollback fails, will return + \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction. + If no transaction is active, or the rollback fails, will return OGRERR_FAILURE. Datasources which do not support transactions will - always return OGRERR_UNSUPPORTED_OPERATION. + always return OGRERR_UNSUPPORTED_OPERATION. This function is the same as the C++ method GDALDataset::RollbackTransaction(). diff --git a/gdal/gcore/gdalopeninfo.cpp b/gdal/gcore/gdalopeninfo.cpp index 30bd7ef5bc78..fce0a68f4c62 100644 --- a/gdal/gcore/gdalopeninfo.cpp +++ b/gdal/gcore/gdalopeninfo.cpp @@ -51,6 +51,7 @@ GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn, char **papszSiblingsIn ) { + /* -------------------------------------------------------------------- */ /* Ensure that C: is treated as C:\ so we can stat it on */ /* Windows. Similar to what is done in CPLStat(). */ @@ -75,8 +76,8 @@ GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn, nHeaderBytes = 0; nHeaderBytesTried = 0; pabyHeader = NULL; - bIsDirectory = FALSE; bStatOK = FALSE; + bIsDirectory = FALSE; nOpenFlags = nOpenFlagsIn; eAccess = (nOpenFlags & GDAL_OF_UPDATE) ? GA_Update : GA_ReadOnly; fpL = NULL; @@ -124,20 +125,23 @@ GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn, if( bPotentialDirectory ) { + int nStatFlags = VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG; + if(nOpenFlagsIn & GDAL_OF_VERBOSE_ERROR) + nStatFlags |= VSI_STAT_SET_ERROR_FLAG; + /* For those special files, opening them with VSIFOpenL() might result */ /* in content, even if they should be considered as directories, so */ /* use stat */ - if( VSIStatExL( pszFilename, &sStat, - VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 ) - { + if(VSIStatExL( pszFilename, &sStat, nStatFlags) == 0) { bStatOK = TRUE; if( VSI_ISDIR( sStat.st_mode ) ) bIsDirectory = TRUE; } } - if( !bIsDirectory ) - fpL = VSIFOpenL( pszFilename, (eAccess == GA_Update) ? "r+b" : "rb" ); + if( !bIsDirectory ) { + fpL = VSIFOpenExL( pszFilename, (eAccess == GA_Update) ? "r+b" : "rb", (nOpenFlagsIn & GDAL_OF_VERBOSE_ERROR) > 0); + } if( fpL != NULL ) { bStatOK = TRUE; @@ -161,7 +165,7 @@ GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn, } else if( !bStatOK ) { - if( VSIStatExL( pszFilename, &sStat, + if( !bPotentialDirectory && VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 ) { bStatOK = TRUE; @@ -254,6 +258,7 @@ char** GDALOpenInfo::GetSiblingFiles() CPLString osDir = CPLGetDirname( pszFilename ); const int nMaxFiles = atoi(CPLGetConfigOption("GDAL_READDIR_LIMIT_ON_OPEN", "1000")); + papszSiblingFiles = VSIReadDirEx( osDir, nMaxFiles ); if( nMaxFiles > 0 && CSLCount(papszSiblingFiles) > nMaxFiles ) { diff --git a/gdal/port/GNUmakefile b/gdal/port/GNUmakefile index af135afd0cce..53f10b81bc6e 100644 --- a/gdal/port/GNUmakefile +++ b/gdal/port/GNUmakefile @@ -7,11 +7,11 @@ else include GDALmake.opt endif -ifeq ($(LIBZ_SETTING),internal) -XTRA_OPT = -I../frmts/zlib -else -XTRA_OPT = -endif +ifeq ($(LIBZ_SETTING),internal) +XTRA_OPT = -I../frmts/zlib +else +XTRA_OPT = +endif CPPFLAGS := $(CPPFLAGS) $(CURL_INC) $(XTRA_OPT) @@ -27,7 +27,7 @@ OBJ = cpl_conv.o cpl_error.o cpl_string.o cplgetsymbol.o cplstringlist.o \ cpl_base64.o cpl_vsil_curl.o cpl_vsil_curl_streaming.o \ cpl_vsil_cache.o cpl_xml_validate.o cpl_spawn.o \ cpl_google_oauth2.o cpl_progress.o cpl_virtualmem.o cpl_worker_thread_pool.o \ - cpl_vsil_crypt.o cpl_sha256.o cpl_aws.o + cpl_vsil_crypt.o cpl_sha256.o cpl_aws.o cpl_vsi_error.o ifeq ($(ODBC_SETTING),yes) OBJ := $(OBJ) cpl_odbc.o @@ -66,5 +66,5 @@ clean: install: for f in *.h ; do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; done -xmlreformat: xmlreformat.o +xmlreformat: xmlreformat.o $(CXX) $(CXXFLAGS) xmlreformat.o $(CONFIG_LIBS) -o xmlreformat diff --git a/gdal/port/cpl_aws.cpp b/gdal/port/cpl_aws.cpp index 382abd3937ae..f43cf0dcfad2 100644 --- a/gdal/port/cpl_aws.cpp +++ b/gdal/port/cpl_aws.cpp @@ -29,6 +29,7 @@ ****************************************************************************/ #include "cpl_aws.h" +#include "cpl_vsi_error.h" #include "cpl_sha256.h" #include "cpl_time.h" #include "cpl_minixml.h" @@ -405,14 +406,14 @@ VSIS3HandleHelper* VSIS3HandleHelper::BuildFromURI(const char* pszURI, CPLString osSecretAccessKey = CPLGetConfigOption("AWS_SECRET_ACCESS_KEY", ""); if( osSecretAccessKey.size() == 0 ) { - CPLError(CE_Failure, CPLE_AppDefined, + VSIError(VSIE_AWSInvalidCredentials, "AWS_SECRET_ACCESS_KEY configuration option not defined"); return NULL; } CPLString osAccessKeyId = CPLGetConfigOption("AWS_ACCESS_KEY_ID", ""); if( osAccessKeyId.size() == 0 ) { - CPLError(CE_Failure, CPLE_AppDefined, + VSIError(VSIE_AWSInvalidCredentials, "AWS_ACCESS_KEY_ID configuration option not defined"); return NULL; } @@ -492,7 +493,7 @@ struct curl_slist* VSIS3HandleHelper::GetCurlHeaders(const CPLString& osVerb, osXAMZContentSHA256, osXAMZDate); - struct curl_slist *headers=NULL; + struct curl_slist *headers=NULL; headers = curl_slist_append(headers, CPLSPrintf("x-amz-date: %s", osXAMZDate.c_str())); headers = curl_slist_append(headers, @@ -509,7 +510,7 @@ struct curl_slist* VSIS3HandleHelper::GetCurlHeaders(const CPLString& osVerb, /* CanRestartOnError() */ /************************************************************************/ -bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg) +bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetError) { #ifdef DEBUG_VERBOSE CPLDebug("S3", "%s", pszErrorMsg); @@ -517,14 +518,14 @@ bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg) if( !STARTS_WITH(pszErrorMsg, "psHandlerStack != NULL && - EQUAL(CPLGetConfigOption( "CPL_ACCUM_ERROR_MSG", "" ), "ON")) - { - nPreviousSize = static_cast(strlen(psCtx->szLastErrMsg)); - if (nPreviousSize) - { - if (nPreviousSize + 1 + 1 >= psCtx->nLastErrMsgMax) - { - psCtx->nLastErrMsgMax *= 3; - psCtx = static_cast ( - CPLRealloc( psCtx, - sizeof(CPLErrorContext) - - DEFAULT_LAST_ERR_MSG_SIZE - + psCtx->nLastErrMsgMax + 1)); - CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE ); - } - psCtx->szLastErrMsg[nPreviousSize] = '\n'; - psCtx->szLastErrMsg[nPreviousSize+1] = '0'; - nPreviousSize ++; - } - } - int nPR; while( ((nPR = CPLvsnprintf( psCtx->szLastErrMsg+nPreviousSize, @@ -346,7 +324,7 @@ void CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, /* -------------------------------------------------------------------- */ if( psCtx->psHandlerStack != NULL ) { - psCtx->psHandlerStack->pfnHandler(eErrClass, err_no, + psCtx->psHandlerStack->pfnHandler(eErrClass, err_no, psCtx->szLastErrMsg); } else @@ -461,7 +439,7 @@ static int CPLGetProcessMemorySize() * * Categories are usually an identifier for the subsystem producing the * error. For instance "GDAL" might be used for the GDAL core, and "TIFF" - * for messages from the TIFF translator. + * for messages from the TIFF translator. * * @param pszCategory name of the debugging message category. * @param pszFormat printf() style format string for message to display. @@ -515,7 +493,7 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... ) { strcpy( pszMessage, VSICTime( VSITime(NULL) ) ); - // On windows anyway, ctime puts a \n at the end, but I'm not + // On windows anyway, ctime puts a \n at the end, but I'm not // convinced this is standard behaviour, so we'll get rid of it // carefully @@ -550,7 +528,7 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... ) va_list args; va_start(args, pszFormat); - CPLvsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage), + CPLvsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage), pszFormat, args); va_end(args); @@ -746,7 +724,7 @@ const char* CPL_STDCALL CPLGetLastErrorMsg() /* CPLDefaultErrorHandler() */ /************************************************************************/ -void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError, +void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError, const char * pszErrorMsg ) { @@ -792,13 +770,13 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError, else fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg ); - if (eErrClass != CE_Debug - && nMaxErrors > 0 + if (eErrClass != CE_Debug + && nMaxErrors > 0 && nCount == nMaxErrors ) { - fprintf( fpLog, + fprintf( fpLog, "More than %d errors or warnings have been reported. " - "No more will be reported from now.\n", + "No more will be reported from now.\n", nMaxErrors ); } @@ -809,7 +787,7 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError, /* CPLQuietErrorHandler() */ /************************************************************************/ -void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , CPLErrorNum nError, +void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , CPLErrorNum nError, const char * pszErrorMsg ) { @@ -821,7 +799,7 @@ void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , CPLErrorNum nError, /* CPLLoggingErrorHandler() */ /************************************************************************/ -void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError, +void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError, const char * pszErrorMsg ) { @@ -917,9 +895,9 @@ void CPLTurnFailureIntoWarning( int bOn ) **********************************************************************/ /** - * Install custom error handle with user's data. This method is - * essentially CPLSetErrorHandler with an added pointer to pUserData. - * The pUserData is not returned in the CPLErrorHandler, however, and + * Install custom error handle with user's data. This method is + * essentially CPLSetErrorHandler with an added pointer to pUserData. + * The pUserData is not returned in the CPLErrorHandler, however, and * must be fetched via CPLGetLastErrorUserData * * @param pfnErrorHandlerNew new error handler function. @@ -927,8 +905,8 @@ void CPLTurnFailureIntoWarning( int bOn ) * @return returns the previously installed error handler. */ -CPLErrorHandler CPL_STDCALL -CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, +CPLErrorHandler CPL_STDCALL +CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, void* pUserData ) { CPLErrorContext *psCtx = CPLGetErrorContext(); @@ -979,7 +957,7 @@ CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, * * * Pass NULL to come back to the default behavior. The default behaviour - * (CPLDefaultErrorHandler()) is to write the message to stderr. + * (CPLDefaultErrorHandler()) is to write the message to stderr. * * The msg will be a partially formatted error message not containing the * "ERROR %d:" portion emitted by the default handler. Message formatting @@ -1001,12 +979,12 @@ CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, * Generally speaking CPLSetErrorHandler() would be used to set a desired * global error handler, while CPLPushErrorHandler() would be used to install * a temporary local error handler, such as CPLQuietErrorHandler() to suppress - * error reporting in a limited segment of code. + * error reporting in a limited segment of code. * * @param pfnErrorHandlerNew new error handler function. * @return returns the previously installed error handler. */ -CPLErrorHandler CPL_STDCALL +CPLErrorHandler CPL_STDCALL CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew ) { return CPLSetErrorHandlerEx(pfnErrorHandlerNew, NULL); @@ -1022,7 +1000,7 @@ CPLSetErrorHandler( CPLErrorHandler pfnErrorHandlerNew ) * This pushes a new error handler on the thread-local error handler * stack. This handler will be used until removed with CPLPopErrorHandler(). * - * The CPLSetErrorHandler() docs have further information on how + * The CPLSetErrorHandler() docs have further information on how * CPLError handlers work. * * @param pfnErrorHandlerNew new error handler function. @@ -1043,16 +1021,16 @@ void CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler pfnErrorHandlerNew ) * Push a new CPLError handler with user data on the error context. * * This pushes a new error handler on the thread-local error handler - * stack. This handler will be used until removed with CPLPopErrorHandler(). + * stack. This handler will be used until removed with CPLPopErrorHandler(). * Obtain the user data back by using CPLGetErrorContext(). * - * The CPLSetErrorHandler() docs have further information on how + * The CPLSetErrorHandler() docs have further information on how * CPLError handlers work. * * @param pfnErrorHandlerNew new error handler function. - * @param pUserData User data to put on the error context. + * @param pUserData User data to put on the error context. */ -void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, +void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, void* pUserData ) { @@ -1079,10 +1057,10 @@ void CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, /** * Pop error handler off stack. * - * Discards the current error handler on the error handler stack, and restores + * Discards the current error handler on the error handler stack, and restores * the one in use before the last CPLPushErrorHandler() call. This method * has no effect if there are no error handlers on the current threads error - * handler stack. + * handler stack. */ void CPL_STDCALL CPLPopErrorHandler() diff --git a/gdal/port/cpl_error.h b/gdal/port/cpl_error.h index 52435c75cc04..3412b222f2b1 100644 --- a/gdal/port/cpl_error.h +++ b/gdal/port/cpl_error.h @@ -15,16 +15,16 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ @@ -65,17 +65,24 @@ typedef enum /* between CPLErr and CPLErrorNum */ typedef enum { - CPLE_None, - CPLE_AppDefined, - CPLE_OutOfMemory, - CPLE_FileIO, - CPLE_OpenFailed, - CPLE_IllegalArg, - CPLE_NotSupported, - CPLE_AssertionFailed, - CPLE_NoWriteAccess, - CPLE_UserInterrupt, - CPLE_ObjectNull, + CPLE_None, + CPLE_AppDefined, + CPLE_OutOfMemory, + CPLE_FileIO, + CPLE_OpenFailed, + CPLE_IllegalArg, + CPLE_NotSupported, + CPLE_AssertionFailed, + CPLE_NoWriteAccess, + CPLE_UserInterrupt, + CPLE_ObjectNull, + CPLE_HttpResponse, + CPLE_HttpResponse, + CPLE_AWSBucketNotFound, + CPLE_AWSObjectNotFound, + CPLE_AWSAccessDenied, + CPLE_AWSInvalidCredentials, + CPLE_AWSSignaturDoesNotMatch, } CPLErrorNum; #else @@ -94,6 +101,16 @@ typedef int CPLErrorNum; #define CPLE_UserInterrupt 9 #define CPLE_ObjectNull 10 +/* + * Filesystem-specific errors + */ +#define CPLE_HttpResponse 11 +#define CPLE_AWSBucketNotFound 12 +#define CPLE_AWSObjectNotFound 13 +#define CPLE_AWSAccessDenied 14 +#define CPLE_AWSInvalidCredentials 15 +#define CPLE_AWSSignaturDoesNotMatch 16 + /* 100 - 299 reserved for GDAL */ #endif diff --git a/gdal/port/cpl_multiproc.h b/gdal/port/cpl_multiproc.h index c140f2bed1c0..39b496033d19 100644 --- a/gdal/port/cpl_multiproc.h +++ b/gdal/port/cpl_multiproc.h @@ -15,16 +15,16 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ @@ -92,7 +92,7 @@ void CPL_DLL CPLDestroyCond( CPLCond *hCond ); GIntBig CPL_DLL CPLGetPID( void ); int CPL_DLL CPLCreateThread( CPLThreadFunc pfnMain, void *pArg ); CPLJoinableThread CPL_DLL* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pArg ); -void CPL_DLL CPLJoinThread(CPLJoinableThread* hJoinableThread); +void CPL_DLL CPLJoinThread(CPLJoinableThread* hJoinableThread); void CPL_DLL CPLSleep( double dfWaitInSeconds ); const char CPL_DLL *CPLGetThreadingModel( void ); @@ -196,23 +196,24 @@ class CPL_DLL CPLLockHolder /* Thread local storage. */ /* -------------------------------------------------------------------- */ -#define CTLS_RLBUFFERINFO 1 /* cpl_conv.cpp */ -#define CTLS_WIN32_COND 2 /* cpl_multiproc.cpp */ -#define CTLS_CSVTABLEPTR 3 /* cpl_csv.cpp */ -#define CTLS_CSVDEFAULTFILENAME 4 /* cpl_csv.cpp */ -#define CTLS_ERRORCONTEXT 5 /* cpl_error.cpp */ +#define CTLS_RLBUFFERINFO 1 /* cpl_conv.cpp */ +#define CTLS_WIN32_COND 2 /* cpl_multiproc.cpp */ +#define CTLS_CSVTABLEPTR 3 /* cpl_csv.cpp */ +#define CTLS_CSVDEFAULTFILENAME 4 /* cpl_csv.cpp */ +#define CTLS_ERRORCONTEXT 5 /* cpl_error.cpp */ #define CTLS_GDALDATASET_REC_PROTECT_MAP 6 /* gdaldataset.cpp */ -#define CTLS_PATHBUF 7 /* cpl_path.cpp */ -#define CTLS_UNUSED3 8 -#define CTLS_UNUSED4 9 -#define CTLS_CPLSPRINTF 10 /* cpl_string.h */ -#define CTLS_RESPONSIBLEPID 11 /* gdaldataset.cpp */ -#define CTLS_VERSIONINFO 12 /* gdal_misc.cpp */ -#define CTLS_VERSIONINFO_LICENCE 13 /* gdal_misc.cpp */ -#define CTLS_CONFIGOPTIONS 14 /* cpl_conv.cpp */ -#define CTLS_FINDFILE 15 /* cpl_findfile.cpp */ - -#define CTLS_MAX 32 +#define CTLS_PATHBUF 7 /* cpl_path.cpp */ +#define CTLS_UNUSED3 8 +#define CTLS_UNUSED4 9 +#define CTLS_CPLSPRINTF 10 /* cpl_string.h */ +#define CTLS_RESPONSIBLEPID 11 /* gdaldataset.cpp */ +#define CTLS_VERSIONINFO 12 /* gdal_misc.cpp */ +#define CTLS_VERSIONINFO_LICENCE 13 /* gdal_misc.cpp */ +#define CTLS_CONFIGOPTIONS 14 /* cpl_conv.cpp */ +#define CTLS_FINDFILE 15 /* cpl_findfile.cpp */ +#define CTLS_VSIERRORCONTEXT 16 /* cpl_vsi_error.cpp */ + +#define CTLS_MAX 32 CPL_C_START void CPL_DLL * CPLGetTLS( int nIndex ); diff --git a/gdal/port/cpl_vsi.h b/gdal/port/cpl_vsi.h index 1655241641c6..fc8815b3b4bf 100644 --- a/gdal/port/cpl_vsi.h +++ b/gdal/port/cpl_vsi.h @@ -4,7 +4,7 @@ * Project: CPL - Common Portability Library * Author: Frank Warmerdam, warmerdam@pobox.com * Purpose: Include file defining Virtual File System (VSI) functions, a - * layer over POSIX file and other system services. + * layer over POSIX file and other system services. * ****************************************************************************** * Copyright (c) 1998, Frank Warmerdam @@ -51,7 +51,6 @@ * that the default implementation is very simple. */ - /* -------------------------------------------------------------------- */ /* We need access to ``struct stat''. */ /* -------------------------------------------------------------------- */ @@ -137,6 +136,7 @@ typedef FILE VSILFILE; #endif VSILFILE CPL_DLL * VSIFOpenL( const char *, const char * ) CPL_WARN_UNUSED_RESULT; +VSILFILE CPL_DLL * VSIFOpenExL( const char *, const char *, bool ) CPL_WARN_UNUSED_RESULT; int CPL_DLL VSIFCloseL( VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT; int CPL_DLL VSIFSeekL( VSILFILE *, vsi_l_offset, int ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT; vsi_l_offset CPL_DLL VSIFTellL( VSILFILE * ) CPL_WARN_UNUSED_RESULT; @@ -164,9 +164,10 @@ typedef struct VSI_STAT64_T VSIStatBufL; int CPL_DLL VSIStatL( const char *, VSIStatBufL * ) CPL_WARN_UNUSED_RESULT; -#define VSI_STAT_EXISTS_FLAG 0x1 -#define VSI_STAT_NATURE_FLAG 0x2 -#define VSI_STAT_SIZE_FLAG 0x4 +#define VSI_STAT_EXISTS_FLAG 0x1 +#define VSI_STAT_NATURE_FLAG 0x2 +#define VSI_STAT_SIZE_FLAG 0x4 +#define VSI_STAT_SET_ERROR_FLAG 0x8 int CPL_DLL VSIStatExL( const char * pszFilename, VSIStatBufL * psStatBuf, int nFlags ) CPL_WARN_UNUSED_RESULT; @@ -261,11 +262,11 @@ void CPL_DLL VSISetCryptKey(const GByte* pabyKey, int nKeySize); void CPL_DLL VSICleanupFileManager(void); VSILFILE CPL_DLL *VSIFileFromMemBuffer( const char *pszFilename, - GByte *pabyData, + GByte *pabyData, vsi_l_offset nDataLength, int bTakeOwnership ) CPL_WARN_UNUSED_RESULT; -GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename, - vsi_l_offset *pnDataLength, +GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename, + vsi_l_offset *pnDataLength, int bUnlinkAndSeize ); typedef size_t (*VSIWriteFunction)(const void* ptr, size_t size, size_t nmemb, FILE* stream); diff --git a/gdal/port/cpl_vsi_error.cpp b/gdal/port/cpl_vsi_error.cpp new file mode 100644 index 000000000000..c0c76ecde92f --- /dev/null +++ b/gdal/port/cpl_vsi_error.cpp @@ -0,0 +1,294 @@ +/****************************************************************************** + * $Id$ + * + * Project: VSI Virtual File System + * Purpose: Implement an error system for reporting file system errors. + * Filesystem errors need to be handled separately from the + * CPLError architecture because they are potentially ignored. + * Author: Rob Emanuele, rdemanuele at gmail.com + * + ****************************************************************************** + * Copyright (c) 2016, Rob Emanuele + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#include "cpl_vsi_error.h" +#include "cpl_error.h" +#include "cpl_string.h" +#include "cpl_vsi.h" +#include "cpl_conv.h" +#include "cpl_multiproc.h" + +#if !defined(WIN32) +#include +#endif + + +#define TIMESTAMP_DEBUG +//#define MEMORY_DEBUG + +CPL_CVSID("$Id$"); + +static const int DEFAULT_LAST_ERR_MSG_SIZE = +#if !defined(HAVE_VSNPRINTF) + 20000 +#else + 500 +#endif + ; + +typedef struct { + VSIErrorNum nLastErrNo; + int nLastErrMsgMax; + char szLastErrMsg[DEFAULT_LAST_ERR_MSG_SIZE]; + /* Do not add anything here. szLastErrMsg must be the last field. See CPLRealloc() below */ +} VSIErrorContext; + + +/************************************************************************/ +/* CPLGetErrorContext() */ +/************************************************************************/ + +static VSIErrorContext *VSIGetErrorContext() + +{ + int bError; + VSIErrorContext *psCtx = + reinterpret_cast( + CPLGetTLSEx( CTLS_VSIERRORCONTEXT, &bError ) ); + if( bError ) + return NULL; + + if( psCtx == NULL ) + { + psCtx = reinterpret_cast( + VSICalloc( sizeof(VSIErrorContext), 1) ); + if (psCtx == NULL) { + fprintf(stderr, "Out of memory attempting to record a VSI error.\n"); + return NULL; + } + psCtx->nLastErrNo = VSIE_None; + psCtx->nLastErrMsgMax = sizeof(psCtx->szLastErrMsg); + CPLSetTLS( CTLS_VSIERRORCONTEXT, psCtx, TRUE ); + } + + return psCtx; +} + +/********************************************************************** + * VSIError() + **********************************************************************/ + +/** + * Report an VSI filesystem error. + * + * This function records an error in the filesystem that may or may not be + * used in the future, for example converted into a CPLError. This allows + * filesystem errors to be available to error handling functionality, but + * reported only when necessary. + * + * @param err_no the error number (VSIE_*) from cpl_vsi_error.h. + * @param fmt a printf() style format string. Any additional arguments + * will be treated as arguments to fill in this format in a manner + * similar to printf(). + */ + +void VSIError(VSIErrorNum err_no, const char *fmt, ...) +{ + va_list args; + + // Expand the error message + va_start(args, fmt); + VSIErrorV( err_no, fmt, args ); + va_end(args); +} + +/************************************************************************/ +/* VSIErrorV() */ +/************************************************************************/ + +void VSIErrorV( VSIErrorNum err_no, const char *fmt, va_list args ) +{ + VSIErrorContext *psCtx = VSIGetErrorContext(); + if( psCtx == NULL ) + return; + +/* -------------------------------------------------------------------- */ +/* Expand the error message */ +/* -------------------------------------------------------------------- */ +#if defined(HAVE_VSNPRINTF) + { + va_list wrk_args; + +#ifdef va_copy + va_copy( wrk_args, args ); +#else + wrk_args = args; +#endif + + int nPreviousSize = 0; + int nPR; + while( ((nPR = CPLvsnprintf( + psCtx->szLastErrMsg+nPreviousSize, + psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1 + || nPR >= psCtx->nLastErrMsgMax-nPreviousSize-1) + && psCtx->nLastErrMsgMax < 1000000 ) + { +#ifdef va_copy + va_end( wrk_args ); + va_copy( wrk_args, args ); +#else + wrk_args = args; +#endif + psCtx->nLastErrMsgMax *= 3; + psCtx = static_cast ( + CPLRealloc( psCtx, + sizeof(VSIErrorContext) + - DEFAULT_LAST_ERR_MSG_SIZE + + psCtx->nLastErrMsgMax + 1) ); + CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE ); + } + + va_end( wrk_args ); + } +#else + // !HAVE_VSNPRINTF + CPLvsnprintf( psCtx->szLastErrMsg, psCtx->nLastErrMsgMax, fmt, args); +#endif + + psCtx->nLastErrNo = err_no; +} + +/********************************************************************** + * VSIErrorReset() + **********************************************************************/ + +/** + * Erase any traces of previous errors. + * + * This is used to clear out the latest file system error when it is either translated + * into a CPLError call or when it is determined to be ignorable. + */ + +void CPL_STDCALL VSIErrorReset() +{ + VSIErrorContext *psCtx = VSIGetErrorContext(); + if( psCtx == NULL ) + return; + + psCtx->nLastErrNo = VSIE_None; + psCtx->szLastErrMsg[0] = '\0'; +} + +/********************************************************************** + * VSIGetLastErrorNo() + **********************************************************************/ + +/** + * Fetch the last error number. + * + * Fetches the last error number posted with VSIError(), that hasn't + * been cleared by VSIErrorReset(). This is the error number, not the error + * class. + * + * @return the error number of the last error to occur, or VSIE_None (0) + * if there are no posted errors. + */ + +VSIErrorNum CPL_STDCALL VSIGetLastErrorNo() +{ + VSIErrorContext *psCtx = VSIGetErrorContext(); + if( psCtx == NULL ) + return 0; + + return psCtx->nLastErrNo; +} + +/********************************************************************** + * VSIGetLastErrorMsg() + **********************************************************************/ + +/** + * Get the last error message. + * + * Fetches the last error message posted with VSIError(), that hasn't + * been cleared by VSIErrorReset(). The returned pointer is to an internal + * string that should not be altered or freed. + * + * @return the last error message, or NULL if there is no posted error + * message. + */ + +const char* CPL_STDCALL VSIGetLastErrorMsg() +{ + VSIErrorContext *psCtx = VSIGetErrorContext(); + if( psCtx == NULL ) + return ""; + + return psCtx->szLastErrMsg; +} + +/********************************************************************** + * VSItoCPLError() + **********************************************************************/ + +/** + * Translate the VSI error into a CPLError call + * + * Fetches the last error message posted with VSIError(), that hasn't + * been cleared by VSIErrorReset(). The returned pointer is to an internal + * string that should not be altered or freed. + * + * @return true if a CPLError was issued, or false if not. + */ + +bool CPL_DLL CPL_STDCALL VSIToCPLError(CPLErr eErrClass, CPLErrorNum eDefaultErrorNo) { + int err = VSIGetLastErrorNo(); + switch(err) { + case VSIE_None: + return false; + case VSIE_FileError: + CPLError(eErrClass, eDefaultErrorNo, "%s", VSIGetLastErrorMsg()); + break; + case VSIE_HttpError: + CPLError(eErrClass, CPLE_HttpResponse, "%s", VSIGetLastErrorMsg()); + break; + case VSIE_AWSAccessDenied: + CPLError(eErrClass, CPLE_AWSAccessDenied, "%s", VSIGetLastErrorMsg()); + break; + case VSIE_AWSBucketNotFound: + CPLError(eErrClass, CPLE_AWSBucketNotFound, "%s", VSIGetLastErrorMsg()); + break; + case VSIE_AWSObjectNotFound: + CPLError(eErrClass, CPLE_AWSObjectNotFound, "%s", VSIGetLastErrorMsg()); + break; + case VSIE_AWSInvalidCredentials: + CPLError(eErrClass, CPLE_AWSInvalidCredentials, "%s", VSIGetLastErrorMsg()); + break; + case VSIE_AWSSignatureDoesNotMatch: + CPLError(eErrClass, CPLE_AWSSignaturDoesNotMatch, "%s", VSIGetLastErrorMsg()); + break; + default: + CPLError(eErrClass, CPLE_HttpResponse, "A filesystem error with code %d occurred", err); + break; + } + + return true; +} diff --git a/gdal/port/cpl_vsi_error.h b/gdal/port/cpl_vsi_error.h new file mode 100644 index 000000000000..696ed66d39da --- /dev/null +++ b/gdal/port/cpl_vsi_error.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * $Id$ + * + * Project: VSI Virtual File System + * Purpose: Implement an error system for reporting file system errors. + * Filesystem errors need to be handled separately from the + * CPLError architecture because they are potentially ignored. + * Author: Rob Emanuele, rdemanuele at gmail.com + * + ****************************************************************************** + * Copyright (c) 2016, Rob Emanuele + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ****************************************************************************/ + +#ifndef CPL_VSI_ERROR_H_INCLUDED +#define CPL_VSI_ERROR_H_INCLUDED + +#include "cpl_port.h" +#include "cpl_error.h" + +/* ==================================================================== + Filesystem error codes. + ==================================================================== */ + +CPL_C_START + +typedef int VSIErrorNum; + +#define VSIE_None 0 +#define VSIE_FileError 1 +#define VSIE_HttpError 2 + +#define VSIE_AWSError 5 +#define VSIE_AWSAccessDenied 6 +#define VSIE_AWSBucketNotFound 7 +#define VSIE_AWSObjectNotFound 8 +#define VSIE_AWSInvalidCredentials 9 +#define VSIE_AWSSignatureDoesNotMatch 10 + +void CPL_DLL VSIError(VSIErrorNum err_no, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT (2, 3); +void CPL_DLL VSIErrorV(VSIErrorNum, const char *, va_list ); + +void CPL_DLL CPL_STDCALL VSIErrorReset( void ); +VSIErrorNum CPL_DLL CPL_STDCALL VSIGetLastErrorNo( void ); +const char CPL_DLL * CPL_STDCALL VSIGetLastErrorMsg( void ); + +bool CPL_DLL CPL_STDCALL VSIToCPLError(CPLErr eErrClass, CPLErrorNum eDefaultErrorNo); + +CPL_C_END + +#endif /* CPL_VSI_ERROR_H_INCLUDED */ diff --git a/gdal/port/cpl_vsi_mem.cpp b/gdal/port/cpl_vsi_mem.cpp index f157dadcf4f6..3d4036191e46 100644 --- a/gdal/port/cpl_vsi_mem.cpp +++ b/gdal/port/cpl_vsi_mem.cpp @@ -40,7 +40,7 @@ CPL_CVSID("$Id$"); ** Notes on Multithreading: ** ** VSIMemFilesystemHandler: This class maintains a mutex to protect -** access and update of the oFileList array which has all the "files" in +** access and update of the oFileList array which has all the "files" in ** the memory filesystem area. It is expected that multiple threads would ** want to create and read different files at the same time and so might ** collide access oFileList without the mutex. @@ -51,8 +51,8 @@ CPL_CVSID("$Id$"); ** here), which means we don't need to do any protection of this class. ** ** VSIMemHandle: This is essentially a "current location" representing -** on accessor to a file, and is inherently intended only to be used in -** a single thread. +** on accessor to a file, and is inherently intended only to be used in +** a single thread. ** ** In General: ** @@ -97,7 +97,7 @@ class VSIMemFile /************************************************************************/ class VSIMemHandle CPL_FINAL : public VSIVirtualHandle -{ +{ public: VSIMemFile *poFile; vsi_l_offset m_nOffset; @@ -123,7 +123,7 @@ class VSIMemHandle CPL_FINAL : public VSIVirtualHandle /* ==================================================================== */ /************************************************************************/ -class VSIMemFilesystemHandler CPL_FINAL : public VSIFilesystemHandler +class VSIMemFilesystemHandler CPL_FINAL : public VSIFilesystemHandler { public: std::map oFileList; @@ -132,8 +132,11 @@ class VSIMemFilesystemHandler CPL_FINAL : public VSIFilesystemHandler VSIMemFilesystemHandler(); virtual ~VSIMemFilesystemHandler(); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); virtual int Mkdir( const char *pszDirname, long nMode ); @@ -221,7 +224,7 @@ bool VSIMemFile::SetLength( vsi_l_offset nNewLength ) } /* Clear the new allocated part of the buffer */ - memset(pabyNewData + nAllocLength, 0, + memset(pabyNewData + nAllocLength, 0, (size_t) (nNewAlloc - nAllocLength)); pabyData = pabyNewData; @@ -282,9 +285,9 @@ int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence ) { if( !bUpdate ) // Read-only files cannot be extended by seek. { - CPLDebug( "VSIMemHandle", + CPLDebug( "VSIMemHandle", "Attempt to extend read-only file '%s' to length " CPL_FRMT_GUIB " from " CPL_FRMT_GUIB ".", - poFile->osFilename.c_str(), + poFile->osFilename.c_str(), m_nOffset, poFile->nLength ); m_nOffset = poFile->nLength; @@ -445,8 +448,9 @@ VSIMemFilesystemHandler::~VSIMemFilesystemHandler() /************************************************************************/ VSIVirtualHandle * -VSIMemFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess ) +VSIMemFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ) { CPLMutexHolder oHolder( &hMutex ); @@ -467,6 +471,7 @@ VSIMemFilesystemHandler::Open( const char *pszFilename, && strstr(pszAccess, "a") == NULL && poFile == NULL ) { + if(bSetError) { VSIError(VSIE_FileError, "No such file or directory"); } errno = ENOENT; return NULL; } @@ -499,7 +504,7 @@ VSIMemFilesystemHandler::Open( const char *pszFilename, poHandle->poFile = poFile; poHandle->m_nOffset = 0; poHandle->bEOF = FALSE; - if( strstr(pszAccess,"w") || strstr(pszAccess,"+") + if( strstr(pszAccess,"w") || strstr(pszAccess,"+") || strstr(pszAccess,"a") ) poHandle->bUpdate = TRUE; else @@ -669,7 +674,7 @@ char **VSIMemFilesystemHandler::ReadDirEx( const char *pszPath, { const char *pszFilePath = iter->second->osFilename.c_str(); if( EQUALN(osPath,pszFilePath,nPathLen) - && pszFilePath[nPathLen] == '/' + && pszFilePath[nPathLen] == '/' && strstr(pszFilePath+nPathLen+1,"/") == NULL ) { if (nItems == 0) @@ -680,7 +685,7 @@ char **VSIMemFilesystemHandler::ReadDirEx( const char *pszPath, else if (nItems >= nAllocatedItems) { nAllocatedItems = nAllocatedItems * 2; - papszDir = (char**)CPLRealloc(papszDir, + papszDir = (char**)CPLRealloc(papszDir, (nAllocatedItems+2)*sizeof(char*)); } @@ -773,21 +778,21 @@ GIntBig VSIMemFilesystemHandler::GetDiskFreeSpace( const char* /*pszDirname*/ ) /************************************************************************/ /** - * \brief Install "memory" file system handler. + * \brief Install "memory" file system handler. * * A special file handler is installed that allows block of memory to be * treated as files. All portions of the file system underneath the base - * path "/vsimem/" will be handled by this driver. + * path "/vsimem/" will be handled by this driver. * * Normal VSI*L functions can be used freely to create and destroy memory * arrays treating them as if they were real file system objects. Some * additional methods exist to efficient create memory file system objects * without duplicating original copies of the data or to "steal" the block - * of memory associated with a memory file. + * of memory associated with a memory file. * * At this time the memory handler does not properly handle directory * semantics for the memory portion of the filesystem. The VSIReadDir() - * function is not supported though this will be corrected in the future. + * function is not supported though this will be corrected in the future. * * Calling this function repeatedly should do no harm, though it is not * necessary. It is already called the first time a virtualizable @@ -797,7 +802,7 @@ GIntBig VSIMemFilesystemHandler::GetDiskFreeSpace( const char* /*pszDirname*/ ) * buffer to another. * * \code - * GByte *ConvertBufferFormat( GByte *pabyInData, vsi_l_offset nInDataLength, + * GByte *ConvertBufferFormat( GByte *pabyInData, vsi_l_offset nInDataLength, * vsi_l_offset *pnOutDataLength ) * { * // create memory file system object from buffer. @@ -806,15 +811,15 @@ GIntBig VSIMemFilesystemHandler::GetDiskFreeSpace( const char* /*pszDirname*/ ) * * // Open memory buffer for read. * GDALDatasetH hDS = GDALOpen( "/vsimem/work.dat", GA_ReadOnly ); - * - * // Get output format driver. + * + * // Get output format driver. * GDALDriverH hDriver = GDALGetDriverByName( "GTiff" ); * GDALDatasetH hOutDS; * - * hOutDS = GDALCreateCopy( hDriver, "/vsimem/out.tif", hDS, TRUE, NULL, + * hOutDS = GDALCreateCopy( hDriver, "/vsimem/out.tif", hDS, TRUE, NULL, * NULL, NULL ); - * - * // close source file, and "unlink" it. + * + * // close source file, and "unlink" it. * GDALClose( hDS ); * VSIUnlink( "/vsimem/work.dat" ); * @@ -839,33 +844,33 @@ void VSIInstallMemFileHandler() * * A virtual memory file is created from the passed buffer with the indicated * filename. Under normal conditions the filename would need to be absolute - * and within the /vsimem/ portion of the filesystem. + * and within the /vsimem/ portion of the filesystem. * * If bTakeOwnership is TRUE, then the memory file system handler will take * ownership of the buffer, freeing it when the file is deleted. Otherwise * it remains the responsibility of the caller, but should not be freed as * long as it might be accessed as a file. In no circumstances does this - * function take a copy of the pabyData contents. + * function take a copy of the pabyData contents. * * @param pszFilename the filename to be created. - * @param pabyData the data buffer for the file. + * @param pabyData the data buffer for the file. * @param nDataLength the length of buffer in bytes. - * @param bTakeOwnership TRUE to transfer "ownership" of buffer or FALSE. + * @param bTakeOwnership TRUE to transfer "ownership" of buffer or FALSE. * - * @return open file handle on created file (see VSIFOpenL()). + * @return open file handle on created file (see VSIFOpenL()). */ VSILFILE *VSIFileFromMemBuffer( const char *pszFilename, - GByte *pabyData, + GByte *pabyData, vsi_l_offset nDataLength, int bTakeOwnership ) { - if( VSIFileManager::GetHandler("") + if( VSIFileManager::GetHandler("") == VSIFileManager::GetHandler("/vsimem/") ) VSIInstallMemFileHandler(); - VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *) + VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *) VSIFileManager::GetHandler("/vsimem/"); if (pszFilename == NULL) @@ -897,7 +902,7 @@ VSILFILE *VSIFileFromMemBuffer( const char *pszFilename, /************************************************************************/ /** - * \brief Fetch buffer underlying memory file. + * \brief Fetch buffer underlying memory file. * * This function returns a pointer to the memory buffer underlying a * virtual "in memory" file. If bUnlinkAndSeize is TRUE the filesystem @@ -911,12 +916,12 @@ VSILFILE *VSIFileFromMemBuffer( const char *pszFilename, * @return pointer to memory buffer or NULL on failure. */ -GByte *VSIGetMemFileBuffer( const char *pszFilename, +GByte *VSIGetMemFileBuffer( const char *pszFilename, vsi_l_offset *pnDataLength, int bUnlinkAndSeize ) { - VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *) + VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *) VSIFileManager::GetHandler("/vsimem/"); if (pszFilename == NULL) @@ -938,7 +943,7 @@ GByte *VSIGetMemFileBuffer( const char *pszFilename, if( bUnlinkAndSeize ) { if( !poFile->bOwnData ) - CPLDebug( "VSIMemFile", + CPLDebug( "VSIMemFile", "File doesn't own data in VSIGetMemFileBuffer!" ); else poFile->bOwnData = FALSE; diff --git a/gdal/port/cpl_vsi_virtual.h b/gdal/port/cpl_vsi_virtual.h index fc7f4ea64af9..b79e20df49ed 100644 --- a/gdal/port/cpl_vsi_virtual.h +++ b/gdal/port/cpl_vsi_virtual.h @@ -4,7 +4,7 @@ * Project: VSI Virtual File System * Purpose: Declarations for classes related to the virtual filesystem. * These would only be normally required by applications implementing - * their own virtual file system classes which should be rare. + * their own virtual file system classes which should be rare. * The class interface may be fragile through versions. * Author: Frank Warmerdam, warmerdam@pobox.com * @@ -35,6 +35,7 @@ #define CPL_VSI_VIRTUAL_H_INCLUDED #include "cpl_vsi.h" +#include "cpl_vsi_error.h" #include "cpl_string.h" #include "cpl_multiproc.h" @@ -46,7 +47,7 @@ /* VSIVirtualHandle */ /************************************************************************/ -class CPL_DLL VSIVirtualHandle { +class CPL_DLL VSIVirtualHandle { public: virtual int Seek( vsi_l_offset nOffset, int nWhence ) = 0; virtual vsi_l_offset Tell() = 0; @@ -71,18 +72,25 @@ class CPL_DLL VSIFilesystemHandler { virtual ~VSIFilesystemHandler() {} - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess) = 0; + VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess ) + { + return Open(pszFilename, pszAccess, false); + } + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ) = 0; virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags) = 0; virtual int Unlink( const char *pszFilename ) { (void) pszFilename; errno=ENOENT; return -1; } - virtual int Mkdir( const char *pszDirname, long nMode ) + virtual int Mkdir( const char *pszDirname, long nMode ) {(void)pszDirname; (void)nMode; errno=ENOENT; return -1;} - virtual int Rmdir( const char *pszDirname ) + virtual int Rmdir( const char *pszDirname ) { (void) pszDirname; errno=ENOENT; return -1; } - virtual char **ReadDir( const char *pszDirname ) + virtual char **ReadDir( const char *pszDirname ) { (void) pszDirname; return NULL; } - virtual char **ReadDirEx( const char *pszDirname, int /* nMaxFiles */ ) + virtual char **ReadDirEx( const char *pszDirname, int /* nMaxFiles */ ) { return ReadDir(pszDirname); } virtual int Rename( const char *oldpath, const char *newpath ) { (void) oldpath; (void)newpath; errno=ENOENT; return -1; } @@ -95,7 +103,7 @@ class CPL_DLL VSIFilesystemHandler { /* VSIFileManager */ /************************************************************************/ -class CPL_DLL VSIFileManager +class CPL_DLL VSIFileManager { private: VSIFilesystemHandler *poDefaultHandler; @@ -109,7 +117,7 @@ class CPL_DLL VSIFileManager ~VSIFileManager(); static VSIFilesystemHandler *GetHandler( const char * ); - static void InstallHandler( const std::string& osPrefix, + static void InstallHandler( const std::string& osPrefix, VSIFilesystemHandler * ); /* RemoveHandler is never defined. */ /* static void RemoveHandler( const std::string& osPrefix ); */ @@ -163,7 +171,7 @@ class VSIArchiveReader virtual int GotoFileOffset(VSIArchiveEntryFileOffset* pOffset) = 0; }; -class VSIArchiveFilesystemHandler : public VSIFilesystemHandler +class VSIArchiveFilesystemHandler : public VSIFilesystemHandler { protected: CPLMutex* hMutex; diff --git a/gdal/port/cpl_vsil.cpp b/gdal/port/cpl_vsil.cpp index d122c7e9ee91..f4d0a350ecc3 100644 --- a/gdal/port/cpl_vsil.cpp +++ b/gdal/port/cpl_vsil.cpp @@ -535,18 +535,55 @@ int VSIIsCaseSensitiveFS( const char * pszFilename ) * Analog of the POSIX fopen() function. * * @param pszFilename the file to open. UTF-8 encoded. - * @param pszAccess access requested (i.e. "r", "r+", "w". + * @param pszAccess access requested (i.e. "r", "r+", "w") * * @return NULL on failure, or the file handle. */ VSILFILE *VSIFOpenL( const char * pszFilename, const char * pszAccess ) +{ + return VSIFOpenExL(pszFilename, pszAccess, false); +} + +/************************************************************************/ +/* VSIFOpenExL() */ +/************************************************************************/ + +/** + * \brief Open file. + * + * This function opens a file with the desired access. Large files (larger + * than 2GB) should be supported. Binary access is always implied and + * the "b" does not need to be included in the pszAccess string. + * + * Note that the "VSILFILE *" returned since GDAL 1.8.0 by this function is + * *NOT* a standard C library FILE *, and cannot be used with any functions + * other than the "VSI*L" family of functions. They aren't "real" FILE objects. + * + * On windows it is possible to define the configuration option + * GDAL_FILE_IS_UTF8 to have pszFilename treated as being in the local + * encoding instead of UTF-8, restoring the pre-1.8.0 behavior of VSIFOpenL(). + * + * This method goes through the VSIFileHandler virtualization and may + * work on unusual filesystems such as in memory. + * + * Analog of the POSIX fopen() function. + * + * @param pszFilename the file to open. UTF-8 encoded. + * @param pszAccess access requested (i.e. "r", "r+", "w") + * @param bSetError flag determining whether or not this open call should set VSIErrors on failure. + * + * @return NULL on failure, or the file handle. + */ + +VSILFILE *VSIFOpenExL( const char * pszFilename, const char * pszAccess, bool bSetError ) + { VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( pszFilename ); - VSILFILE* fp = (VSILFILE *) poFSHandler->Open( pszFilename, pszAccess ); + VSILFILE* fp = (VSILFILE *) poFSHandler->Open( pszFilename, pszAccess, bSetError ); VSIDebug3( "VSIFOpenL(%s,%s) = %p", pszFilename, pszAccess, fp ); diff --git a/gdal/port/cpl_vsil_crypt.cpp b/gdal/port/cpl_vsil_crypt.cpp index 16b87e186fb1..4a937720345e 100644 --- a/gdal/port/cpl_vsil_crypt.cpp +++ b/gdal/port/cpl_vsil_crypt.cpp @@ -23,7 +23,7 @@ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ @@ -591,7 +591,7 @@ int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKe return VSICryptReadError(); CPL_LSBPTR64(&nPayloadFileSize); #ifdef VERBOSE_VSICRYPT - CPLDebug("VSICRYPT", "nPayloadFileSize read = " CPL_FRMT_GUIB, + CPLDebug("VSICRYPT", "nPayloadFileSize read = " CPL_FRMT_GUIB, nPayloadFileSize); #endif @@ -1265,7 +1265,7 @@ int VSICryptFileHandle::Flush() if( bUpdateHeader ) { #ifdef VERBOSE_VSICRYPT - CPLDebug("VSICRYPT", "nPayloadFileSize = " CPL_FRMT_GUIB, + CPLDebug("VSICRYPT", "nPayloadFileSize = " CPL_FRMT_GUIB, poHeader->nPayloadFileSize); #endif if( !poHeader->WriteToFile(poBaseHandle, poEncCipher) ) @@ -1300,14 +1300,17 @@ int VSICryptFileHandle::Close() /* VSICryptFilesystemHandler */ /************************************************************************/ -class VSICryptFilesystemHandler CPL_FINAL : public VSIFilesystemHandler +class VSICryptFilesystemHandler CPL_FINAL : public VSIFilesystemHandler { public: VSICryptFilesystemHandler(); ~VSICryptFilesystemHandler(); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); virtual int Rename( const char *oldpath, const char *newpath ); @@ -1400,8 +1403,9 @@ static CPLString GetKey(const char* pszFilename) /* Open() */ /************************************************************************/ -VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess) +VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */ ) { #ifdef VERBOSE_VSICRYPT CPLDebug("VSICRYPT", "Open(%s, %s)", pszFilename, pszAccess); @@ -1747,7 +1751,7 @@ static GDALDataset* VSICryptOpen(GDALOpenInfo* poOpenInfo) * The default is AES. * Only used on creation. Ignored otherwise. * Note: depending on how GDAL is build, if linked against the DLL version of libcrypto++, - * only a subset of those algorithms will be available, namely AES, DES_EDE2, DES_EDE3 and SKIPJACK. + * only a subset of those algorithms will be available, namely AES, DES_EDE2, DES_EDE3 and SKIPJACK. * Also available as VSICRYPT_ALG configuration option. *
  • mode=CBC/CFB/OFB/CTR/CBC_CTS: to specify the block cipher mode of operation. * The default is CBC. @@ -1867,12 +1871,12 @@ void VSIInstallCryptFileHandler(void) #else /* HAVE_CRYPTOPP */ -class VSIDummyCryptFilesystemHandler : public VSIFilesystemHandler +class VSIDummyCryptFilesystemHandler : public VSIFilesystemHandler { public: VSIDummyCryptFilesystemHandler() {} - virtual VSIVirtualHandle *Open( CPL_UNUSED const char *pszFilename, + virtual VSIVirtualHandle *Open( CPL_UNUSED const char *pszFilename, CPL_UNUSED const char *pszAccess) { CPLError(CE_Failure, CPLE_NotSupported, diff --git a/gdal/port/cpl_vsil_curl.cpp b/gdal/port/cpl_vsil_curl.cpp index 10e8cd9c6147..b3f2cace3ba5 100644 --- a/gdal/port/cpl_vsil_curl.cpp +++ b/gdal/port/cpl_vsil_curl.cpp @@ -133,7 +133,7 @@ typedef struct bool bError; bool bDownloadHeaderOnly; - VSILFILE *fp; + VSILFILE *fp; VSICurlReadCbkFunc pfnReadCbk; void *pReadCbkUserData; bool bInterrupted; @@ -224,7 +224,7 @@ typedef struct class VSICurlHandle; -class VSICurlFilesystemHandler : public VSIFilesystemHandler +class VSICurlFilesystemHandler : public VSIFilesystemHandler { CachedRegion **papsRegions; int nRegions; @@ -264,8 +264,12 @@ class VSICurlFilesystemHandler : public VSIFilesystemHandler VSICurlFilesystemHandler(); ~VSICurlFilesystemHandler(); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); + virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); virtual int Rename( const char *oldpath, const char *newpath ); @@ -328,9 +332,10 @@ class VSICurlHandle : public VSIVirtualHandle protected: virtual struct curl_slist* GetCurlHeaders(const CPLString& ) { return NULL; } - virtual bool CanRestartOnError(const char*) { return false; } + bool CanRestartOnError(const char* pszErrorMsg) { return CanRestartOnError(pszErrorMsg, false); } + virtual bool CanRestartOnError(const char*, bool) { return false; } virtual bool UseLimitRangeGetInsteadOfHead() { return false; } - virtual void ProcessGetFileSizeResult(const char* /* pszContent */ ) {} + virtual void ProcessGetFileSizeResult(const char* /* pszContent */ ) {} void SetURL(const char* pszURL); public: @@ -349,8 +354,9 @@ class VSICurlHandle : public VSIVirtualHandle virtual int Close(); bool IsKnownFileSize() const { return bHasComputedFileSize; } - vsi_l_offset GetFileSize(); - bool Exists(); + vsi_l_offset GetFileSize() { return GetFileSize(false); } + vsi_l_offset GetFileSize(bool bSetError); + bool Exists(bool bSetError); bool IsDirectory() const { return bIsDirectory; } time_t GetMTime() const { return mTime; } @@ -482,7 +488,7 @@ void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL) #endif curl_easy_setopt(hCurlHandle, CURLOPT_NOBODY, 0); - curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 1); + curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 1); curl_easy_setopt(hCurlHandle, CURLOPT_HEADER, 0); /* 7.16.4 */ @@ -613,7 +619,7 @@ static size_t VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, v /* GetFileSize() */ /************************************************************************/ -vsi_l_offset VSICurlHandle::GetFileSize() +vsi_l_offset VSICurlHandle::GetFileSize(bool bSetError) { WriteFuncStruct sWriteFuncData; WriteFuncStruct sWriteFuncHeaderData; @@ -776,6 +782,7 @@ vsi_l_offset VSICurlHandle::GetFileSize() long response_code = 0; curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code); + if( UseLimitRangeGetInsteadOfHead() && response_code == 206 ) { eExists = EXIST_NO; @@ -795,12 +802,26 @@ vsi_l_offset VSICurlHandle::GetFileSize() else if( response_code != 200 ) { if( UseLimitRangeGetInsteadOfHead() && sWriteFuncData.pBuffer != NULL && - CanRestartOnError((const char*)sWriteFuncData.pBuffer) ) + CanRestartOnError((const char*)sWriteFuncData.pBuffer, bSetError) ) { bHasComputedFileSize = false; CPLFree(sWriteFuncData.pBuffer); CPLFree(sWriteFuncHeaderData.pBuffer); - return GetFileSize(); + return GetFileSize(bSetError); + } + + // If there was no VSI error thrown in the process, + // fail by reporting the HTTP response code. + if(bSetError && VSIGetLastErrorNo() == 0) { + if(strlen(szCurlErrBuf) > 0) { + if(response_code == 0) { + VSIError(VSIE_HttpError, "CURL error: %s", szCurlErrBuf); + } else { + VSIError(VSIE_HttpError, "HTTP response code: %d - %s", (int)response_code, szCurlErrBuf); + } + } else { + VSIError(VSIE_HttpError, "HTTP response code: %d", (int)response_code); + } } eExists = EXIST_NO; @@ -844,10 +865,11 @@ vsi_l_offset VSICurlHandle::GetFileSize() /* Exists() */ /************************************************************************/ -bool VSICurlHandle::Exists() +bool VSICurlHandle::Exists(bool bSetError) { - if (eExists == EXIST_UNKNOWN) - GetFileSize(); + if (eExists == EXIST_UNKNOWN) { + GetFileSize(bSetError); + } return eExists == EXIST_YES; } @@ -890,7 +912,7 @@ bool VSICurlHandle::DownloadRegion(vsi_l_offset startOffset, int nBlocks) sWriteFuncHeaderData.nStartOffset = startOffset; sWriteFuncHeaderData.nEndOffset = startOffset + nBlocks * DOWNLOAD_CHUNK_SIZE - 1; /* Some servers don't like we try to read after end-of-file (#5786) */ - if( cachedFileProp->bHasComputedFileSize && + if( cachedFileProp->bHasComputedFileSize && sWriteFuncHeaderData.nEndOffset >= cachedFileProp->fileSize ) { sWriteFuncHeaderData.nEndOffset = cachedFileProp->fileSize - 1; @@ -1658,7 +1680,7 @@ CURL* VSICurlFilesystemHandler::GetCurlHandleFor(CPLString osURL) /* GetRegionFromCacheDisk() */ /************************************************************************/ -const CachedRegion* +const CachedRegion* VSICurlFilesystemHandler::GetRegionFromCacheDisk(const char* pszURL, vsi_l_offset nFileOffsetStart) { @@ -1889,7 +1911,8 @@ VSICurlHandle* VSICurlFilesystemHandler::CreateFileHandle(const char* pszURL) /************************************************************************/ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess) + const char *pszAccess, + bool bSetError ) { if (strchr(pszAccess, 'w') != NULL || strchr(pszAccess, '+') != NULL) @@ -1918,13 +1941,13 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename, } } - VSICurlHandle* poHandle = CreateFileHandle( osFilename + strlen(GetFSPrefix())); + VSICurlHandle* poHandle = CreateFileHandle(osFilename + strlen(GetFSPrefix())); if( poHandle == NULL ) return NULL; if (!bGotFileList) { /* If we didn't get a filelist, check that the file really exists */ - if (!poHandle->Exists()) + if (!poHandle->Exists(bSetError)) { delete poHandle; return NULL; @@ -1953,7 +1976,7 @@ static char *VSICurlParserFindEOL( char *pszData ) if( *pszData == '\0' ) return NULL; - else + else return pszData; } @@ -2834,7 +2857,7 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE", "YES"))) ) pStatBuf->st_size = poHandle->GetFileSize(); - int nRet = (poHandle->Exists()) ? 0 : -1; + int nRet = poHandle->Exists((nFlags & VSI_STAT_SET_ERROR_FLAG) > 0) ? 0 : -1; pStatBuf->st_mtime = poHandle->GetMTime(); pStatBuf->st_mode = poHandle->IsDirectory() ? S_IFDIR : S_IFREG; delete poHandle; @@ -3049,8 +3072,9 @@ class VSIS3FSHandler CPL_FINAL : public VSICurlFilesystemHandler public: VSIS3FSHandler() {} - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); @@ -3068,7 +3092,7 @@ class VSIS3Handle CPL_FINAL : public VSICurlHandle protected: virtual struct curl_slist* GetCurlHeaders(const CPLString& osVerb); - virtual bool CanRestartOnError(const char*); + virtual bool CanRestartOnError(const char*, bool); virtual bool UseLimitRangeGetInsteadOfHead() { return true; } virtual void ProcessGetFileSizeResult(const char* pszContent); @@ -3660,7 +3684,8 @@ int VSIS3WriteHandle::Close() /************************************************************************/ VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename, - const char *pszAccess) + const char *pszAccess, + bool bSetError) { if (strchr(pszAccess, 'w') != NULL ) { @@ -3686,7 +3711,7 @@ VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename, } else { - return VSICurlFilesystemHandler::Open(pszFilename, pszAccess); + return VSICurlFilesystemHandler::Open(pszFilename, pszAccess, bSetError); } } @@ -3999,9 +4024,9 @@ struct curl_slist* VSIS3Handle::GetCurlHeaders(const CPLString& osVerb) /* CanRestartOnError() */ /************************************************************************/ -bool VSIS3Handle::CanRestartOnError(const char* pszErrorMsg) +bool VSIS3Handle::CanRestartOnError(const char* pszErrorMsg, bool bSetError) { - if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg) ) + if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg, bSetError) ) { ((VSIS3FSHandler*) poFS)->UpdateMapFromHandle(m_poS3HandleHelper); diff --git a/gdal/port/cpl_vsil_curl_streaming.cpp b/gdal/port/cpl_vsil_curl_streaming.cpp index 861eea760c07..d1be34fb0421 100644 --- a/gdal/port/cpl_vsil_curl_streaming.cpp +++ b/gdal/port/cpl_vsil_curl_streaming.cpp @@ -188,8 +188,11 @@ class VSICurlStreamingFSHandler : public VSIFilesystemHandler VSICurlStreamingFSHandler(); ~VSICurlStreamingFSHandler(); + using VSIFilesystemHandler::Open; + virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); void AcquireMutex(); @@ -259,7 +262,8 @@ class VSICurlStreamingHandle : public VSIVirtualHandle protected: virtual struct curl_slist* GetCurlHeaders(const CPLString& ) { return NULL; } virtual bool StopReceivingBytesOnError() { return true; } - virtual bool CanRestartOnError(const char*) { return false; } + bool CanRestartOnError(const char* pszErrorMsg) { return CanRestartOnError(pszErrorMsg, false); } + virtual bool CanRestartOnError(const char*, bool) { return false; } virtual bool InterpretRedirect() { return true; } void SetURL(const char* pszURL); @@ -1488,7 +1492,8 @@ VSICurlStreamingHandle* VSICurlStreamingFSHandler::CreateFileHandle(const char* /************************************************************************/ VSIVirtualHandle* VSICurlStreamingFSHandler::Open( const char *pszFilename, - const char *pszAccess ) + const char *pszAccess, + bool /* bSetError */ ) { if (strchr(pszAccess, 'w') != NULL || strchr(pszAccess, '+') != NULL) @@ -1642,7 +1647,7 @@ class VSIS3StreamingHandle CPL_FINAL: public VSICurlStreamingHandle protected: virtual struct curl_slist* GetCurlHeaders(const CPLString& osVerb); virtual bool StopReceivingBytesOnError() { return false; } - virtual bool CanRestartOnError(const char*); + virtual bool CanRestartOnError(const char*, bool); virtual bool InterpretRedirect() { return false; } public: @@ -1700,9 +1705,9 @@ struct curl_slist* VSIS3StreamingHandle::GetCurlHeaders(const CPLString& osVerb) /* CanRestartOnError() */ /************************************************************************/ -bool VSIS3StreamingHandle::CanRestartOnError(const char* pszErrorMsg) +bool VSIS3StreamingHandle::CanRestartOnError(const char* pszErrorMsg, bool bSetError) { - if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg) ) + if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg, bSetError) ) { ((VSIS3StreamingFSHandler*) m_poFS)->UpdateMapFromHandle(m_poS3HandleHelper); diff --git a/gdal/port/cpl_vsil_gzip.cpp b/gdal/port/cpl_vsil_gzip.cpp index 32ace440baae..1b0bdf18f0aa 100644 --- a/gdal/port/cpl_vsil_gzip.cpp +++ b/gdal/port/cpl_vsil_gzip.cpp @@ -188,7 +188,7 @@ class VSIGZipHandle CPL_FINAL : public VSIVirtualHandle }; -class VSIGZipFilesystemHandler CPL_FINAL : public VSIFilesystemHandler +class VSIGZipFilesystemHandler CPL_FINAL : public VSIFilesystemHandler { CPLMutex* hMutex; VSIGZipHandle* poHandleLastGZipFile; @@ -197,10 +197,13 @@ class VSIGZipFilesystemHandler CPL_FINAL : public VSIFilesystemHandler VSIGZipFilesystemHandler(); ~VSIGZipFilesystemHandler(); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); - VSIGZipHandle *OpenGZipReadOnly( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); + VSIGZipHandle *OpenGZipReadOnly( const char *pszFilename, + const char *pszAccess ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); virtual int Rename( const char *oldpath, const char *newpath ); @@ -223,7 +226,7 @@ VSIGZipHandle* VSIGZipHandle::Duplicate() CPLAssert (m_compressed_size != 0); CPLAssert (m_pszBaseFileName != NULL); - VSIFilesystemHandler *poFSHandler = + VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( m_pszBaseFileName ); VSIVirtualHandle* poNewBaseHandle = @@ -362,7 +365,7 @@ void VSIGZipHandle::SaveInfo_unlocked() { if (m_pszBaseFileName && m_bCanSaveInfo) { - VSIFilesystemHandler *poFSHandler = + VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( "/vsigzip/" ); ((VSIGZipFilesystemHandler*)poFSHandler)->SaveInfo_unlocked(this); m_bCanSaveInfo = FALSE; @@ -377,7 +380,7 @@ VSIGZipHandle::~VSIGZipHandle() { if (m_pszBaseFileName && m_bCanSaveInfo) { - VSIFilesystemHandler *poFSHandler = + VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( "/vsigzip/" ); ((VSIGZipFilesystemHandler*)poFSHandler)->SaveInfo(this); } @@ -1168,7 +1171,7 @@ size_t VSIGZipWriteHandle::Read( CPL_UNUSED void *pBuffer, /* Write() */ /************************************************************************/ -size_t VSIGZipWriteHandle::Write( const void * const pBuffer, +size_t VSIGZipWriteHandle::Write( const void * const pBuffer, size_t const nSize, size_t const nMemb ) { @@ -1190,8 +1193,8 @@ size_t VSIGZipWriteHandle::Write( const void * const pBuffer, int nNewBytesToWrite = MIN((int) (Z_BUFSIZE-sStream.avail_in), nBytesToWrite - nNextByte); - memcpy( pabyInBuf + sStream.avail_in, - ((Byte *) pBuffer) + nNextByte, + memcpy( pabyInBuf + sStream.avail_in, + ((Byte *) pBuffer) + nNextByte, nNewBytesToWrite ); sStream.next_in = pabyInBuf; @@ -1346,10 +1349,11 @@ void VSIGZipFilesystemHandler::SaveInfo_unlocked( VSIGZipHandle* poHandle ) /* Open() */ /************************************************************************/ -VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess) +VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */ ) { - VSIFilesystemHandler *poFSHandler = + VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( pszFilename + strlen("/vsigzip/")); /* -------------------------------------------------------------------- */ @@ -1394,10 +1398,10 @@ VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename, /* OpenGZipReadOnly() */ /************************************************************************/ -VSIGZipHandle* VSIGZipFilesystemHandler::OpenGZipReadOnly( const char *pszFilename, +VSIGZipHandle* VSIGZipFilesystemHandler::OpenGZipReadOnly( const char *pszFilename, const char *pszAccess) { - VSIFilesystemHandler *poFSHandler = + VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( pszFilename + strlen("/vsigzip/")); CPLMutexHolder oHolder(&hMutex); @@ -1485,7 +1489,7 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename, if (STARTS_WITH_CI(pszLine, "compressed_size=")) { const char* pszBuffer = pszLine + strlen("compressed_size="); - nCompressedSize = + nCompressedSize = CPLScanUIntBig(pszBuffer, static_cast(strlen(pszBuffer))); } else if (STARTS_WITH_CI(pszLine, "uncompressed_size=")) @@ -1593,9 +1597,9 @@ char** VSIGZipFilesystemHandler::ReadDirEx( const char * /*pszDirname*/, /** - * \brief Install GZip file system handler. + * \brief Install GZip file system handler. * - * A special file handler is installed that allows reading on-the-fly and + * A special file handler is installed that allows reading on-the-fly and * writing in GZip (.gz) files. * * All portions of the file system underneath the base @@ -1766,7 +1770,7 @@ int VSIZipReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset) class VSIZipWriteHandle; -class VSIZipFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler +class VSIZipFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler { std::map oMapZipWriteHandles; VSIVirtualHandle *OpenForWrite_unlocked( const char *pszFilename, @@ -1779,8 +1783,11 @@ class VSIZipFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler virtual std::vector GetExtensions(); virtual VSIArchiveReader* CreateReader(const char* pszZipFileName); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual VSIVirtualHandle *OpenForWrite( const char *pszFilename, const char *pszAccess ); @@ -1903,8 +1910,9 @@ VSIArchiveReader* VSIZipFilesystemHandler::CreateReader(const char* pszZipFileNa /* Open() */ /************************************************************************/ -VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess) +VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */ ) { CPLString osZipInFileName; @@ -1943,7 +1951,7 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename, return NULL; } - VSIFilesystemHandler *poFSHandler = + VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( zipFilename); VSIVirtualHandle* poVirtualHandle = @@ -2371,7 +2379,7 @@ void VSIZipWriteHandle::StartNewFile(VSIZipWriteHandle* poSubFile) /** - * \brief Install ZIP file system handler. + * \brief Install ZIP file system handler. * * A special file handler is installed that allows reading on-the-fly in ZIP * (.zip) archives. diff --git a/gdal/port/cpl_vsil_sparsefile.cpp b/gdal/port/cpl_vsil_sparsefile.cpp index 35233f6310d4..6826cfd3c97f 100644 --- a/gdal/port/cpl_vsil_sparsefile.cpp +++ b/gdal/port/cpl_vsil_sparsefile.cpp @@ -36,9 +36,9 @@ CPL_CVSID("$Id$"); -class SFRegion { +class SFRegion { public: - SFRegion() : fp(NULL), nDstOffset(0), nSrcOffset(0), nLength(0), + SFRegion() : fp(NULL), nDstOffset(0), nSrcOffset(0), nLength(0), byValue(0), bTriedOpen(FALSE) {} CPLString osFilename; @@ -59,7 +59,7 @@ class SFRegion { class VSISparseFileFilesystemHandler; class VSISparseFileHandle : public VSIVirtualHandle -{ +{ VSISparseFileFilesystemHandler* m_poFS; public: @@ -84,7 +84,7 @@ class VSISparseFileHandle : public VSIVirtualHandle /* ==================================================================== */ /************************************************************************/ -class VSISparseFileFilesystemHandler : public VSIFilesystemHandler +class VSISparseFileFilesystemHandler : public VSIFilesystemHandler { std::map oRecOpenCount; @@ -92,13 +92,16 @@ class VSISparseFileFilesystemHandler : public VSIFilesystemHandler VSISparseFileFilesystemHandler(); virtual ~VSISparseFileFilesystemHandler(); - int DecomposePath( const char *pszPath, - CPLString &osFilename, + int DecomposePath( const char *pszPath, + CPLString &osFilename, vsi_l_offset &nSparseFileOffset, vsi_l_offset &nSparseFileSize ); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); virtual int Mkdir( const char *pszDirname, long nMode ); @@ -205,18 +208,18 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount ) /* -------------------------------------------------------------------- */ size_t nReturnCount = nCount; GUIntBig nBytesRequested = nSize * nCount; - GUIntBig nBytesAvailable = + GUIntBig nBytesAvailable = aoRegions[iRegion].nDstOffset + aoRegions[iRegion].nLength; if( nCurOffset + nBytesRequested > nBytesAvailable ) { - size_t nExtraBytes = + size_t nExtraBytes = (size_t) (nCurOffset + nBytesRequested - nBytesAvailable); // Recurse to get the rest of the request. GUIntBig nCurOffsetSave = nCurOffset; nCurOffset += nBytesRequested - nExtraBytes; - size_t nBytesRead = + size_t nBytesRead = this->Read( ((char *) pBuffer) + nBytesRequested - nExtraBytes, 1, nExtraBytes ); nCurOffset = nCurOffsetSave; @@ -232,7 +235,7 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount ) /* -------------------------------------------------------------------- */ if( aoRegions[iRegion].osFilename.size() == 0 ) { - memset( pBuffer, aoRegions[iRegion].byValue, + memset( pBuffer, aoRegions[iRegion].byValue, (size_t) nBytesRequested ); } @@ -245,11 +248,11 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount ) { if( !aoRegions[iRegion].bTriedOpen ) { - aoRegions[iRegion].fp = + aoRegions[iRegion].fp = VSIFOpenL( aoRegions[iRegion].osFilename, "r" ); if( aoRegions[iRegion].fp == NULL ) { - CPLDebug( "/vsisparse/", "Failed to open '%s'.", + CPLDebug( "/vsisparse/", "Failed to open '%s'.", aoRegions[iRegion].osFilename.c_str() ); } aoRegions[iRegion].bTriedOpen = TRUE; @@ -260,15 +263,15 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount ) } } - if( VSIFSeekL( aoRegions[iRegion].fp, - nCurOffset - - aoRegions[iRegion].nDstOffset + if( VSIFSeekL( aoRegions[iRegion].fp, + nCurOffset + - aoRegions[iRegion].nDstOffset + aoRegions[iRegion].nSrcOffset, SEEK_SET ) != 0 ) return 0; m_poFS->IncRecCounter(); - size_t nBytesRead = VSIFReadL( pBuffer, 1, (size_t) nBytesRequested, + size_t nBytesRead = VSIFReadL( pBuffer, 1, (size_t) nBytesRequested, aoRegions[iRegion].fp ); m_poFS->DecRecCounter(); @@ -332,8 +335,9 @@ VSISparseFileFilesystemHandler::~VSISparseFileFilesystemHandler() /************************************************************************/ VSIVirtualHandle * -VSISparseFileFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess ) +VSISparseFileFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */) { CPLAssert( STARTS_WITH_CI(pszFilename, "/vsisparse/") ); @@ -397,14 +401,14 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename, oRegion.osFilename, NULL ); } - oRegion.nDstOffset = + oRegion.nDstOffset = CPLScanUIntBig( CPLGetXMLValue(psRegion,"DestinationOffset","0" ), 32 ); - oRegion.nSrcOffset = + oRegion.nSrcOffset = CPLScanUIntBig( CPLGetXMLValue(psRegion,"SourceOffset","0" ), 32); - oRegion.nLength = + oRegion.nLength = CPLScanUIntBig( CPLGetXMLValue(psRegion,"RegionLength","0" ), 32); oRegion.byValue = (GByte) atoi(CPLGetXMLValue(psRegion,"Value","0" )); @@ -416,7 +420,7 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename, /* Get sparse file length, use maximum bound of regions if not */ /* explicit in file. */ /* -------------------------------------------------------------------- */ - poHandle->nOverallLength = + poHandle->nOverallLength = CPLScanUIntBig( CPLGetXMLValue(psXMLRoot,"Length","0" ), 32); if( poHandle->nOverallLength == 0 ) { @@ -437,7 +441,7 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename, /* Stat() */ /************************************************************************/ -int VSISparseFileFilesystemHandler::Stat( const char * pszFilename, +int VSISparseFileFilesystemHandler::Stat( const char * pszFilename, VSIStatBufL * psStatBuf, int nFlags ) @@ -453,7 +457,7 @@ int VSISparseFileFilesystemHandler::Stat( const char * pszFilename, size_t nLength = (size_t) poFile->Tell(); delete poFile; - int nResult = VSIStatExL( pszFilename + strlen("/vsisparse/"), + int nResult = VSIStatExL( pszFilename + strlen("/vsisparse/"), psStatBuf, nFlags ); psStatBuf->st_size = nLength; @@ -507,7 +511,7 @@ char **VSISparseFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath ) /************************************************************************/ /** - * Install /vsisparse/ virtual file handler. + * Install /vsisparse/ virtual file handler. * * The sparse virtual file handler allows a virtual file to be composed * from chunks of data in other files, potentially with large spaces in @@ -515,10 +519,10 @@ char **VSISparseFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath ) * test some sorts of operations on what seems to be a large file with * image data set to a constant value. It is also helpful when wanting to * add test files to the test suite that are too large, but for which most - * of the data can be ignored. It could, in theory, also be used to - * treat several files on different file systems as one large virtual file. + * of the data can be ignored. It could, in theory, also be used to + * treat several files on different file systems as one large virtual file. * - * The file referenced by /vsisparse/ should be an XML control file + * The file referenced by /vsisparse/ should be an XML control file * formatted something like: * * @@ -554,13 +558,13 @@ char **VSISparseFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath ) \endverbatim * - * Hopefully the values and semantics are fairly obvious. + * Hopefully the values and semantics are fairly obvious. * - * This driver is installed by default. + * This driver is installed by default. */ void VSIInstallSparseFileHandler() { - VSIFileManager::InstallHandler( "/vsisparse/", + VSIFileManager::InstallHandler( "/vsisparse/", new VSISparseFileFilesystemHandler ); } diff --git a/gdal/port/cpl_vsil_stdin.cpp b/gdal/port/cpl_vsil_stdin.cpp index bf11ce54d8f4..5e2ee975cf00 100644 --- a/gdal/port/cpl_vsil_stdin.cpp +++ b/gdal/port/cpl_vsil_stdin.cpp @@ -14,16 +14,16 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ @@ -75,8 +75,11 @@ class VSIStdinFilesystemHandler CPL_FINAL : public VSIFilesystemHandler VSIStdinFilesystemHandler(); virtual ~VSIStdinFilesystemHandler(); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); }; @@ -330,8 +333,9 @@ VSIStdinFilesystemHandler::~VSIStdinFilesystemHandler() /************************************************************************/ VSIVirtualHandle * -VSIStdinFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess ) +VSIStdinFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */ ) { if (strcmp(pszFilename, "/vsistdin/") != 0) diff --git a/gdal/port/cpl_vsil_stdout.cpp b/gdal/port/cpl_vsil_stdout.cpp index fb58839c984f..d749cde32cd2 100644 --- a/gdal/port/cpl_vsil_stdout.cpp +++ b/gdal/port/cpl_vsil_stdout.cpp @@ -14,16 +14,16 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ @@ -48,10 +48,10 @@ static FILE* pWriteStream = stdout; /** Set an alternative write function and output file handle instead of * fwrite() / stdout. - * + * * @param pFct Function with same signature as fwrite() * @param stream File handle on which to output. Passed to pFct. - * + * * @since GDAL 2.0 */ void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream ) @@ -70,8 +70,11 @@ void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream ) class VSIStdoutFilesystemHandler CPL_FINAL : public VSIFilesystemHandler { public: - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); }; @@ -150,7 +153,7 @@ size_t VSIStdoutHandle::Read( CPL_UNUSED void * pBuffer, /* Write() */ /************************************************************************/ -size_t VSIStdoutHandle::Write( const void * pBuffer, size_t nSize, +size_t VSIStdoutHandle::Write( const void * pBuffer, size_t nSize, size_t nCount ) { @@ -191,7 +194,8 @@ int VSIStdoutHandle::Close() VSIVirtualHandle * VSIStdoutFilesystemHandler::Open( CPL_UNUSED const char *pszFilename, - const char *pszAccess ) + const char *pszAccess, + bool /* bSetError */ ) { if ( strchr(pszAccess, 'r') != NULL || strchr(pszAccess, '+') != NULL ) @@ -234,8 +238,11 @@ int VSIStdoutFilesystemHandler::Stat( CPL_UNUSED const char * pszFilename, class VSIStdoutRedirectFilesystemHandler CPL_FINAL : public VSIFilesystemHandler { public: + using VSIFilesystemHandler::Open; + virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); }; @@ -364,7 +371,8 @@ int VSIStdoutRedirectHandle::Close() VSIVirtualHandle * VSIStdoutRedirectFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess ) + const char *pszAccess, + bool /* bSetError */ ) { if ( strchr(pszAccess, 'r') != NULL || diff --git a/gdal/port/cpl_vsil_subfile.cpp b/gdal/port/cpl_vsil_subfile.cpp index 2d61d32bbe2a..685337dace0b 100644 --- a/gdal/port/cpl_vsil_subfile.cpp +++ b/gdal/port/cpl_vsil_subfile.cpp @@ -42,7 +42,7 @@ CPL_CVSID("$Id$"); /************************************************************************/ class VSISubFileHandle : public VSIVirtualHandle -{ +{ public: VSILFILE *fp; vsi_l_offset nSubregionOffset; @@ -65,19 +65,22 @@ class VSISubFileHandle : public VSIVirtualHandle /* ==================================================================== */ /************************************************************************/ -class VSISubFileFilesystemHandler : public VSIFilesystemHandler +class VSISubFileFilesystemHandler : public VSIFilesystemHandler { public: VSISubFileFilesystemHandler(); virtual ~VSISubFileFilesystemHandler(); - int DecomposePath( const char *pszPath, - CPLString &osFilename, + int DecomposePath( const char *pszPath, + CPLString &osFilename, vsi_l_offset &nSubFileOffset, vsi_l_offset &nSubFileSize ); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); virtual int Mkdir( const char *pszDirname, long nMode ); @@ -300,8 +303,9 @@ VSISubFileFilesystemHandler::DecomposePath( const char *pszPath, /************************************************************************/ VSIVirtualHandle * -VSISubFileFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess ) +VSISubFileFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */ ) { CPLString osSubFilePath; @@ -350,7 +354,7 @@ VSISubFileFilesystemHandler::Open( const char *pszFilename, /* Stat() */ /************************************************************************/ -int VSISubFileFilesystemHandler::Stat( const char * pszFilename, +int VSISubFileFilesystemHandler::Stat( const char * pszFilename, VSIStatBufL * psStatBuf, int nFlags ) @@ -426,11 +430,11 @@ char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath ) /************************************************************************/ /** - * Install /vsisubfile/ virtual file handler. + * Install /vsisubfile/ virtual file handler. * - * This virtual file system handler allows access to subregions of - * files, treating them as a file on their own to the virtual file - * system functions (VSIFOpenL(), etc). + * This virtual file system handler allows access to subregions of + * files, treating them as a file on their own to the virtual file + * system functions (VSIFOpenL(), etc). * * A special form of the filename is used to indicate a subportion * of another file: @@ -439,11 +443,11 @@ char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath ) * * The size parameter is optional. Without it the remainder of the * file from the start offset as treated as part of the subfile. Otherwise - * only bytes from are treated as part of the subfile. - * The portion may be a relative or absolute path using normal - * rules. The and values are in bytes. + * only bytes from are treated as part of the subfile. + * The portion may be a relative or absolute path using normal + * rules. The and values are in bytes. * - * eg. + * eg. * /vsisubfile/1000_3000,/data/abc.ntf * /vsisubfile/5000,../xyz/raw.dat * @@ -451,12 +455,11 @@ char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath ) * is no meaningful support for filesystem operations for creating new * files, traversing directories, and deleting files within the /vsisubfile/ * area. Only the VSIStatL(), VSIFOpenL() and operations based on the file - * handle returned by VSIFOpenL() operate properly. + * handle returned by VSIFOpenL() operate properly. */ void VSIInstallSubFileHandler() { - VSIFileManager::InstallHandler( "/vsisubfile/", + VSIFileManager::InstallHandler( "/vsisubfile/", new VSISubFileFilesystemHandler ); } - diff --git a/gdal/port/cpl_vsil_tar.cpp b/gdal/port/cpl_vsil_tar.cpp index a835dafcfe4a..b2696bc452f0 100644 --- a/gdal/port/cpl_vsil_tar.cpp +++ b/gdal/port/cpl_vsil_tar.cpp @@ -345,15 +345,18 @@ int VSITarReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset) /* ==================================================================== */ /************************************************************************/ -class VSITarFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler +class VSITarFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler { public: virtual const char* GetPrefix() { return "/vsitar"; } virtual std::vector GetExtensions(); virtual VSIArchiveReader* CreateReader(const char* pszTarFileName); - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); }; @@ -407,8 +410,9 @@ VSIArchiveReader* VSITarFilesystemHandler::CreateReader(const char* pszTarFileNa /* Open() */ /************************************************************************/ -VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess) +VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */ ) { if (strchr(pszAccess, 'w') != NULL || diff --git a/gdal/port/cpl_vsil_unix_stdio_64.cpp b/gdal/port/cpl_vsil_unix_stdio_64.cpp index 48688e2269f2..5759b7bf0be4 100644 --- a/gdal/port/cpl_vsil_unix_stdio_64.cpp +++ b/gdal/port/cpl_vsil_unix_stdio_64.cpp @@ -52,6 +52,7 @@ #if !defined(WIN32) #include "cpl_vsi_virtual.h" +#include "cpl_vsi_error.h" #include "cpl_string.h" #include "cpl_multiproc.h" @@ -117,7 +118,7 @@ CPL_CVSID("$Id$"); /* ==================================================================== */ /************************************************************************/ -class VSIUnixStdioFilesystemHandler CPL_FINAL : public VSIFilesystemHandler +class VSIUnixStdioFilesystemHandler CPL_FINAL : public VSIFilesystemHandler { #ifdef VSI_COUNT_BYTES_READ vsi_l_offset nTotalBytesRead; @@ -130,8 +131,11 @@ class VSIUnixStdioFilesystemHandler CPL_FINAL : public VSIFilesystemHandler virtual ~VSIUnixStdioFilesystemHandler(); #endif + using VSIFilesystemHandler::Open; + virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); @@ -510,7 +514,8 @@ VSIUnixStdioFilesystemHandler::~VSIUnixStdioFilesystemHandler() VSIVirtualHandle * VSIUnixStdioFilesystemHandler::Open( const char *pszFilename, - const char *pszAccess ) + const char *pszAccess, + bool bSetError ) { FILE *fp = VSI_FOPEN64( pszFilename, pszAccess ); @@ -521,6 +526,7 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename, if( fp == NULL ) { + if(bSetError) { VSIError(VSIE_FileError, "%s", strerror(nError)); } errno = nError; return NULL; } diff --git a/gdal/port/cpl_vsil_win32.cpp b/gdal/port/cpl_vsil_win32.cpp index d109f47b8c2b..8c69787f4a40 100644 --- a/gdal/port/cpl_vsil_win32.cpp +++ b/gdal/port/cpl_vsil_win32.cpp @@ -15,16 +15,16 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ @@ -49,11 +49,15 @@ CPL_CVSID("$Id$"); /* ==================================================================== */ /************************************************************************/ -class VSIWin32FilesystemHandler CPL_FINAL : public VSIFilesystemHandler +class VSIWin32FilesystemHandler CPL_FINAL : public VSIFilesystemHandler { public: - virtual VSIVirtualHandle *Open( const char *pszFilename, - const char *pszAccess); + + using VSIFilesystemHandler::Open; + + virtual VSIVirtualHandle *Open( const char *pszFilename, + const char *pszAccess, + bool bSetError ); virtual int Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ); virtual int Unlink( const char *pszFilename ); virtual int Rename( const char *oldpath, const char *newpath ); @@ -95,7 +99,7 @@ class VSIWin32Handle CPL_FINAL : public VSIVirtualHandle /* */ /* TODO: If the function is going to be public CPL function, then */ /* replace the switch with array of (Win32 code, errno code) tuples and */ -/* complement it with missing codes. */ +/* complement it with missing codes. */ /************************************************************************/ static int ErrnoFromGetLastError(DWORD dwError = 0) @@ -224,15 +228,15 @@ int VSIWin32Handle::Seek( vsi_l_offset nOffset, int nWhence ) #ifdef notdef LPVOID lpMsgBuf = NULL; - FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf ); - printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n", + printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n", (GUInt32) nOffset, nMoveLow, dwMoveHigh ); #endif errno = ErrnoFromGetLastError(); @@ -252,7 +256,7 @@ vsi_l_offset VSIWin32Handle::Tell() LARGE_INTEGER li; li.HighPart = 0; - li.LowPart = SetFilePointer( hFile, 0, (PLONG) &(li.HighPart), + li.LowPart = SetFilePointer( hFile, 0, (PLONG) &(li.HighPart), FILE_CURRENT ); return (static_cast(li.QuadPart)); @@ -467,8 +471,9 @@ static bool VSIWin32IsLongFilename( const wchar_t* pwszFilename ) /* Open() */ /************************************************************************/ -VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, - const char *pszAccess ) +VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, + const char *pszAccess, + bool /* bSetError */ ) { DWORD dwDesiredAccess, dwCreationDisposition, dwFlagsAndAttributes; @@ -484,7 +489,7 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, // Append is read and write but not overwrite data (only append data) if (strchr(pszAccess, 'a') != NULL ) { - dwDesiredAccess = + dwDesiredAccess = FILE_GENERIC_READ | (FILE_GENERIC_WRITE ^ FILE_WRITE_DATA); // Wine < 1.7.4 doesn't work properly without FILE_WRITE_DATA bit @@ -521,7 +526,7 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, else dwCreationDisposition = OPEN_EXISTING; - dwFlagsAndAttributes = (dwDesiredAccess == GENERIC_READ) ? + dwFlagsAndAttributes = (dwDesiredAccess == GENERIC_READ) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL; /* -------------------------------------------------------------------- */ @@ -532,11 +537,11 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, if( CSLTestBoolean( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) ) { - wchar_t *pwszFilename = + wchar_t *pwszFilename = CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 ); - hFile = CreateFileW( pwszFilename, dwDesiredAccess, - FILE_SHARE_READ | FILE_SHARE_WRITE, + hFile = CreateFileW( pwszFilename, dwDesiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL ); if ( hFile == INVALID_HANDLE_VALUE && @@ -562,8 +567,8 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, { VSIWin32TryLongFilename(pwszFilename); nLastError = 0; - hFile = CreateFileW( pwszFilename, dwDesiredAccess, - FILE_SHARE_READ | FILE_SHARE_WRITE, + hFile = CreateFileW( pwszFilename, dwDesiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL ); } @@ -571,8 +576,8 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, } else { - hFile = CreateFile( pszFilename, dwDesiredAccess, - FILE_SHARE_READ | FILE_SHARE_WRITE, + hFile = CreateFile( pszFilename, dwDesiredAccess, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL ); } @@ -613,7 +618,7 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename, /* Stat() */ /************************************************************************/ -int VSIWin32FilesystemHandler::Stat( const char * pszFilename, +int VSIWin32FilesystemHandler::Stat( const char * pszFilename, VSIStatBufL * pStatBuf, int nFlags ) @@ -625,7 +630,7 @@ int VSIWin32FilesystemHandler::Stat( const char * pszFilename, CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) ) { int nResult; - wchar_t *pwszFilename = + wchar_t *pwszFilename = CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 ); bool bTryOtherStatImpl = false; @@ -694,7 +699,7 @@ int VSIWin32FilesystemHandler::Unlink( const char * pszFilename ) CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) ) { int nResult; - wchar_t *pwszFilename = + wchar_t *pwszFilename = CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 ); nResult = _wunlink( pwszFilename ); @@ -721,9 +726,9 @@ int VSIWin32FilesystemHandler::Rename( const char *oldpath, CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) ) { int nResult; - wchar_t *pwszOldPath = + wchar_t *pwszOldPath = CPLRecodeToWChar( oldpath, CPL_ENC_UTF8, CPL_ENC_UCS2 ); - wchar_t *pwszNewPath = + wchar_t *pwszNewPath = CPLRecodeToWChar( newpath, CPL_ENC_UTF8, CPL_ENC_UCS2 ); nResult = _wrename( pwszOldPath, pwszNewPath ); @@ -752,7 +757,7 @@ int VSIWin32FilesystemHandler::Mkdir( const char * pszPathname, CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) ) { int nResult; - wchar_t *pwszFilename = + wchar_t *pwszFilename = CPLRecodeToWChar( pszPathname, CPL_ENC_UTF8, CPL_ENC_UCS2 ); nResult = _wmkdir( pwszFilename ); @@ -778,7 +783,7 @@ int VSIWin32FilesystemHandler::Rmdir( const char * pszPathname ) CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) ) { int nResult; - wchar_t *pwszFilename = + wchar_t *pwszFilename = CPLRecodeToWChar( pszPathname, CPL_ENC_UTF8, CPL_ENC_UCS2 ); nResult = _wrmdir( pwszFilename ); @@ -813,7 +818,7 @@ char **VSIWin32FilesystemHandler::ReadDirEx( const char *pszPath, pszPath = "."; pszFileSpec = CPLStrdup(CPLSPrintf("%s\\*.*", pszPath)); - wchar_t *pwszFileSpec = + wchar_t *pwszFileSpec = CPLRecodeToWChar( pszFileSpec, CPL_ENC_UTF8, CPL_ENC_UCS2 ); if ( (hFile = _wfindfirst( pwszFileSpec, &c_file )) != -1L ) @@ -830,7 +835,7 @@ char **VSIWin32FilesystemHandler::ReadDirEx( const char *pszPath, } else { - /* Should we generate an error??? + /* Should we generate an error??? * For now we'll just return NULL (at the end of the function) */ } @@ -866,7 +871,7 @@ char **VSIWin32FilesystemHandler::ReadDirEx( const char *pszPath, } else { - /* Should we generate an error??? + /* Should we generate an error??? * For now we'll just return NULL (at the end of the function) */ }