int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptionsIn ) { VSIStatBufL stat; /* -------------------------------------------------------------------- */ /* Try to create directory if it doesn't already exist. */ /* -------------------------------------------------------------------- */ if( VSIStatL( pszNameIn, &stat ) != 0 ) { VSIMkdir( pszNameIn, 0755 ); } if( VSIStatL( pszNameIn, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) ) { CPLError( CE_Failure, CPLE_AppDefined, "%s is not a directory, nor can be directly created as one.", pszNameIn ); return FALSE; } /* -------------------------------------------------------------------- */ /* Store various information. */ /* -------------------------------------------------------------------- */ pszPath = CPLStrdup( pszNameIn ); pszName = CPLStrdup( pszNameIn ); bWriteMode = true; SetOptionList( papszOptionsIn ); /* -------------------------------------------------------------------- */ /* Work out the version. */ /* -------------------------------------------------------------------- */ // nVersionCode = 1000; /* census 2000 */ nVersionCode = 1002; /* census 2002 */ if( GetOption("VERSION") != nullptr ) { nVersionCode = atoi(GetOption("VERSION")); nVersionCode = std::max(0, std::min(9999, nVersionCode)); } nVersion = TigerClassifyVersion(nVersionCode); return TRUE; }
static void ProcessIdentifyTarget( const char *pszTarget, char **papszSiblingList, bool bRecursive, bool bReportFailures, bool bForceRecurse ) { GDALDriverH hDriver; VSIStatBufL sStatBuf; int i; hDriver = GDALIdentifyDriver( pszTarget, papszSiblingList ); if( hDriver != nullptr ) printf( "%s: %s\n", pszTarget, GDALGetDriverShortName( hDriver ) ); else if( bReportFailures ) printf( "%s: unrecognized\n", pszTarget ); if( !bForceRecurse && (!bRecursive || hDriver != nullptr) ) return; if( VSIStatL( pszTarget, &sStatBuf ) != 0 || !VSI_ISDIR( sStatBuf.st_mode ) ) return; papszSiblingList = VSIReadDir( pszTarget ); for( i = 0; papszSiblingList && papszSiblingList[i]; i++ ) { if( EQUAL(papszSiblingList[i],"..") || EQUAL(papszSiblingList[i],".") ) continue; CPLString osSubTarget = CPLFormFilename( pszTarget, papszSiblingList[i], nullptr ); ProcessIdentifyTarget( osSubTarget, papszSiblingList, bRecursive, bReportFailures, bForceRecurse ); } CSLDestroy(papszSiblingList); }
bool wxGxLocalDBFactory::GetChildren(wxGxObject* pParent, char** &pFileNames, wxArrayLong & pChildrenIds) { wxGxCatalogBase* pCatalog = GetGxCatalog(); bool bCheckNames = CSLCount(pFileNames) < CHECK_DUBLES_MAX_COUNT; for(int i = CSLCount(pFileNames) - 1; i >= 0; i-- ) { VSIStatBufL BufL; int ret = VSIStatL(pFileNames[i], &BufL); if(ret == 0) { if (VSI_ISDIR(BufL.st_mode) && wxGISEQUAL(CPLGetExtension(pFileNames[i]), "gdb")) { wxGxObject* pObj = GetGxObject(pParent, wxString(CPLGetFilename(pFileNames[i]), wxConvUTF8), pFileNames[i], enumContGDBFolder, bCheckNames); if(pObj) pChildrenIds.Add(pObj->GetId()); pFileNames = CSLRemoveStrings( pFileNames, i, 1, NULL ); } //TODO: mdb, sqlite, db extensions } } return true; }
OGRLayer * OGRCSVDataSource::ICreateLayer( const char *pszLayerName, CPL_UNUSED OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType, char ** papszOptions ) { /* -------------------------------------------------------------------- */ /* Verify we are in update mode. */ /* -------------------------------------------------------------------- */ if (!bUpdate) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "New layer %s cannot be created.\n", pszName, pszLayerName ); return NULL; } /* -------------------------------------------------------------------- */ /* Verify that the datasource is a directory. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; if( strncmp(pszName, "/vsizip/", 8) == 0) { /* Do nothing */ } else if( !EQUAL(pszName, "/vsistdout/") && (VSIStatL( pszName, &sStatBuf ) != 0 || !VSI_ISDIR( sStatBuf.st_mode )) ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create csv layer (file) against a non-directory datasource." ); return NULL; } /* -------------------------------------------------------------------- */ /* What filename would we use? */ /* -------------------------------------------------------------------- */ CPLString osFilename; if( osDefaultCSVName != "" ) { osFilename = CPLFormFilename( pszName, osDefaultCSVName, NULL ); osDefaultCSVName = ""; } else { osFilename = CPLFormFilename( pszName, pszLayerName, "csv" ); } /* -------------------------------------------------------------------- */ /* Does this directory/file already exist? */ /* -------------------------------------------------------------------- */ if( VSIStatL( osFilename, &sStatBuf ) == 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create layer %s, but %s already exists.", pszLayerName, osFilename.c_str() ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the empty file. */ /* -------------------------------------------------------------------- */ const char *pszDelimiter = CSLFetchNameValue( papszOptions, "SEPARATOR"); char chDelimiter = ','; if (pszDelimiter != NULL) { if (EQUAL(pszDelimiter, "COMMA")) chDelimiter = ','; else if (EQUAL(pszDelimiter, "SEMICOLON")) chDelimiter = ';'; else if (EQUAL(pszDelimiter, "TAB")) chDelimiter = '\t'; else if (EQUAL(pszDelimiter, "SPACE")) chDelimiter = ' '; else { CPLError( CE_Warning, CPLE_AppDefined, "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON, SPACE or TAB.", pszDelimiter ); } } /* -------------------------------------------------------------------- */ /* Create a layer. */ /* -------------------------------------------------------------------- */ nLayers++; papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, sizeof(void*) * nLayers); papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, NULL, osFilename, TRUE, TRUE, chDelimiter ); papoLayers[nLayers-1]->BuildFeatureDefn(); /* -------------------------------------------------------------------- */ /* Was a partiuclar CRLF order requested? */ /* -------------------------------------------------------------------- */ const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT"); int bUseCRLF; if( pszCRLFFormat == NULL ) { #ifdef WIN32 bUseCRLF = TRUE; #else bUseCRLF = FALSE; #endif } else if( EQUAL(pszCRLFFormat,"CRLF") ) bUseCRLF = TRUE; else if( EQUAL(pszCRLFFormat,"LF") ) bUseCRLF = FALSE; else { CPLError( CE_Warning, CPLE_AppDefined, "LINEFORMAT=%s not understood, use one of CRLF or LF.", pszCRLFFormat ); #ifdef WIN32 bUseCRLF = TRUE; #else bUseCRLF = FALSE; #endif } papoLayers[nLayers-1]->SetCRLF( bUseCRLF ); /* -------------------------------------------------------------------- */ /* Should we write the geometry ? */ /* -------------------------------------------------------------------- */ const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY"); if( bEnableGeometryFields ) { papoLayers[nLayers-1]->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT); } else if (pszGeometry != NULL) { if (EQUAL(pszGeometry, "AS_WKT")) { papoLayers[nLayers-1]->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT); } else if (EQUAL(pszGeometry, "AS_XYZ") || EQUAL(pszGeometry, "AS_XY") || EQUAL(pszGeometry, "AS_YX")) { if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint) { papoLayers[nLayers-1]->SetWriteGeometry(eGType, EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ : EQUAL(pszGeometry, "AS_XY") ? OGR_CSV_GEOM_AS_XY : OGR_CSV_GEOM_AS_YX); } else { CPLError( CE_Warning, CPLE_AppDefined, "Geometry type %s is not compatible with GEOMETRY=AS_XYZ.", OGRGeometryTypeToName(eGType) ); } } else { CPLError( CE_Warning, CPLE_AppDefined, "Unsupported value %s for creation option GEOMETRY", pszGeometry ); } } /* -------------------------------------------------------------------- */ /* Should we create a CSVT file ? */ /* -------------------------------------------------------------------- */ const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT"); if (pszCreateCSVT) papoLayers[nLayers-1]->SetCreateCSVT(CSLTestBoolean(pszCreateCSVT)); /* -------------------------------------------------------------------- */ /* Should we write a UTF8 BOM ? */ /* -------------------------------------------------------------------- */ const char *pszWriteBOM = CSLFetchNameValue( papszOptions, "WRITE_BOM"); if (pszWriteBOM) papoLayers[nLayers-1]->SetWriteBOM(CSLTestBoolean(pszWriteBOM)); return papoLayers[nLayers-1]; }
int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCreate) { // Check if a range is set and extract it and the filename const char *pszc=pszFilename; if (*pszFilename==0) return FALSE; while (*pszc) ++pszc; if (*(pszc-1)==']') { --pszc; while (pszc!=pszFilename && *pszc!='[') pszc--; if (pszc==pszFilename) return FALSE; poRange.setRange(pszc); } pszName = CPLStrdup( pszFilename ); pszName[pszc-pszFilename]=0; bUpdate = bUpdateIn; if (bCreate && EQUAL(pszName, "/vsistdout/")) return TRUE; /* For writable /vsizip/, do nothing more */ if (bCreate && STARTS_WITH(pszName, "/vsizip/")) return TRUE; CPLString osFilename(pszName); CPLString osBaseFilename = CPLGetFilename(pszName); // Determine what sort of object this is. VSIStatBufL sStatBuf; if (VSIStatExL( osFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0) return FALSE; // Is this a single Selafin file? if (VSI_ISREG(sStatBuf.st_mode)) return OpenTable( pszName ); // Is this a single a ZIP file with only a Selafin file inside ? if( STARTS_WITH(osFilename, "/vsizip/") && VSI_ISREG(sStatBuf.st_mode) ) { char** papszFiles = VSIReadDir(osFilename); if (CSLCount(papszFiles) != 1) { CSLDestroy(papszFiles); return FALSE; } osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL); CSLDestroy(papszFiles); return OpenTable( osFilename ); } #ifdef notdef // Otherwise it has to be a directory. if( !VSI_ISDIR(sStatBuf.st_mode) ) return FALSE; // Scan through for entries which look like Selafin files int nNotSelafinCount = 0, i; char **papszNames = VSIReadDir( osFilename ); for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ ) { CPLString oSubFilename = CPLFormFilename( osFilename, papszNames[i], NULL ); if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") ) continue; if( VSIStatL( oSubFilename, &sStatBuf ) != 0 || !VSI_ISREG(sStatBuf.st_mode) ) { nNotSelafinCount++; continue; } if( !OpenTable( oSubFilename ) ) { CPLDebug("Selafin", "Cannot open %s", oSubFilename.c_str()); nNotSelafinCount++; continue; } } CSLDestroy( papszNames ); // We presume that this is indeed intended to be a Selafin datasource if over half the files were Selafin files. return nNotSelafinCount < nLayers; #else return FALSE; #endif }
OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate ) { // First check if we have to do any work. int nLen = strlen(pszFilename); if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) || (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) ) return NULL; long hr; /* Check that the filename is really a directory, to avoid confusion with */ /* Garmin MapSource - gdb format which can be a problem when the FileGDB */ /* driver is loaded as a plugin, and loaded before the GPSBabel driver */ /* (http://trac.osgeo.org/osgeo4w/ticket/245) */ VSIStatBuf stat; if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) ) { return NULL; } CPLMutexHolderD(&hMutex); Geodatabase* pGeoDatabase = NULL; FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename]; if( pConnection != NULL ) { pGeoDatabase = pConnection->m_pGeodatabase; pConnection->m_nRefCount ++; CPLDebug("FileGDB", "ref_count of %s = %d now", pszFilename, pConnection->m_nRefCount); } else { pGeoDatabase = new Geodatabase; hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase); if (FAILED(hr) || pGeoDatabase == NULL) { delete pGeoDatabase; GDBErr(hr, "Failed to open Geodatabase"); return NULL; } CPLDebug("FileGDB", "Really opening %s", pszFilename); oMapConnections[pszFilename] = new FGdbDatabaseConnection(pGeoDatabase); } FGdbDataSource* pDS; pDS = new FGdbDataSource(this); if(!pDS->Open( pGeoDatabase, pszFilename, bUpdate ) ) { delete pDS; return NULL; } else return new OGRMutexedDataSource(pDS, TRUE, hMutex); }
int OGRTABDataSource::Open( const char * pszName, int bTestOpen ) { VSIStatBuf stat; CPLAssert( m_pszName == NULL ); m_pszName = CPLStrdup( pszName ); /* -------------------------------------------------------------------- */ /* Is this a file or directory? */ /* -------------------------------------------------------------------- */ if( VSIStat( pszName, &stat ) != 0 || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) ) { if( !bTestOpen ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s is not a file or directory.\n" "Unable to open as a Mapinfo dataset.\n", pszName ); } return FALSE; } /* -------------------------------------------------------------------- */ /* If it is a file, try to open as a Mapinfo file. */ /* -------------------------------------------------------------------- */ if( VSI_ISREG(stat.st_mode) ) { IMapInfoFile *poFile; poFile = IMapInfoFile::SmartOpen( pszName, bTestOpen ); if( poFile == NULL ) return FALSE; m_nLayerCount = 1; m_papoLayers = (IMapInfoFile **) CPLMalloc(sizeof(void*)); m_papoLayers[0] = poFile; m_pszDirectory = CPLStrdup( CPLGetPath(pszName) ); } /* -------------------------------------------------------------------- */ /* Otherwise, we need to scan the whole directory for files */ /* ending in .tab or .mif. */ /* -------------------------------------------------------------------- */ else { char **papszFileList = CPLReadDir( pszName ); m_pszDirectory = CPLStrdup( pszName ); for( int iFile = 0; papszFileList != NULL && papszFileList[iFile] != NULL; iFile++ ) { IMapInfoFile *poFile; const char *pszExtension = CPLGetExtension(papszFileList[iFile]); char *pszSubFilename; if( !EQUAL(pszExtension,"tab") && !EQUAL(pszExtension,"mif") ) continue; pszSubFilename = CPLStrdup( CPLFormFilename( m_pszDirectory, papszFileList[iFile], NULL )); poFile = IMapInfoFile::SmartOpen( pszSubFilename, bTestOpen ); CPLFree( pszSubFilename ); if( poFile == NULL ) { CSLDestroy( papszFileList ); return FALSE; } m_nLayerCount++; m_papoLayers = (IMapInfoFile **) CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount); m_papoLayers[m_nLayerCount-1] = poFile; } CSLDestroy( papszFileList ); if( m_nLayerCount == 0 ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_OpenFailed, "No mapinfo files found in directory %s.\n", m_pszDirectory ); return FALSE; } } return TRUE; }
OGRLayer * OGRCSVDataSource::ICreateLayer( const char *pszLayerName, OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType, char ** papszOptions ) { /* -------------------------------------------------------------------- */ /* Verify we are in update mode. */ /* -------------------------------------------------------------------- */ if( !bUpdate ) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "New layer %s cannot be created.", pszName, pszLayerName ); return NULL; } /* -------------------------------------------------------------------- */ /* Verify that the datasource is a directory. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; if( STARTS_WITH(pszName, "/vsizip/")) { /* Do nothing */ } else if( !EQUAL(pszName, "/vsistdout/") && (VSIStatL( pszName, &sStatBuf ) != 0 || !VSI_ISDIR( sStatBuf.st_mode )) ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create csv layer (file) against a " "non-directory datasource." ); return NULL; } /* -------------------------------------------------------------------- */ /* What filename would we use? */ /* -------------------------------------------------------------------- */ CPLString osFilename; if( osDefaultCSVName != "" ) { osFilename = CPLFormFilename( pszName, osDefaultCSVName, NULL ); osDefaultCSVName = ""; } else { osFilename = CPLFormFilename( pszName, pszLayerName, "csv" ); } /* -------------------------------------------------------------------- */ /* Does this directory/file already exist? */ /* -------------------------------------------------------------------- */ if( VSIStatL( osFilename, &sStatBuf ) == 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create layer %s, but %s already exists.", pszLayerName, osFilename.c_str() ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the empty file. */ /* -------------------------------------------------------------------- */ const char *pszDelimiter = CSLFetchNameValue( papszOptions, "SEPARATOR"); char chDelimiter = ','; if (pszDelimiter != NULL) { if (EQUAL(pszDelimiter, "COMMA")) chDelimiter = ','; else if (EQUAL(pszDelimiter, "SEMICOLON")) chDelimiter = ';'; else if (EQUAL(pszDelimiter, "TAB")) chDelimiter = '\t'; else if (EQUAL(pszDelimiter, "SPACE")) chDelimiter = ' '; else { CPLError( CE_Warning, CPLE_AppDefined, "SEPARATOR=%s not understood, use one of " "COMMA, SEMICOLON, SPACE or TAB.", pszDelimiter ); } } /* -------------------------------------------------------------------- */ /* Create a layer. */ /* -------------------------------------------------------------------- */ OGRCSVLayer* poCSVLayer = new OGRCSVLayer( pszLayerName, NULL, osFilename, true, true, chDelimiter ); poCSVLayer->BuildFeatureDefn(); /* -------------------------------------------------------------------- */ /* Was a particular CRLF order requested? */ /* -------------------------------------------------------------------- */ const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT"); bool bUseCRLF = false; if( pszCRLFFormat == NULL ) { #ifdef WIN32 bUseCRLF = true; #endif } else if( EQUAL(pszCRLFFormat, "CRLF") ) { bUseCRLF = true; } else if( EQUAL(pszCRLFFormat, "LF") ) { } else { CPLError( CE_Warning, CPLE_AppDefined, "LINEFORMAT=%s not understood, use one of CRLF or LF.", pszCRLFFormat ); #ifdef WIN32 bUseCRLF = true; #endif } poCSVLayer->SetCRLF( bUseCRLF ); /* -------------------------------------------------------------------- */ /* Should we write the geometry ? */ /* -------------------------------------------------------------------- */ const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY"); if( bEnableGeometryFields ) { poCSVLayer->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT, CSLFetchNameValueDef(papszOptions, "GEOMETRY_NAME", "WKT")); } else if (pszGeometry != NULL) { if (EQUAL(pszGeometry, "AS_WKT")) { poCSVLayer->SetWriteGeometry(eGType, OGR_CSV_GEOM_AS_WKT, CSLFetchNameValueDef(papszOptions, "GEOMETRY_NAME", "WKT")); } else if (EQUAL(pszGeometry, "AS_XYZ") || EQUAL(pszGeometry, "AS_XY") || EQUAL(pszGeometry, "AS_YX")) { if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint) { poCSVLayer->SetWriteGeometry( eGType, EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ : EQUAL(pszGeometry, "AS_XY") ? OGR_CSV_GEOM_AS_XY : OGR_CSV_GEOM_AS_YX); } else { CPLError( CE_Warning, CPLE_AppDefined, "Geometry type %s is not compatible with " "GEOMETRY=AS_XYZ.", OGRGeometryTypeToName(eGType) ); } } else { CPLError( CE_Warning, CPLE_AppDefined, "Unsupported value %s for creation option GEOMETRY", pszGeometry ); } } /* -------------------------------------------------------------------- */ /* Should we create a CSVT file ? */ /* -------------------------------------------------------------------- */ const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT"); if (pszCreateCSVT && CPLTestBool(pszCreateCSVT)) { poCSVLayer->SetCreateCSVT(true); /* -------------------------------------------------------------------- */ /* Create .prj file */ /* -------------------------------------------------------------------- */ if( poSpatialRef != NULL && osFilename != "/vsistdout/" ) { char* pszWKT = NULL; poSpatialRef->exportToWkt(&pszWKT); if( pszWKT ) { VSILFILE* fpPRJ = VSIFOpenL(CPLResetExtension(osFilename, "prj"), "wb"); if( fpPRJ ) { CPL_IGNORE_RET_VAL(VSIFPrintfL(fpPRJ, "%s\n", pszWKT)); VSIFCloseL(fpPRJ); } CPLFree(pszWKT); } } } /* -------------------------------------------------------------------- */ /* Should we write a UTF8 BOM ? */ /* -------------------------------------------------------------------- */ const char *pszWriteBOM = CSLFetchNameValue( papszOptions, "WRITE_BOM"); if( pszWriteBOM ) poCSVLayer->SetWriteBOM(CPLTestBool(pszWriteBOM)); nLayers++; papoLayers = static_cast<OGRLayer **>( CPLRealloc( papoLayers, sizeof(void*) * nLayers ) ); OGRLayer* poLayer = poCSVLayer; if( osFilename != "/vsistdout/" ) poLayer = new OGRCSVEditableLayer(poCSVLayer, NULL); papoLayers[nLayers-1] = poLayer; return poLayer; }
OGRDataSource *OGRGeoconceptDriver::CreateDataSource( const char* pszName, char** papszOptions ) { VSIStatBuf stat; int bSingleNewFile = FALSE; if( pszName==NULL || strlen(pszName)==0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid datasource name (null or empty)"); return NULL; } /* -------------------------------------------------------------------- */ /* Is the target a valid existing directory? */ /* -------------------------------------------------------------------- */ if( CPLStat( pszName, &stat ) == 0 ) { if( !VSI_ISDIR(stat.st_mode) ) { CPLError( CE_Failure, CPLE_AppDefined, "%s is not a valid existing directory.", pszName ); return NULL; } } /* -------------------------------------------------------------------- */ /* Does it end with the extension .gxt indicating the user likely */ /* wants to create a single file set? */ /* -------------------------------------------------------------------- */ else if( EQUAL(CPLGetExtension(pszName),"gxt") || EQUAL(CPLGetExtension(pszName),"txt") ) { bSingleNewFile = TRUE; } /* -------------------------------------------------------------------- */ /* Otherwise try to create a new directory. */ /* -------------------------------------------------------------------- */ else { VSIStatBuf sStat; if( VSIStat( pszName, &sStat ) == 0 ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create datasource named %s, " "but that is an existing directory.", pszName ); return NULL; } } /* -------------------------------------------------------------------- */ /* Return a new OGRDataSource() */ /* -------------------------------------------------------------------- */ OGRGeoconceptDataSource *poDS = NULL; poDS = new OGRGeoconceptDataSource(); if( !poDS->Create( pszName, papszOptions ) ) { delete poDS; return NULL; } return poDS; }
int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn) { if (bUpdateIn) { CPLError(CE_Failure, CPLE_NotSupported, "OGR/GPX driver does not support opening a file in update mode"); return FALSE; } #ifdef HAVE_EXPAT pszName = CPLStrdup( pszFilename ); /* -------------------------------------------------------------------- */ /* Determine what sort of object this is. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; if( VSIStatL( pszFilename, &sStatBuf ) != 0 ) return FALSE; if( VSI_ISDIR(sStatBuf.st_mode) ) return FALSE; VSILFILE* fp = VSIFOpenL(pszFilename, "r"); if (fp == NULL) return FALSE; validity = GPX_VALIDITY_UNKNOWN; CPLFree(pszVersion); pszVersion = NULL; bUseExtensions = FALSE; nElementsRead = 0; XML_Parser oParser = OGRCreateExpatXMLParser(); oCurrentParser = oParser; XML_SetUserData(oParser, this); XML_SetElementHandler(oParser, ::startElementValidateCbk, NULL); XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk); char aBuf[BUFSIZ]; int nDone; unsigned int nLen; int nCount = 0; /* Begin to parse the file and look for the <gpx> element */ /* It *MUST* be the first element of an XML file */ /* So once we have read the first element, we know if we can */ /* handle the file or not with that driver */ do { nDataHandlerCounter = 0; nLen = (unsigned int) VSIFReadL( aBuf, 1, sizeof(aBuf), fp ); nDone = VSIFEofL(fp); if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR) { if (nLen <= BUFSIZ-1) aBuf[nLen] = 0; else aBuf[BUFSIZ-1] = 0; if (strstr(aBuf, "<?xml") && strstr(aBuf, "<gpx")) { CPLError(CE_Failure, CPLE_AppDefined, "XML parsing of GPX file failed : %s at line %d, column %d", XML_ErrorString(XML_GetErrorCode(oParser)), (int)XML_GetCurrentLineNumber(oParser), (int)XML_GetCurrentColumnNumber(oParser)); } validity = GPX_VALIDITY_INVALID; break; } if (validity == GPX_VALIDITY_INVALID) { break; } else if (validity == GPX_VALIDITY_VALID) { /* If we have recognized the <gpx> element, now we try */ /* to recognize if they are <extensions> tags */ /* But we stop to look for after an arbitrary number of tags */ if (bUseExtensions) break; else if (nElementsRead > 200) break; } else { /* After reading 50 * BUFSIZE bytes, and not finding whether the file */ /* is GPX or not, we give up and fail silently */ nCount ++; if (nCount == 50) break; } } while (!nDone && nLen > 0 ); XML_ParserFree(oParser); VSIFCloseL(fp); if (validity == GPX_VALIDITY_VALID) { CPLDebug("GPX", "%s seems to be a GPX file.", pszFilename); if (bUseExtensions) CPLDebug("GPX", "It uses <extensions>"); if (pszVersion == NULL) { /* Default to 1.1 */ CPLError(CE_Warning, CPLE_AppDefined, "GPX schema version is unknown. " "The driver may not be able to handle the file correctly and will behave as if it is GPX 1.1."); pszVersion = CPLStrdup("1.1"); } else if (strcmp(pszVersion, "1.0") == 0 || strcmp(pszVersion, "1.1") == 0) { /* Fine */ } else { CPLError(CE_Warning, CPLE_AppDefined, "GPX schema version '%s' is not handled by the driver. " "The driver may not be able to handle the file correctly and will behave as if it is GPX 1.1.", pszVersion); } nLayers = 5; papoLayers = (OGRGPXLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRGPXLayer*)); papoLayers[0] = new OGRGPXLayer( pszName, "waypoints", GPX_WPT, this, FALSE ); papoLayers[1] = new OGRGPXLayer( pszName, "routes", GPX_ROUTE, this, FALSE ); papoLayers[2] = new OGRGPXLayer( pszName, "tracks", GPX_TRACK, this, FALSE ); papoLayers[3] = new OGRGPXLayer( pszName, "route_points", GPX_ROUTE_POINT, this, FALSE ); papoLayers[4] = new OGRGPXLayer( pszName, "track_points", GPX_TRACK_POINT, this, FALSE ); } return (validity == GPX_VALIDITY_VALID); #else char aBuf[256]; VSILFILE* fp = VSIFOpenL(pszFilename, "r"); if (fp) { unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, 255, fp ); aBuf[nLen] = 0; if (strstr(aBuf, "<?xml") && strstr(aBuf, "<gpx")) { CPLError(CE_Failure, CPLE_NotSupported, "OGR/GPX driver has not been built with read support. Expat library required"); } VSIFCloseL(fp); } return FALSE; #endif }
OGRDataSource *OGRShapeDriver::CreateDataSource( const char * pszName, CPL_UNUSED char **papszOptions ) { VSIStatBuf stat; int bSingleNewFile = FALSE; /* -------------------------------------------------------------------- */ /* Is the target a valid existing directory? */ /* -------------------------------------------------------------------- */ if( CPLStat( pszName, &stat ) == 0 ) { if( !VSI_ISDIR(stat.st_mode) ) { CPLError( CE_Failure, CPLE_AppDefined, "%s is not a directory.\n", pszName ); return NULL; } } /* -------------------------------------------------------------------- */ /* Does it end in the extension .shp indicating the user likely */ /* wants to create a single file set? */ /* -------------------------------------------------------------------- */ else if( EQUAL(CPLGetExtension(pszName),"shp") || EQUAL(CPLGetExtension(pszName),"dbf") ) { bSingleNewFile = TRUE; } /* -------------------------------------------------------------------- */ /* Otherwise try to create a new directory. */ /* -------------------------------------------------------------------- */ else { if( VSIMkdir( pszName, 0755 ) != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Failed to create directory %s\n" "for shapefile datastore.\n", pszName ); return NULL; } } /* -------------------------------------------------------------------- */ /* Return a new OGRDataSource() */ /* -------------------------------------------------------------------- */ OGRShapeDataSource *poDS = NULL; poDS = new OGRShapeDataSource(); if( !poDS->Open( pszName, TRUE, FALSE, bSingleNewFile ) ) { delete poDS; return NULL; } else return poDS; }
OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate ) { // First check if we have to do any work. size_t nLen = strlen(pszFilename); if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) || (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) ) return NULL; long hr; /* Check that the filename is really a directory, to avoid confusion with */ /* Garmin MapSource - gdb format which can be a problem when the FileGDB */ /* driver is loaded as a plugin, and loaded before the GPSBabel driver */ /* (http://trac.osgeo.org/osgeo4w/ticket/245) */ VSIStatBuf stat; if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) ) { return NULL; } CPLMutexHolderD(&hMutex); FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename]; if( pConnection != NULL ) { if( pConnection->IsFIDHackInProgress() ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot open geodatabase at the moment since it is in 'FID hack mode'"); return NULL; } pConnection->m_nRefCount ++; CPLDebug("FileGDB", "ref_count of %s = %d now", pszFilename, pConnection->m_nRefCount); } else { Geodatabase* pGeoDatabase = new Geodatabase; hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase); if (FAILED(hr)) { delete pGeoDatabase; if( OGRGetDriverByName("OpenFileGDB") != NULL && bUpdate == FALSE ) { std::wstring fgdb_error_desc_w; std::string fgdb_error_desc("Unknown error"); fgdbError er; er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w); if ( er == S_OK ) { fgdb_error_desc = WStringToString(fgdb_error_desc_w); } CPLDebug("FileGDB", "Cannot open %s with FileGDB driver: %s. Failing silently so OpenFileGDB can be tried", pszFilename, fgdb_error_desc.c_str()); } else { GDBErr(hr, "Failed to open Geodatabase"); } oMapConnections.erase(pszFilename); return NULL; } CPLDebug("FileGDB", "Really opening %s", pszFilename); pConnection = new FGdbDatabaseConnection(pszFilename, pGeoDatabase); oMapConnections[pszFilename] = pConnection; } FGdbDataSource* pDS; pDS = new FGdbDataSource(this, pConnection); if(!pDS->Open( pszFilename, bUpdate, NULL ) ) { delete pDS; return NULL; } else { OGRMutexedDataSource* poMutexedDS = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE); if( bUpdate ) return OGRCreateEmulatedTransactionDataSourceWrapper(poMutexedDS, this, TRUE, FALSE); else return poMutexedDS; } }
char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename, CPLString &osFileInArchive, int bCheckMainFileExists) { int i = 0; if (strcmp(pszFilename, GetPrefix()) == 0) return NULL; /* Allow natural chaining of VSI drivers without requiring double slash */ CPLString osDoubleVsi(GetPrefix()); osDoubleVsi += "/vsi"; if (strncmp(pszFilename, osDoubleVsi.c_str(), osDoubleVsi.size()) == 0) pszFilename += strlen(GetPrefix()); else pszFilename += strlen(GetPrefix()) + 1; while(pszFilename[i]) { std::vector<CPLString> oExtensions = GetExtensions(); std::vector<CPLString>::const_iterator iter; int nToSkip = 0; for( iter = oExtensions.begin(); iter != oExtensions.end(); ++iter ) { const CPLString& osExtension = *iter; if (EQUALN(pszFilename + i, osExtension.c_str(), strlen(osExtension.c_str()))) { nToSkip = strlen(osExtension.c_str()); break; } } if (nToSkip != 0) { VSIStatBufL statBuf; char* archiveFilename = CPLStrdup(pszFilename); int bArchiveFileExists = FALSE; if (archiveFilename[i + nToSkip] == '/' || archiveFilename[i + nToSkip] == '\\') { archiveFilename[i + nToSkip] = 0; } if (!bCheckMainFileExists) { bArchiveFileExists = TRUE; } else { CPLMutexHolder oHolder( &hMutex ); if (oFileList.find(archiveFilename) != oFileList.end() ) { bArchiveFileExists = TRUE; } } if (!bArchiveFileExists) { VSIFilesystemHandler *poFSHandler = VSIFileManager::GetHandler( archiveFilename ); if (poFSHandler->Stat(archiveFilename, &statBuf, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 && !VSI_ISDIR(statBuf.st_mode)) { bArchiveFileExists = TRUE; } } if (bArchiveFileExists) { if (pszFilename[i + nToSkip] == '/' || pszFilename[i + nToSkip] == '\\') { char* pszArchiveInFileName = CPLStrdup(pszFilename + i + nToSkip + 1); /* Replace a/../b by b and foo/a/../b by foo/b */ while(TRUE) { char* pszPrevDir = strstr(pszArchiveInFileName, "/../"); if (pszPrevDir == NULL || pszPrevDir == pszArchiveInFileName) break; char* pszPrevSlash = pszPrevDir - 1; while(pszPrevSlash != pszArchiveInFileName && *pszPrevSlash != '/') pszPrevSlash --; if (pszPrevSlash == pszArchiveInFileName) memmove(pszArchiveInFileName, pszPrevDir + nToSkip, strlen(pszPrevDir + nToSkip) + 1); else memmove(pszPrevSlash + 1, pszPrevDir + nToSkip, strlen(pszPrevDir + nToSkip) + 1); } osFileInArchive = pszArchiveInFileName; CPLFree(pszArchiveInFileName); } else osFileInArchive = ""; /* Remove trailing slash */ if (osFileInArchive.size()) { char lastC = osFileInArchive[strlen(osFileInArchive) - 1]; if (lastC == '\\' || lastC == '/') osFileInArchive.resize(strlen(osFileInArchive) - 1); } return archiveFilename; } CPLFree(archiveFilename); } i++; } return NULL; }
int OGRSVGDataSource::Open( const char * pszFilename, int bUpdateIn) { if (bUpdateIn) { CPLError(CE_Failure, CPLE_NotSupported, "OGR/SVG driver does not support opening a file in update mode"); return FALSE; } #ifdef HAVE_EXPAT pszName = CPLStrdup( pszFilename ); /* -------------------------------------------------------------------- */ /* Determine what sort of object this is. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; if( VSIStatL( pszFilename, &sStatBuf ) != 0 ) return FALSE; if( VSI_ISDIR(sStatBuf.st_mode) ) return FALSE; CPLString osFilename(pszFilename); if (EQUAL(CPLGetExtension(pszFilename), "svgz") && strstr(pszFilename, "/vsigzip/") == NULL) { osFilename = CPLString("/vsigzip/") + pszFilename; pszFilename = osFilename.c_str(); } VSILFILE* fp = VSIFOpenL(pszFilename, "r"); if (fp == NULL) return FALSE; eValidity = SVG_VALIDITY_UNKNOWN; XML_Parser oParser = OGRCreateExpatXMLParser(); oCurrentParser = oParser; XML_SetUserData(oParser, this); XML_SetElementHandler(oParser, ::startElementValidateCbk, NULL); XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk); char aBuf[BUFSIZ]; int nDone; unsigned int nLen; int nCount = 0; /* Begin to parse the file and look for the <svg> element */ /* It *MUST* be the first element of an XML file */ /* So once we have read the first element, we know if we can */ /* handle the file or not with that driver */ do { nDataHandlerCounter = 0; nLen = (unsigned int) VSIFReadL( aBuf, 1, sizeof(aBuf), fp ); nDone = VSIFEofL(fp); if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR) { if (nLen <= BUFSIZ-1) aBuf[nLen] = 0; else aBuf[BUFSIZ-1] = 0; if (strstr(aBuf, "<?xml") && strstr(aBuf, "<svg")) { CPLError(CE_Failure, CPLE_AppDefined, "XML parsing of SVG file failed : %s at line %d, column %d", XML_ErrorString(XML_GetErrorCode(oParser)), (int)XML_GetCurrentLineNumber(oParser), (int)XML_GetCurrentColumnNumber(oParser)); } eValidity = SVG_VALIDITY_INVALID; break; } if (eValidity == SVG_VALIDITY_INVALID) { break; } else if (eValidity == SVG_VALIDITY_VALID) { break; } else { /* After reading 50 * BUFSIZE bytes, and not finding whether the file */ /* is SVG or not, we give up and fail silently */ nCount ++; if (nCount == 50) break; } } while (!nDone && nLen > 0 ); XML_ParserFree(oParser); VSIFCloseL(fp); if (eValidity == SVG_VALIDITY_VALID) { if (bIsCloudmade) { nLayers = 3; papoLayers =(OGRSVGLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRSVGLayer*)); papoLayers[0] = new OGRSVGLayer( pszFilename, "points", SVG_POINTS, this ); papoLayers[1] = new OGRSVGLayer( pszFilename, "lines", SVG_LINES, this ); papoLayers[2] = new OGRSVGLayer( pszFilename, "polygons", SVG_POLYGONS, this ); } else { CPLDebug("SVG", "%s seems to be a SVG file, but not a Cloudmade vector one.", pszFilename); } } return (nLayers > 0); #else char aBuf[256]; VSILFILE* fp = VSIFOpenL(pszFilename, "r"); if (fp) { unsigned int nLen = (unsigned int)VSIFReadL( aBuf, 1, 255, fp ); aBuf[nLen] = 0; if (strstr(aBuf, "<?xml") && strstr(aBuf, "<svg") && strstr(aBuf, "http://cloudmade.com/")) { CPLError(CE_Failure, CPLE_NotSupported, "OGR/SVG driver has not been built with read support. " "Expat library required"); } VSIFCloseL(fp); } return FALSE; #endif }
int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen, char ** papszLimitedFileList ) { VSIStatBuf stat; char **papszFileList = NULL; pszName = CPLStrdup( pszFilename ); /* -------------------------------------------------------------------- */ /* Is the given path a directory or a regular file? */ /* -------------------------------------------------------------------- */ if( CPLStat( pszFilename, &stat ) != 0 || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_AppDefined, "%s is neither a file or directory, NTF access failed.\n", pszFilename ); return FALSE; } /* -------------------------------------------------------------------- */ /* Build a list of filenames we figure are NTF files. */ /* -------------------------------------------------------------------- */ if( VSI_ISREG(stat.st_mode) ) { papszFileList = CSLAddString( NULL, pszFilename ); } else { char **candidateFileList = CPLReadDir( pszFilename ); int i; for( i = 0; candidateFileList != NULL && candidateFileList[i] != NULL; i++ ) { if( papszLimitedFileList != NULL && CSLFindString(papszLimitedFileList, candidateFileList[i]) == -1 ) { continue; } if( strlen(candidateFileList[i]) > 4 && EQUALN(candidateFileList[i] + strlen(candidateFileList[i])-4, ".ntf",4) ) { char fullFilename[2048]; sprintf( fullFilename, "%s%c%s", pszFilename, #ifdef WIN32 '\\', #else '/', #endif candidateFileList[i] ); papszFileList = CSLAddString( papszFileList, fullFilename ); } } CSLDestroy( candidateFileList ); if( CSLCount(papszFileList) == 0 ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_OpenFailed, "No candidate NTF files (.ntf) found in\n" "directory: %s", pszFilename ); return FALSE; } } /* -------------------------------------------------------------------- */ /* Loop over all these files trying to open them. In testopen */ /* mode we first read the first 80 characters, to verify that */ /* it looks like an NTF file. Note that we don't keep the file */ /* open ... we don't want to occupy alot of file handles when */ /* handling a whole directory. */ /* -------------------------------------------------------------------- */ int i; papoNTFFileReader = (NTFFileReader **) CPLCalloc(sizeof(void*), CSLCount(papszFileList)); for( i = 0; papszFileList[i] != NULL; i++ ) { if( bTestOpen ) { char szHeader[80]; FILE *fp; int j; fp = VSIFOpen( papszFileList[i], "rb" ); if( fp == NULL ) continue; if( VSIFRead( szHeader, 80, 1, fp ) < 1 ) { VSIFClose( fp ); continue; } VSIFClose( fp ); if( !EQUALN(szHeader,"01",2) ) continue; for( j = 0; j < 80; j++ ) { if( szHeader[j] == 10 || szHeader[j] == 13 ) break; } if( j == 80 || szHeader[j-1] != '%' ) continue; } NTFFileReader *poFR; poFR = new NTFFileReader( this ); if( !poFR->Open( papszFileList[i] ) ) { delete poFR; CSLDestroy( papszFileList ); return FALSE; } poFR->SetBaseFID( nNTFFileCount * 1000000 + 1 ); poFR->Close(); EnsureTileNameUnique( poFR ); papoNTFFileReader[nNTFFileCount++] = poFR; } CSLDestroy( papszFileList ); if( nNTFFileCount == 0 ) return FALSE; /* -------------------------------------------------------------------- */ /* Establish generic layers. */ /* -------------------------------------------------------------------- */ EstablishGenericLayers(); /* -------------------------------------------------------------------- */ /* Loop over all the files, collecting a unique feature class */ /* listing. */ /* -------------------------------------------------------------------- */ for( int iSrcFile = 0; iSrcFile < nNTFFileCount; iSrcFile++ ) { NTFFileReader *poSrcReader = papoNTFFileReader[iSrcFile]; for( int iSrcFC = 0; iSrcFC < poSrcReader->GetFCCount(); iSrcFC++ ) { int iDstFC; char *pszSrcFCName, *pszSrcFCNum; poSrcReader->GetFeatureClass( iSrcFC, &pszSrcFCNum, &pszSrcFCName); for( iDstFC = 0; iDstFC < nFCCount; iDstFC++ ) { if( EQUAL(pszSrcFCNum,papszFCNum[iDstFC]) ) break; } if( iDstFC >= nFCCount ) { nFCCount++; papszFCNum = CSLAddString(papszFCNum,pszSrcFCNum); papszFCName = CSLAddString(papszFCName,pszSrcFCName); } } } /* -------------------------------------------------------------------- */ /* Create a new layer specifically for feature classes. */ /* -------------------------------------------------------------------- */ if( nFCCount > 0 ) poFCLayer = new OGRNTFFeatureClassLayer( this ); else poFCLayer = NULL; return TRUE; }
GDALOpenInfo::GDALOpenInfo(const char *pszFilenameIn, GDALAccess eAccessIn, char **papszSiblingsIn) { /* -------------------------------------------------------------------- */ /* Ensure that C: is treated as C:\ so we can stat it on */ /* Windows. Similar to what is done in CPLStat(). */ /* -------------------------------------------------------------------- */ #ifdef WIN32 if (strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':') { char szAltPath[10]; strcpy(szAltPath, pszFilenameIn); strcat(szAltPath, "\\"); pszFilename = CPLStrdup(szAltPath); } else #endif pszFilename = CPLStrdup(pszFilenameIn); /* -------------------------------------------------------------------- */ /* Initialize. */ /* -------------------------------------------------------------------- */ nHeaderBytes = 0; pabyHeader = NULL; bIsDirectory = FALSE; bStatOK = FALSE; eAccess = eAccessIn; fp = NULL; #ifdef HAVE_READLINK int bHasRetried = FALSE; #endif /* -------------------------------------------------------------------- */ /* Collect information about the file. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStat; #ifdef HAVE_READLINK retry: #endif if (VSIStatExL(pszFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0) { bStatOK = TRUE; if (VSI_ISREG(sStat.st_mode)) { pabyHeader = (GByte*) CPLCalloc(1025, 1); fp = VSIFOpen(pszFilename, "rb"); if (fp != NULL) { nHeaderBytes = (int) VSIFRead(pabyHeader, 1, 1024, fp); VSIRewind(fp); } /* XXX: ENOENT is used to catch the case of virtual filesystem * when we do not have a real file with such a name. Under some * circumstances EINVAL reported instead of ENOENT in Windows * (for filenames containing colon, e.g. "smth://name"). * See also: #2437 */ else if (errno == 27 /* "File to large" */ || errno == ENOENT || errno == EINVAL #ifdef EOVERFLOW || errno == EOVERFLOW #else || errno == 75 /* Linux EOVERFLOW */ || errno == 79 /* Solaris EOVERFLOW */ #endif ) { VSILFILE *fpL = VSIFOpenL(pszFilename, "rb"); if (fpL != NULL) { nHeaderBytes = (int) VSIFReadL(pabyHeader, 1, 1024, fpL); VSIFCloseL(fpL); } } } else if (VSI_ISDIR(sStat.st_mode)) bIsDirectory = TRUE; } #ifdef HAVE_READLINK else if (!bHasRetried) { /* If someone creates a file with "ln -sf /vsicurl/http://download.osgeo.org/gdal/data/gtiff/utm.tif my_remote_utm.tif" */ /* we will be able to open it by passing my_remote_utm.tif */ /* This helps a lot for GDAL based readers that only provide file explorers to open datasets */ char szPointerFilename[2048]; int nBytes = readlink(pszFilename, szPointerFilename, sizeof(szPointerFilename)); if (nBytes != -1) { szPointerFilename[MIN(nBytes, (int)sizeof(szPointerFilename) - 1)] = 0; CPLFree(pszFilename); pszFilename = CPLStrdup(szPointerFilename); papszSiblingsIn = NULL; bHasRetried = TRUE; goto retry; } } #endif /* -------------------------------------------------------------------- */ /* Capture sibling list either from passed in values, or by */ /* scanning for them. */ /* -------------------------------------------------------------------- */ if (papszSiblingsIn != NULL) { papszSiblingFiles = CSLDuplicate(papszSiblingsIn); } else if (bStatOK && !bIsDirectory) { const char *pszOptionVal = CPLGetConfigOption("GDAL_DISABLE_READDIR_ON_OPEN", "NO"); if (EQUAL(pszOptionVal, "EMPTY_DIR")) { papszSiblingFiles = CSLAddString(NULL, CPLGetFilename(pszFilename)); } else if (CSLTestBoolean(pszOptionVal)) { /* skip reading the directory */ papszSiblingFiles = NULL; } else { CPLString osDir = CPLGetDirname(pszFilename); papszSiblingFiles = VSIReadDir(osDir); } } else papszSiblingFiles = NULL; }
GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, GDALAccess eAccessIn, char **papszSiblingsIn ) { /* -------------------------------------------------------------------- */ /* Ensure that C: is treated as C:\ so we can stat it on */ /* Windows. Similar to what is done in CPLStat(). */ /* -------------------------------------------------------------------- */ #ifdef WIN32 if( strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':' ) { char szAltPath[10]; strcpy( szAltPath, pszFilenameIn ); strcat( szAltPath, "\\" ); pszFilename = CPLStrdup( szAltPath ); } else #endif pszFilename = CPLStrdup( pszFilenameIn ); /* -------------------------------------------------------------------- */ /* Initialize. */ /* -------------------------------------------------------------------- */ nHeaderBytes = 0; pabyHeader = NULL; bIsDirectory = FALSE; bStatOK = FALSE; eAccess = eAccessIn; fp = NULL; /* -------------------------------------------------------------------- */ /* Collect information about the file. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStat; if( VSIStatL( pszFilename, &sStat ) == 0 ) { bStatOK = TRUE; if( VSI_ISREG( sStat.st_mode ) ) { pabyHeader = (GByte *) CPLCalloc(1025,1); fp = VSIFOpen( pszFilename, "rb" ); if( fp != NULL ) { nHeaderBytes = (int) VSIFRead( pabyHeader, 1, 1024, fp ); VSIRewind( fp ); } /* XXX: ENOENT is used to catch the case of virtual filesystem * when we do not have a real file with such a name. Under some * circumstances EINVAL reported instead of ENOENT in Windows * (for filenames containing colon, e.g. "smth://name"). * See also: #2437 */ else if( errno == 27 /* "File to large" */ || errno == ENOENT || errno == EINVAL #ifdef EOVERFLOW || errno == EOVERFLOW #else || errno == 75 /* Linux EOVERFLOW */ || errno == 79 /* Solaris EOVERFLOW */ #endif ) { fp = VSIFOpenL( pszFilename, "rb" ); if( fp != NULL ) { nHeaderBytes = (int) VSIFReadL( pabyHeader, 1, 1024, fp ); VSIFCloseL( fp ); fp = NULL; } } } else if( VSI_ISDIR( sStat.st_mode ) ) bIsDirectory = TRUE; } /* -------------------------------------------------------------------- */ /* Capture sibling list either from passed in values, or by */ /* scanning for them. */ /* -------------------------------------------------------------------- */ if( papszSiblingsIn != NULL ) { papszSiblingFiles = CSLDuplicate( papszSiblingsIn ); } else if( bStatOK && !bIsDirectory ) { if( CSLTestBoolean( CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" )) ) { /* skip reading the directory */ papszSiblingFiles = NULL; } else { CPLString osDir = CPLGetDirname( pszFilename ); papszSiblingFiles = VSIReadDir( osDir ); } } else papszSiblingFiles = NULL; }
OGRLayer * OGRCSVDataSource::CreateLayer( const char *pszLayerName, OGRSpatialReference *poSpatialRef, OGRwkbGeometryType eGType, char ** papszOptions ) { /* -------------------------------------------------------------------- */ /* Verify we are in update mode. */ /* -------------------------------------------------------------------- */ if (!bUpdate) { CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "New layer %s cannot be created.\n", pszName, pszLayerName ); return NULL; } /* -------------------------------------------------------------------- */ /* Verify that the datasource is a directory. */ /* -------------------------------------------------------------------- */ VSIStatBuf sStatBuf; if( VSIStat( pszName, &sStatBuf ) != 0 || !VSI_ISDIR( sStatBuf.st_mode ) ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create csv layer (file) against a non-directory datasource." ); return NULL; } /* -------------------------------------------------------------------- */ /* What filename would we use? */ /* -------------------------------------------------------------------- */ const char *pszFilename; pszFilename = CPLFormFilename( pszName, pszLayerName, "csv" ); /* -------------------------------------------------------------------- */ /* does this file already exist? */ /* -------------------------------------------------------------------- */ if( VSIStat( pszName, &sStatBuf ) != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create layer %s, but file %s already exists.", pszLayerName, pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Create the empty file. */ /* -------------------------------------------------------------------- */ FILE *fp; fp = VSIFOpen( pszFilename, "w+b" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to create %s:\n%s", pszFilename, VSIStrerror( errno ) ); return NULL; } const char *pszDelimiter = CSLFetchNameValue( papszOptions, "SEPARATOR"); char chDelimiter = ','; if (pszDelimiter != NULL) { if (EQUAL(pszDelimiter, "COMMA")) chDelimiter = ','; else if (EQUAL(pszDelimiter, "SEMICOLON")) chDelimiter = ';'; else if (EQUAL(pszDelimiter, "TAB")) chDelimiter = '\t'; else { CPLError( CE_Warning, CPLE_AppDefined, "SEPARATOR=%s not understood, use one of COMMA, SEMICOLON or TAB.", pszDelimiter ); } } /* -------------------------------------------------------------------- */ /* Create a layer. */ /* -------------------------------------------------------------------- */ nLayers++; papoLayers = (OGRCSVLayer **) CPLRealloc(papoLayers, sizeof(void*) * nLayers); papoLayers[nLayers-1] = new OGRCSVLayer( pszLayerName, fp, pszFilename, TRUE, TRUE, chDelimiter ); /* -------------------------------------------------------------------- */ /* Was a partiuclar CRLF order requested? */ /* -------------------------------------------------------------------- */ const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT"); int bUseCRLF; if( pszCRLFFormat == NULL ) { #ifdef WIN32 bUseCRLF = TRUE; #else bUseCRLF = FALSE; #endif } else if( EQUAL(pszCRLFFormat,"CRLF") ) bUseCRLF = TRUE; else if( EQUAL(pszCRLFFormat,"LF") ) bUseCRLF = FALSE; else { CPLError( CE_Warning, CPLE_AppDefined, "LINEFORMAT=%s not understood, use one of CRLF or LF.", pszCRLFFormat ); #ifdef WIN32 bUseCRLF = TRUE; #else bUseCRLF = FALSE; #endif } papoLayers[nLayers-1]->SetCRLF( bUseCRLF ); /* -------------------------------------------------------------------- */ /* Should we write the geometry ? */ /* -------------------------------------------------------------------- */ const char *pszGeometry = CSLFetchNameValue( papszOptions, "GEOMETRY"); if (pszGeometry != NULL) { if (EQUAL(pszGeometry, "AS_WKT")) { papoLayers[nLayers-1]->SetWriteGeometry(OGR_CSV_GEOM_AS_WKT); } else if (EQUAL(pszGeometry, "AS_XYZ") || EQUAL(pszGeometry, "AS_XY") || EQUAL(pszGeometry, "AS_YX")) { if (eGType == wkbUnknown || wkbFlatten(eGType) == wkbPoint) { papoLayers[nLayers-1]->SetWriteGeometry(EQUAL(pszGeometry, "AS_XYZ") ? OGR_CSV_GEOM_AS_XYZ : EQUAL(pszGeometry, "AS_XY") ? OGR_CSV_GEOM_AS_XY : OGR_CSV_GEOM_AS_YX); } else { CPLError( CE_Warning, CPLE_AppDefined, "Geometry type %s is not compatible with GEOMETRY=AS_XYZ.", OGRGeometryTypeToName(eGType) ); } } else { CPLError( CE_Warning, CPLE_AppDefined, "Unsupported value %s for creation option GEOMETRY", pszGeometry ); } } /* -------------------------------------------------------------------- */ /* Should we create a CSVT file ? */ /* -------------------------------------------------------------------- */ const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT"); if (pszCreateCSVT) papoLayers[nLayers-1]->SetCreateCSVT(CSLTestBoolean(pszCreateCSVT)); return papoLayers[nLayers-1]; }
int OGRShapeDataSource::Open( const char * pszNewName, int bUpdate, int bTestOpen, int bSingleNewFileIn ) { VSIStatBufL stat; CPLAssert( nLayers == 0 ); pszName = CPLStrdup( pszNewName ); bDSUpdate = bUpdate; bSingleNewFile = bSingleNewFileIn; /* -------------------------------------------------------------------- */ /* If bSingleNewFile is TRUE we don't try to do anything else. */ /* This is only utilized when the OGRShapeDriver::Create() */ /* method wants to create a stub OGRShapeDataSource for a */ /* single shapefile. The driver will take care of creating the */ /* file by calling CreateLayer(). */ /* -------------------------------------------------------------------- */ if( bSingleNewFile ) return TRUE; /* -------------------------------------------------------------------- */ /* Is the given path a directory or a regular file? */ /* -------------------------------------------------------------------- */ if( VSIStatL( pszNewName, &stat ) != 0 || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_AppDefined, "%s is neither a file or directory, Shape access failed.\n", pszNewName ); return FALSE; } /* -------------------------------------------------------------------- */ /* Build a list of filenames we figure are Shape files. */ /* -------------------------------------------------------------------- */ if( VSI_ISREG(stat.st_mode) ) { if( !OpenFile( pszNewName, bUpdate, bTestOpen ) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open shapefile %s.\n" "It may be corrupt or read-only file accessed in update mode.\n", pszNewName ); return FALSE; } return TRUE; } else { char **papszCandidates = CPLReadDir( pszNewName ); int iCan, nCandidateCount = CSLCount( papszCandidates ); int bMightBeOldCoverage = FALSE; for( iCan = 0; iCan < nCandidateCount; iCan++ ) { char *pszFilename; const char *pszCandidate = papszCandidates[iCan]; if( EQUAL(pszCandidate,"ARC") ) bMightBeOldCoverage = TRUE; if( strlen(pszCandidate) < 4 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".shp") ) continue; pszFilename = CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL)); if( !OpenFile( pszFilename, bUpdate, bTestOpen ) && !bTestOpen ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open shapefile %s.\n" "It may be corrupt or read-only file accessed in update mode.\n", pszFilename ); CPLFree( pszFilename ); return FALSE; } CPLFree( pszFilename ); } // Try and .dbf files without apparent associated shapefiles. for( iCan = 0; iCan < nCandidateCount; iCan++ ) { char *pszFilename; const char *pszCandidate = papszCandidates[iCan]; const char *pszLayerName; int iLayer, bGotAlready = FALSE; // We don't consume .dbf files in a directory that looks like // an old style Arc/Info (for PC?) that unless we found at least // some shapefiles. See Bug 493. if( bMightBeOldCoverage && nLayers == 0 ) continue; if( strlen(pszCandidate) < 4 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".dbf") ) continue; pszLayerName = CPLGetBasename(pszCandidate); for( iLayer = 0; iLayer < nLayers; iLayer++ ) { if( EQUAL(pszLayerName, GetLayer(iLayer)->GetLayerDefn()->GetName()) ) bGotAlready = TRUE; } if( bGotAlready ) continue; // We don't want to access .dbf files with an associated .tab // file, or it will never get recognised as a mapinfo dataset. int iCan2, bFoundTAB = FALSE; for( iCan2 = 0; iCan2 < nCandidateCount; iCan2++ ) { const char *pszCandidate2 = papszCandidates[iCan2]; if( EQUALN(pszCandidate2,pszLayerName,strlen(pszLayerName)) && EQUAL(pszCandidate2 + strlen(pszLayerName), ".tab") ) bFoundTAB = TRUE; } if( bFoundTAB ) continue; pszFilename = CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL)); if( !OpenFile( pszFilename, bUpdate, bTestOpen ) && !bTestOpen ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open dbf file %s.\n" "It may be corrupt or read-only file accessed in update mode.\n", pszFilename ); CPLFree( pszFilename ); return FALSE; } CPLFree( pszFilename ); } CSLDestroy( papszCandidates ); if( !bTestOpen && nLayers == 0 && !bUpdate ) { CPLError( CE_Failure, CPLE_OpenFailed, "No Shapefiles found in directory %s\n", pszNewName ); } } return nLayers > 0 || bUpdate; }
int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn, int bForceOpen ) { pszName = CPLStrdup( pszFilename ); bUpdate = bUpdateIn; /* -------------------------------------------------------------------- */ /* Determine what sort of object this is. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; if( VSIStatL( pszFilename, &sStatBuf ) != 0 ) return FALSE; /* -------------------------------------------------------------------- */ /* Is this a single CSV file? */ /* -------------------------------------------------------------------- */ if( VSI_ISREG(sStatBuf.st_mode) && strlen(pszFilename) > 4 && EQUAL(pszFilename+strlen(pszFilename)-4,".csv") ) return OpenTable( pszFilename ); /* -------------------------------------------------------------------- */ /* Otherwise it has to be a directory. */ /* -------------------------------------------------------------------- */ if( !VSI_ISDIR(sStatBuf.st_mode) ) return FALSE; /* -------------------------------------------------------------------- */ /* Scan through for entries ending in .csv. */ /* -------------------------------------------------------------------- */ int nNotCSVCount = 0, i; char **papszNames = CPLReadDir( pszFilename ); for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ ) { CPLString oSubFilename = CPLFormFilename( pszFilename, papszNames[i], NULL ); if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") ) continue; if (EQUAL(CPLGetExtension(oSubFilename),"csvt")) continue; if( VSIStatL( oSubFilename, &sStatBuf ) != 0 || !VSI_ISREG(sStatBuf.st_mode) || !EQUAL(CPLGetExtension(oSubFilename),"csv") ) { nNotCSVCount++; continue; } if( !OpenTable( oSubFilename ) ) { CSLDestroy( papszNames ); nNotCSVCount++; return FALSE; } } CSLDestroy( papszNames ); /* -------------------------------------------------------------------- */ /* We presume that this is indeed intended to be a CSV */ /* datasource if over half the files were .csv files. */ /* -------------------------------------------------------------------- */ return bForceOpen || nNotCSVCount < nLayers; }
int OGRTABDataSource::Create( const char * pszName, char **papszOptions ) { VSIStatBuf sStat; const char *pszOpt; CPLAssert( m_pszName == NULL ); m_pszName = CPLStrdup( pszName ); m_papszOptions = CSLDuplicate( papszOptions ); if( (pszOpt=CSLFetchNameValue(papszOptions,"FORMAT")) != NULL && EQUAL(pszOpt, "MIF") ) m_bCreateMIF = TRUE; else if( EQUAL(CPLGetExtension(pszName),"mif") || EQUAL(CPLGetExtension(pszName),"mid") ) m_bCreateMIF = TRUE; if( (pszOpt=CSLFetchNameValue(papszOptions,"SPATIAL_INDEX_MODE")) != NULL && EQUAL(pszOpt, "QUICK") ) m_bQuickSpatialIndexMode = TRUE; /* -------------------------------------------------------------------- */ /* Create a new empty directory. */ /* -------------------------------------------------------------------- */ if( strlen(CPLGetExtension(pszName)) == 0 ) { if( VSIStat( pszName, &sStat ) == 0 ) { if( !VSI_ISDIR(sStat.st_mode) ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create dataset named %s,\n" "but that is an existing file.\n", pszName ); return FALSE; } } else { if( VSIMkdir( pszName, 0755 ) != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Unable to create directory %s.\n", pszName ); return FALSE; } } m_pszDirectory = CPLStrdup(pszName); } /* -------------------------------------------------------------------- */ /* Create a new single file. */ /* -------------------------------------------------------------------- */ else { IMapInfoFile *poFile; if( m_bCreateMIF ) poFile = new MIFFile; else poFile = new TABFile; if( poFile->Open( pszName, "wb", FALSE ) != 0 ) { delete poFile; return FALSE; } m_nLayerCount = 1; m_papoLayers = (IMapInfoFile **) CPLMalloc(sizeof(void*)); m_papoLayers[0] = poFile; m_pszDirectory = CPLStrdup( CPLGetPath(pszName) ); m_bSingleFile = TRUE; } return TRUE; }
RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char* tocHeader) { int i, j; unsigned int locationSectionPhysicalLocation; int nSections; unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0; unsigned int boundaryRectangleTablePhysIndex = 0; unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0; unsigned int frameFileIndexSubsectionPhysIndex = 0; unsigned int boundaryRectangleTableOffset; unsigned short boundaryRectangleCount; unsigned int frameIndexTableOffset; unsigned int nFrameFileIndexRecords; unsigned short nFrameFilePathnameRecords; unsigned short frameFileIndexRecordLength; int newBoundaryId = 0; RPFToc* toc; tocHeader += 1; /* skip endian */ tocHeader += 2; /* skip header length */ tocHeader += 12; /* skip file name : this should be A.TOC (padded) */ tocHeader += 1; /* skip new */ tocHeader += 15; /* skip standard_num */ tocHeader += 8; /* skip standard_date */ tocHeader += 1; /* skip classification */ tocHeader += 2; /* skip country */ tocHeader += 2; /* skip release */ memcpy(&locationSectionPhysicalLocation, tocHeader, sizeof(unsigned int)); CPL_MSBPTR32(&locationSectionPhysicalLocation); if( VSIFSeekL( fp, locationSectionPhysicalLocation, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to locationSectionPhysicalLocation at offset %d.", locationSectionPhysicalLocation ); return NULL; } NITFLocation* pasLocations = NITFReadRPFLocationTable(fp, &nSections); for (i = 0; i < nSections; i++) { if (pasLocations[i].nLocId == LID_BoundaryRectangleSectionSubheader) { boundaryRectangleSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset; } else if (pasLocations[i].nLocId == LID_BoundaryRectangleTable) { boundaryRectangleTablePhysIndex = pasLocations[i].nLocOffset; } else if (pasLocations[i].nLocId == LID_FrameFileIndexSectionSubHeader) { frameFileIndexSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset; } else if (pasLocations[i].nLocId == LID_FrameFileIndexSubsection) { frameFileIndexSubsectionPhysIndex = pasLocations[i].nLocOffset; } } CPLFree(pasLocations); if (boundaryRectangleSectionSubHeaderPhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_BoundaryRectangleSectionSubheader." ); return NULL; } if (boundaryRectangleTablePhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_BoundaryRectangleTable." ); return NULL; } if (frameFileIndexSectionSubHeaderPhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_FrameFileIndexSectionSubHeader." ); return NULL; } if (frameFileIndexSubsectionPhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_FrameFileIndexSubsection." ); return NULL; } if( VSIFSeekL( fp, boundaryRectangleSectionSubHeaderPhysIndex, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to boundaryRectangleSectionSubHeaderPhysIndex at offset %d.", boundaryRectangleSectionSubHeaderPhysIndex ); return NULL; } VSIFReadL( &boundaryRectangleTableOffset, 1, sizeof(boundaryRectangleTableOffset), fp); CPL_MSBPTR32( &boundaryRectangleTableOffset ); VSIFReadL( &boundaryRectangleCount, 1, sizeof(boundaryRectangleCount), fp); CPL_MSBPTR16( &boundaryRectangleCount ); if( VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to boundaryRectangleTablePhysIndex at offset %d.", boundaryRectangleTablePhysIndex ); return NULL; } toc = (RPFToc*)CPLMalloc(sizeof(RPFToc)); toc->nEntries = boundaryRectangleCount; toc->entries = (RPFTocEntry*)CPLMalloc(boundaryRectangleCount * sizeof(RPFTocEntry)); memset(toc->entries, 0, boundaryRectangleCount * sizeof(RPFTocEntry)); for(i=0;i<toc->nEntries;i++) { toc->entries[i].isOverviewOrLegend = 0; VSIFReadL( toc->entries[i].type, 1, 5, fp); toc->entries[i].type[5] = 0; RPFTOCTrim(toc->entries[i].type); VSIFReadL( toc->entries[i].compression, 1, 5, fp); toc->entries[i].compression[5] = 0; RPFTOCTrim(toc->entries[i].compression); VSIFReadL( toc->entries[i].scale, 1, 12, fp); toc->entries[i].scale[12] = 0; RPFTOCTrim(toc->entries[i].scale); if (toc->entries[i].scale[0] == '1' && toc->entries[i].scale[1] == ':') { memmove(toc->entries[i].scale, toc->entries[i].scale+2, strlen(toc->entries[i].scale+2)+1); } VSIFReadL( toc->entries[i].zone, 1, 1, fp); toc->entries[i].zone[1] = 0; RPFTOCTrim(toc->entries[i].zone); VSIFReadL( toc->entries[i].producer, 1, 5, fp); toc->entries[i].producer[5] = 0; RPFTOCTrim(toc->entries[i].producer); VSIFReadL( &toc->entries[i].nwLat, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].nwLat); VSIFReadL( &toc->entries[i].nwLong, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].nwLong); VSIFReadL( &toc->entries[i].swLat, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].swLat); VSIFReadL( &toc->entries[i].swLong, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].swLong); VSIFReadL( &toc->entries[i].neLat, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].neLat); VSIFReadL( &toc->entries[i].neLong, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].neLong); VSIFReadL( &toc->entries[i].seLat, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].seLat); VSIFReadL( &toc->entries[i].seLong, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].seLong); VSIFReadL( &toc->entries[i].vertResolution, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].vertResolution); VSIFReadL( &toc->entries[i].horizResolution, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].horizResolution); VSIFReadL( &toc->entries[i].vertInterval, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].vertInterval); VSIFReadL( &toc->entries[i].horizInterval, 1, sizeof(double), fp); CPL_MSBPTR64( &toc->entries[i].horizInterval); VSIFReadL( &toc->entries[i].nVertFrames, 1, sizeof(int), fp); CPL_MSBPTR32( &toc->entries[i].nVertFrames ); VSIFReadL( &toc->entries[i].nHorizFrames, 1, sizeof(int), fp); CPL_MSBPTR32( &toc->entries[i].nHorizFrames ); toc->entries[i].frameEntries = (RPFTocFrameEntry*) VSIMalloc3(toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames, sizeof(RPFTocFrameEntry)); if (toc->entries[i].frameEntries == NULL) { CPLError( CE_Failure, CPLE_OutOfMemory, "RPFTOCReadFromBuffer : Out of memory. Probably due to corrupted TOC file."); RPFTOCFree(toc); return NULL; } memset(toc->entries[i].frameEntries, 0, toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames * sizeof(RPFTocFrameEntry)); CPLDebug("RPFTOC", "[%d] type=%s, compression=%s, scale=%s, zone=%s, producer=%s, nVertFrames=%d, nHorizFrames=%d", i, toc->entries[i].type, toc->entries[i].compression, toc->entries[i].scale, toc->entries[i].zone, toc->entries[i].producer, toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames); } if( VSIFSeekL( fp, frameFileIndexSectionSubHeaderPhysIndex, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to frameFileIndexSectionSubHeaderPhysIndex at offset %d.", frameFileIndexSectionSubHeaderPhysIndex ); RPFTOCFree(toc); return NULL; } /* Skip 1 byte security classification */ VSIFSeekL( fp, 1, SEEK_CUR ); VSIFReadL( &frameIndexTableOffset, 1, sizeof(frameIndexTableOffset), fp); CPL_MSBPTR32( &frameIndexTableOffset ); VSIFReadL( &nFrameFileIndexRecords, 1, sizeof(nFrameFileIndexRecords), fp); CPL_MSBPTR32( &nFrameFileIndexRecords ); VSIFReadL( &nFrameFilePathnameRecords, 1, sizeof(nFrameFilePathnameRecords), fp); CPL_MSBPTR16( &nFrameFilePathnameRecords ); VSIFReadL( &frameFileIndexRecordLength, 1, sizeof(frameFileIndexRecordLength), fp); CPL_MSBPTR16( &frameFileIndexRecordLength ); for (i=0;i<(int)nFrameFileIndexRecords;i++) { RPFTocEntry* entry; RPFTocFrameEntry* frameEntry; unsigned short boundaryId, frameRow, frameCol; unsigned int offsetFrameFilePathName; unsigned short pathLength; if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex(%d) at offset %d.", i, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i); RPFTOCFree(toc); return NULL; } VSIFReadL( &boundaryId, 1, sizeof(boundaryId), fp); CPL_MSBPTR16( &boundaryId ); if (i == 0 && boundaryId == 0) newBoundaryId = 1; if (newBoundaryId == 0) boundaryId--; if (boundaryId >= toc->nEntries) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Bad boundary id (%d) for frame file index %d.", boundaryId, i); RPFTOCFree(toc); return NULL; } entry = &toc->entries[boundaryId]; entry->boundaryId = boundaryId; VSIFReadL( &frameRow, 1, sizeof(frameRow), fp); CPL_MSBPTR16( &frameRow ); VSIFReadL( &frameCol, 1, sizeof(frameCol), fp); CPL_MSBPTR16( &frameCol ); if (newBoundaryId == 0) { frameRow--; frameCol--; } else { /* Trick so that frames are numbered north to south */ frameRow = (unsigned short)((entry->nVertFrames-1) - frameRow); } if (frameRow >= entry->nVertFrames) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Bad row num (%d) for frame file index %d.", frameRow, i); RPFTOCFree(toc); return NULL; } if (frameCol >= entry->nHorizFrames) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Bad col num (%d) for frame file index %d.", frameCol, i); RPFTOCFree(toc); return NULL; } frameEntry = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ]; frameEntry->frameRow = frameRow; frameEntry->frameCol = frameCol; if (frameEntry->exists) { CPLError( CE_Warning, CPLE_AppDefined, "Frame entry(%d,%d) for frame file index %d was already found.", frameRow, frameCol, i); CPLFree(frameEntry->directory); frameEntry->directory = NULL; CPLFree(frameEntry->fullFilePath); frameEntry->fullFilePath = NULL; frameEntry->exists = 0; } VSIFReadL( &offsetFrameFilePathName, 1, sizeof(offsetFrameFilePathName), fp); CPL_MSBPTR32( &offsetFrameFilePathName ); VSIFReadL( frameEntry->filename, 1, 12, fp); frameEntry->filename[12] = '\0'; /* Check if the filename is an overview or legend */ for (j=0;j<12;j++) { if (strcmp(&(frameEntry->filename[j]),".OVR") == 0 || strcmp(&(frameEntry->filename[j]),".ovr") == 0 || strcmp(&(frameEntry->filename[j]),".LGD") == 0 || strcmp(&(frameEntry->filename[j]),".lgd") == 0) { entry->isOverviewOrLegend = TRUE; break; } } /* Extract series code */ if (entry->seriesAbbreviation == NULL) { const NITFSeries* series = NITFGetSeriesInfo(frameEntry->filename); if (series) { entry->seriesAbbreviation = series->abbreviation; entry->seriesName = series->name; } } /* Get file geo reference */ VSIFReadL( frameEntry->georef, 1, 6, fp); frameEntry->georef[6] = '\0'; /* Go to start of pathname record */ /* New path_off offset from start of frame file index section of TOC?? */ /* Add pathoffset wrt frame file index table subsection (loc[3]) */ if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName(%d) at offset %d.", i, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName); RPFTOCFree(toc); return NULL; } VSIFReadL( &pathLength, 1, sizeof(pathLength), fp); CPL_MSBPTR16( &pathLength ); /* if nFrameFileIndexRecords == 65535 and pathLength == 65535 for each record, this leads to 4 GB allocation... Protect against this case */ if (pathLength > 256) { CPLError( CE_Failure, CPLE_NotSupported, "Path length is big : %d. Probably corrupted TOC file.", (int)pathLength); RPFTOCFree(toc); return NULL; } frameEntry->directory = (char *)CPLMalloc(pathLength+1); VSIFReadL( frameEntry->directory, 1, pathLength, fp); frameEntry->directory[pathLength] = 0; if (pathLength > 0 && frameEntry->directory[pathLength-1] == '/') frameEntry->directory[pathLength-1] = 0; if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == '/') { memmove(frameEntry->directory, frameEntry->directory+2, strlen(frameEntry->directory+2)+1); // Some A.TOC have subdirectory names like ".//X/" ... (#5979) // Check if it wasn't intended to be "./X/" instead VSIStatBufL sStatBuf; if( frameEntry->directory[0] == '/' && VSIStatL(CPLFormFilename(CPLGetDirname(pszFilename), frameEntry->directory+1, NULL), &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode) ) { memmove(frameEntry->directory, frameEntry->directory+1, strlen(frameEntry->directory+1)+1); } } { char* baseDir = CPLStrdup(CPLGetDirname(pszFilename)); VSIStatBufL sStatBuf; char* subdir; if (CPLIsFilenameRelative(frameEntry->directory) == FALSE) subdir = CPLStrdup(frameEntry->directory); else if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == 0) subdir = CPLStrdup(baseDir); else subdir = CPLStrdup(CPLFormFilename(baseDir, frameEntry->directory, NULL)); #if !defined(_WIN32) && !defined(_WIN32_CE) if( VSIStatL( subdir, &sStatBuf ) != 0 && subdir[strlen(baseDir)] != 0) { char* c = subdir + strlen(baseDir)+1; while(*c) { if (*c >= 'A' && *c <= 'Z') *c += 'a' - 'A'; c++; } } #endif frameEntry->fullFilePath = CPLStrdup(CPLFormFilename( subdir, frameEntry->filename, NULL)); if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 ) { #if !defined(_WIN32) && !defined(_WIN32_CE) char* c = frameEntry->fullFilePath + strlen(subdir)+1; while(*c) { if (*c >= 'A' && *c <= 'Z') *c += 'a' - 'A'; c++; } if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 ) #endif { frameEntry->fileExists = 0; CPLError( CE_Warning, CPLE_AppDefined, "File %s does not exist.", frameEntry->fullFilePath ); } #if !defined(_WIN32) && !defined(_WIN32_CE) else { frameEntry->fileExists = 1; } #endif } else { frameEntry->fileExists = 1; } CPLFree(subdir); CPLFree(baseDir); } CPLDebug("RPFTOC", "Entry %d : %s,%s (%d, %d)", boundaryId, frameEntry->directory, frameEntry->filename, frameRow, frameCol); frameEntry->exists = 1; } return toc; }
RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char* tocHeader) { tocHeader += 1; /* skip endian */ tocHeader += 2; /* skip header length */ tocHeader += 12; /* skip file name : this should be A.TOC (padded) */ tocHeader += 1; /* skip new */ tocHeader += 15; /* skip standard_num */ tocHeader += 8; /* skip standard_date */ tocHeader += 1; /* skip classification */ tocHeader += 2; /* skip country */ tocHeader += 2; /* skip release */ unsigned int locationSectionPhysicalLocation; memcpy(&locationSectionPhysicalLocation, tocHeader, sizeof(unsigned int)); CPL_MSBPTR32(&locationSectionPhysicalLocation); if( VSIFSeekL( fp, locationSectionPhysicalLocation, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to locationSectionPhysicalLocation at offset %d.", locationSectionPhysicalLocation ); return nullptr; } int nSections; NITFLocation* pasLocations = NITFReadRPFLocationTable(fp, &nSections); unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0; unsigned int boundaryRectangleTablePhysIndex = 0; unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0; unsigned int frameFileIndexSubsectionPhysIndex = 0; for( int i = 0; i < nSections; i++ ) { if (pasLocations[i].nLocId == LID_BoundaryRectangleSectionSubheader) { boundaryRectangleSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset; } else if (pasLocations[i].nLocId == LID_BoundaryRectangleTable) { boundaryRectangleTablePhysIndex = pasLocations[i].nLocOffset; } else if (pasLocations[i].nLocId == LID_FrameFileIndexSectionSubHeader) { frameFileIndexSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset; } else if (pasLocations[i].nLocId == LID_FrameFileIndexSubsection) { frameFileIndexSubsectionPhysIndex = pasLocations[i].nLocOffset; } } CPLFree(pasLocations); if (boundaryRectangleSectionSubHeaderPhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_BoundaryRectangleSectionSubheader." ); return nullptr; } if (boundaryRectangleTablePhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_BoundaryRectangleTable." ); return nullptr; } if (frameFileIndexSectionSubHeaderPhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_FrameFileIndexSectionSubHeader." ); return nullptr; } if (frameFileIndexSubsectionPhysIndex == 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Can't find LID_FrameFileIndexSubsection." ); return nullptr; } if( VSIFSeekL( fp, boundaryRectangleSectionSubHeaderPhysIndex, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to boundaryRectangleSectionSubHeaderPhysIndex at offset %d.", boundaryRectangleSectionSubHeaderPhysIndex ); return nullptr; } unsigned int boundaryRectangleTableOffset; bool bOK = VSIFReadL( &boundaryRectangleTableOffset, sizeof(boundaryRectangleTableOffset), 1, fp) == 1; CPL_MSBPTR32( &boundaryRectangleTableOffset ); unsigned short boundaryRectangleCount; bOK &= VSIFReadL( &boundaryRectangleCount, sizeof(boundaryRectangleCount), 1, fp) == 1; CPL_MSBPTR16( &boundaryRectangleCount ); if( !bOK || VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to boundaryRectangleTablePhysIndex at offset %d.", boundaryRectangleTablePhysIndex ); return nullptr; } RPFToc* toc = reinterpret_cast<RPFToc *>( CPLMalloc( sizeof( RPFToc ) ) ); toc->nEntries = boundaryRectangleCount; toc->entries = reinterpret_cast<RPFTocEntry *>( CPLMalloc( boundaryRectangleCount * sizeof(RPFTocEntry) ) ); memset(toc->entries, 0, boundaryRectangleCount * sizeof(RPFTocEntry)); for( int i = 0; i < toc->nEntries; i++ ) { toc->entries[i].isOverviewOrLegend = 0; bOK &= VSIFReadL( toc->entries[i].type, 1, 5, fp) == 5; toc->entries[i].type[5] = 0; RPFTOCTrim(toc->entries[i].type); bOK &= VSIFReadL( toc->entries[i].compression, 1, 5, fp) == 5; toc->entries[i].compression[5] = 0; RPFTOCTrim(toc->entries[i].compression); bOK &= VSIFReadL( toc->entries[i].scale, 1, 12, fp) == 12; toc->entries[i].scale[12] = 0; RPFTOCTrim(toc->entries[i].scale); if (toc->entries[i].scale[0] == '1' && toc->entries[i].scale[1] == ':') { memmove(toc->entries[i].scale, toc->entries[i].scale+2, strlen(toc->entries[i].scale+2)+1); } bOK &= VSIFReadL( toc->entries[i].zone, 1, 1, fp) == 1; toc->entries[i].zone[1] = 0; RPFTOCTrim(toc->entries[i].zone); bOK &= VSIFReadL( toc->entries[i].producer, 1, 5, fp) == 5; toc->entries[i].producer[5] = 0; RPFTOCTrim(toc->entries[i].producer); bOK &= VSIFReadL( &toc->entries[i].nwLat, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].nwLat); bOK &= VSIFReadL( &toc->entries[i].nwLong, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].nwLong); bOK &= VSIFReadL( &toc->entries[i].swLat, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].swLat); bOK &= VSIFReadL( &toc->entries[i].swLong, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].swLong); bOK &= VSIFReadL( &toc->entries[i].neLat, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].neLat); bOK &= VSIFReadL( &toc->entries[i].neLong, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].neLong); bOK &= VSIFReadL( &toc->entries[i].seLat, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].seLat); bOK &= VSIFReadL( &toc->entries[i].seLong, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].seLong); bOK &= VSIFReadL( &toc->entries[i].vertResolution, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].vertResolution); bOK &= VSIFReadL( &toc->entries[i].horizResolution, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].horizResolution); bOK &= VSIFReadL( &toc->entries[i].vertInterval, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].vertInterval); bOK &= VSIFReadL( &toc->entries[i].horizInterval, sizeof(double), 1, fp) == 1; CPL_MSBPTR64( &toc->entries[i].horizInterval); bOK &= VSIFReadL( &toc->entries[i].nVertFrames, sizeof(int), 1, fp) == 1; CPL_MSBPTR32( &toc->entries[i].nVertFrames ); bOK &= VSIFReadL( &toc->entries[i].nHorizFrames, sizeof(int), 1, fp) == 1; CPL_MSBPTR32( &toc->entries[i].nHorizFrames ); if( !bOK ) { CPLError(CE_Failure, CPLE_FileIO, "I/O error"); toc->entries[i].nVertFrames = 0; toc->entries[i].nHorizFrames = 0; RPFTOCFree(toc); return nullptr; } if( toc->entries[i].vertInterval <= 1e-10 || !CPLIsFinite(toc->entries[i].vertInterval) || toc->entries[i].horizInterval <= 1e-10 || !CPLIsFinite(toc->entries[i].horizInterval) || !(fabs(toc->entries[i].seLong) <= 360.0) || !(fabs(toc->entries[i].nwLong) <= 360.0) || !(fabs(toc->entries[i].nwLat) <= 90.0) || !(fabs(toc->entries[i].seLat) <= 90.0) || toc->entries[i].seLong < toc->entries[i].nwLong || toc->entries[i].nwLat < toc->entries[i].seLat || toc->entries[i].nHorizFrames == 0 || toc->entries[i].nVertFrames == 0 || toc->entries[i].nHorizFrames > INT_MAX / toc->entries[i].nVertFrames ) { CPLError(CE_Failure, CPLE_FileIO, "Invalid TOC entry"); toc->entries[i].nVertFrames = 0; toc->entries[i].nHorizFrames = 0; RPFTOCFree(toc); return nullptr; } // TODO: We could probably use another data structure, like a list, // instead of an array referenced by the frame coordinate... if( static_cast<int>(toc->entries[i].nHorizFrames * toc->entries[i].nVertFrames) > atoi(CPLGetConfigOption("RPFTOC_MAX_FRAME_COUNT", "1000000")) ) { CPLError(CE_Failure, CPLE_AppDefined, "nHorizFrames=%d x nVertFrames=%d > %d. Please raise " "the value of the RPFTOC_MAX_FRAME_COUNT configuration " "option to more than %d if this dataset is legitimate.", toc->entries[i].nHorizFrames, toc->entries[i].nVertFrames, atoi(CPLGetConfigOption("RPFTOC_MAX_FRAME_COUNT", "1000000")), toc->entries[i].nHorizFrames * toc->entries[i].nVertFrames ); toc->entries[i].frameEntries = nullptr; } else { toc->entries[i].frameEntries = reinterpret_cast<RPFTocFrameEntry*>( VSI_CALLOC_VERBOSE( toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames, sizeof(RPFTocFrameEntry) ) ); } if (toc->entries[i].frameEntries == nullptr) { toc->entries[i].nVertFrames = 0; toc->entries[i].nHorizFrames = 0; RPFTOCFree(toc); return nullptr; } CPLDebug("RPFTOC", "[%d] type=%s, compression=%s, scale=%s, zone=%s, producer=%s, nVertFrames=%d, nHorizFrames=%d", i, toc->entries[i].type, toc->entries[i].compression, toc->entries[i].scale, toc->entries[i].zone, toc->entries[i].producer, toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames); } if( VSIFSeekL( fp, frameFileIndexSectionSubHeaderPhysIndex, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to frameFileIndexSectionSubHeaderPhysIndex at offset %d.", frameFileIndexSectionSubHeaderPhysIndex ); RPFTOCFree(toc); return nullptr; } /* Skip 1 byte security classification */ bOK &= VSIFSeekL( fp, 1, SEEK_CUR ) == 0; unsigned int frameIndexTableOffset; bOK &= VSIFReadL( &frameIndexTableOffset, sizeof(frameIndexTableOffset), 1, fp) == 1; CPL_MSBPTR32( &frameIndexTableOffset ); unsigned int nFrameFileIndexRecords; bOK &= VSIFReadL( &nFrameFileIndexRecords, sizeof(nFrameFileIndexRecords), 1, fp) == 1; CPL_MSBPTR32( &nFrameFileIndexRecords ); unsigned short nFrameFilePathnameRecords; bOK &= VSIFReadL( &nFrameFilePathnameRecords, sizeof(nFrameFilePathnameRecords), 1, fp) == 1; CPL_MSBPTR16( &nFrameFilePathnameRecords ); unsigned short frameFileIndexRecordLength; bOK &= VSIFReadL( &frameFileIndexRecordLength, sizeof(frameFileIndexRecordLength), 1, fp) == 1; CPL_MSBPTR16( &frameFileIndexRecordLength ); if( frameFileIndexRecordLength < 3 * sizeof(short) ) { CPLError(CE_Failure, CPLE_FileIO, "Invalid file"); RPFTOCFree(toc); return nullptr; } if( !bOK ) { CPLError(CE_Failure, CPLE_FileIO, "I/O error"); RPFTOCFree(toc); return nullptr; } int newBoundaryId = 0; for( int i = 0; i < static_cast<int>( nFrameFileIndexRecords ); i++ ) { if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex(%d) at offset %d.", i, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i); RPFTOCFree(toc); return nullptr; } unsigned short boundaryId; if( VSIFReadL( &boundaryId, sizeof(boundaryId), 1, fp) != 1 ) { CPLError(CE_Failure, CPLE_FileIO, "I/O error"); RPFTOCFree(toc); return nullptr; } CPL_MSBPTR16( &boundaryId ); if (i == 0 && boundaryId == 0) newBoundaryId = 1; if (newBoundaryId == 0) boundaryId--; if (boundaryId >= toc->nEntries) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Bad boundary id (%d) for frame file index %d.", boundaryId, i); RPFTOCFree(toc); return nullptr; } RPFTocEntry* entry = &toc->entries[boundaryId]; entry->boundaryId = boundaryId; unsigned short frameRow; bOK &= VSIFReadL( &frameRow, sizeof(frameRow), 1, fp) == 1; CPL_MSBPTR16( &frameRow ); unsigned short frameCol; bOK &= VSIFReadL( &frameCol, sizeof(frameCol), 1, fp) == 1; CPL_MSBPTR16( &frameCol ); if( !bOK ) { CPLError(CE_Failure, CPLE_FileIO, "I/O error"); RPFTOCFree(toc); return nullptr; } if (newBoundaryId == 0) { frameRow--; frameCol--; } else { /* Trick so that frames are numbered north to south */ frameRow = (unsigned short)((entry->nVertFrames-1) - frameRow); } if (frameRow >= entry->nVertFrames) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Bad row num (%d) for frame file index %d.", frameRow, i); RPFTOCFree(toc); return nullptr; } if (frameCol >= entry->nHorizFrames) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Bad col num (%d) for frame file index %d.", frameCol, i); RPFTOCFree(toc); return nullptr; } RPFTocFrameEntry* frameEntry = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ]; frameEntry->frameRow = frameRow; frameEntry->frameCol = frameCol; if (frameEntry->exists) { CPLError( CE_Warning, CPLE_AppDefined, "Frame entry(%d,%d) for frame file index %d was already found.", frameRow, frameCol, i); CPLFree(frameEntry->directory); frameEntry->directory = nullptr; CPLFree(frameEntry->fullFilePath); frameEntry->fullFilePath = nullptr; frameEntry->exists = 0; } unsigned int offsetFrameFilePathName; bOK &= VSIFReadL( &offsetFrameFilePathName, sizeof(offsetFrameFilePathName), 1, fp) == 1; CPL_MSBPTR32( &offsetFrameFilePathName ); bOK &= VSIFReadL( frameEntry->filename, 1, 12, fp) == 12; if( !bOK ) { CPLError(CE_Failure, CPLE_FileIO, "I/O error"); RPFTOCFree(toc); return nullptr; } frameEntry->filename[12] = '\0'; bOK &= strlen(frameEntry->filename) > 0; /* Check if the filename is an overview or legend */ for( int j = 0; j < 12; j++ ) { if (strcmp(&(frameEntry->filename[j]),".OVR") == 0 || strcmp(&(frameEntry->filename[j]),".ovr") == 0 || strcmp(&(frameEntry->filename[j]),".LGD") == 0 || strcmp(&(frameEntry->filename[j]),".lgd") == 0) { entry->isOverviewOrLegend = TRUE; break; } } /* Extract series code */ if (entry->seriesAbbreviation == nullptr) { const NITFSeries* series = NITFGetSeriesInfo(frameEntry->filename); if (series) { entry->seriesAbbreviation = series->abbreviation; entry->seriesName = series->name; } } /* Get file geo reference */ bOK &= VSIFReadL( frameEntry->georef, 1, 6, fp) == 6; frameEntry->georef[6] = '\0'; /* Go to start of pathname record */ /* New path_off offset from start of frame file index section of TOC?? */ /* Add pathoffset wrt frame file index table subsection (loc[3]) */ if( !bOK || VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0) { CPLError( CE_Failure, CPLE_NotSupported, "Invalid TOC file. Unable to seek to " "frameFileIndexSubsectionPhysIndex + " "offsetFrameFilePathName(%d) at offset %d.", i, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName); RPFTOCFree(toc); return nullptr; } unsigned short pathLength; bOK &= VSIFReadL( &pathLength, sizeof(pathLength), 1, fp) == 1; CPL_MSBPTR16( &pathLength ); /* if nFrameFileIndexRecords == 65535 and pathLength == 65535 for each record, this leads to 4 GB allocation... Protect against this case */ if (!bOK || pathLength == 0 || pathLength > 256) { CPLError( CE_Failure, CPLE_NotSupported, "Path length is invalid : %d. Probably corrupted TOC file.", static_cast<int>( pathLength ) ); RPFTOCFree(toc); return nullptr; } frameEntry->directory = reinterpret_cast<char *>( CPLMalloc(pathLength+1) ); bOK &= VSIFReadL( frameEntry->directory, 1, pathLength, fp) == pathLength; if( !bOK ) { CPLError(CE_Failure, CPLE_FileIO, "I/O error"); RPFTOCFree(toc); return nullptr; } frameEntry->directory[pathLength] = 0; if (pathLength > 0 && frameEntry->directory[pathLength-1] == '/') frameEntry->directory[pathLength-1] = 0; if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == '/') { memmove(frameEntry->directory, frameEntry->directory+2, strlen(frameEntry->directory+2)+1); // Some A.TOC have subdirectory names like ".//X/" ... (#5979) // Check if it was not intended to be "./X/" instead. VSIStatBufL sStatBuf; if( frameEntry->directory[0] == '/' && VSIStatL(CPLFormFilename(CPLGetDirname(pszFilename), frameEntry->directory+1, nullptr), &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode) ) { memmove(frameEntry->directory, frameEntry->directory+1, strlen(frameEntry->directory+1)+1); } } { char* baseDir = CPLStrdup(CPLGetDirname(pszFilename)); VSIStatBufL sStatBuf; char* subdir = nullptr; if (CPLIsFilenameRelative(frameEntry->directory) == FALSE) subdir = CPLStrdup(frameEntry->directory); else if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == 0) subdir = CPLStrdup(baseDir); else subdir = CPLStrdup(CPLFormFilename(baseDir, frameEntry->directory, nullptr)); #if !defined(_WIN32) && !defined(_WIN32_CE) if( VSIStatL( subdir, &sStatBuf ) != 0 && strlen(subdir) > strlen(baseDir) && subdir[strlen(baseDir)] != 0) { char* c = subdir + strlen(baseDir)+1; while(*c) { if (*c >= 'A' && *c <= 'Z') *c += 'a' - 'A'; c++; } } #endif frameEntry->fullFilePath = CPLStrdup(CPLFormFilename( subdir, frameEntry->filename, nullptr)); if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 ) { #if !defined(_WIN32) && !defined(_WIN32_CE) if( strlen(frameEntry->fullFilePath) > strlen(subdir) ) { char* c = frameEntry->fullFilePath + strlen(subdir)+1; while(*c) { if (*c >= 'A' && *c <= 'Z') *c += 'a' - 'A'; c++; } } if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 ) #endif { frameEntry->fileExists = 0; CPLError( CE_Warning, CPLE_AppDefined, "File %s does not exist.", frameEntry->fullFilePath ); } #if !defined(_WIN32) && !defined(_WIN32_CE) else { frameEntry->fileExists = 1; } #endif } else { frameEntry->fileExists = 1; } CPLFree(subdir); CPLFree(baseDir); } CPLDebug("RPFTOC", "Entry %d : %s,%s (%d, %d)", boundaryId, frameEntry->directory, frameEntry->filename, frameRow, frameCol); frameEntry->exists = 1; } return toc; }
GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Is this a SENTINEL-1 manifest.safe definition? */ /* -------------------------------------------------------------------- */ if ( !SAFEDataset::Identify( poOpenInfo ) ) { return nullptr; } /* -------------------------------------------------------------------- */ /* Get subdataset information, if relevant */ /* -------------------------------------------------------------------- */ CPLString osMDFilename; //Subdataset 1st level selection (ex: for swath selection) CPLString osSelectedSubDS1; //Subdataset 2nd level selection (ex: for polarisation selection) CPLString osSelectedSubDS2; if (STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL1_DS:")) { osMDFilename = poOpenInfo->pszFilename + strlen("SENTINEL1_DS:"); const char* pszSelection1 = strrchr(osMDFilename.c_str(), ':'); if (pszSelection1 == nullptr || pszSelection1 == osMDFilename.c_str() ) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid syntax for SENTINEL1_DS:"); return nullptr; } osMDFilename.resize( pszSelection1 - osMDFilename.c_str() ); osSelectedSubDS1 = pszSelection1 + strlen(":"); const char* pszSelection2 = strchr(osSelectedSubDS1.c_str(), '_'); if (pszSelection2 != nullptr && pszSelection2 != pszSelection1 ) { osSelectedSubDS1.resize( pszSelection2 - osSelectedSubDS1.c_str() ); osSelectedSubDS2 = pszSelection2 + strlen("_"); } //update directory check: VSIStatBufL sStat; if( VSIStatL( osMDFilename.c_str(), &sStat ) == 0 ) poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode ); } else { osMDFilename = poOpenInfo->pszFilename; } if( poOpenInfo->bIsDirectory ) { osMDFilename = CPLFormCIFilename( osMDFilename.c_str(), "manifest.safe", nullptr ); } /* -------------------------------------------------------------------- */ /* Ingest the manifest.safe file. */ /* -------------------------------------------------------------------- */ //TODO REMOVE CPLXMLNode *psImageAttributes, *psImageGenerationParameters; CPLXMLNode *psManifest = CPLParseXMLFile( osMDFilename ); if( psManifest == nullptr ) return nullptr; CPLString osPath(CPLGetPath( osMDFilename )); /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_NotSupported, "The SAFE driver does not support update access to existing" " datasets.\n" ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get contentUnit parent element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psContentUnits = CPLGetXMLNode( psManifest, "=xfdu:XFDU.informationPackageMap.xfdu:contentUnit" ); if( psContentUnits == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><informationPackageMap>" "<xfdu:contentUnit> in manifest file." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get Metadata Objects element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psMetaDataObjects = CPLGetXMLNode( psManifest, "=xfdu:XFDU.metadataSection" ); if( psMetaDataObjects == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><metadataSection>" "in manifest file." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get Data Objects element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDataObjects = CPLGetXMLNode( psManifest, "=xfdu:XFDU.dataObjectSection" ); if( psDataObjects == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><dataObjectSection> in document." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Create the dataset. */ /* -------------------------------------------------------------------- */ SAFEDataset *poDS = new SAFEDataset(); poDS->psManifest = psManifest; /* -------------------------------------------------------------------- */ /* Look for "Measurement Data Unit" contentUnit elements. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAnnotation = nullptr; //Map with all measures aggregated by swath std::map<CPLString, std::set<CPLString> > oMapSwaths2Pols; for( CPLXMLNode *psContentUnit = psContentUnits->psChild; psContentUnit != nullptr; psContentUnit = psContentUnit->psNext ) { if( psContentUnit->eType != CXT_Element || !(EQUAL(psContentUnit->pszValue,"xfdu:contentUnit")) ) { continue; } const char *pszUnitType = CPLGetXMLValue( psContentUnit, "unitType", "" ); const char *pszAnnotation = nullptr; const char *pszCalibration = nullptr; const char *pszMeasurement = nullptr; if ( EQUAL(pszUnitType, "Measurement Data Unit") ) { /* Get dmdID and dataObjectID */ const char *pszDmdID = CPLGetXMLValue(psContentUnit, "dmdID", ""); const char *pszDataObjectID = CPLGetXMLValue( psContentUnit, "dataObjectPointer.dataObjectID", "" ); if( *pszDataObjectID == '\0' || *pszDmdID == '\0' ) { continue; } CPLXMLNode *psDataObject = SAFEDataset::GetDataObject( psDataObjects, pszDataObjectID); const char *pszRepId = CPLGetXMLValue( psDataObject, "repID", "" ); if ( !EQUAL(pszRepId, "s1Level1MeasurementSchema") ) { continue; } pszMeasurement = CPLGetXMLValue( psDataObject, "byteStream.fileLocation.href", ""); if( *pszMeasurement == '\0' ) { continue; } char** papszTokens = CSLTokenizeString2( pszDmdID, " ", CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES ); for( int j = 0; j < CSLCount( papszTokens ); j++ ) { const char* pszId = papszTokens[j]; if( *pszId == '\0' ) { continue; } //Map the metadata ID to the object element CPLXMLNode *psDO = SAFEDataset::GetDataObject( psMetaDataObjects, psDataObjects, pszId); if (psDO == nullptr) { continue; } //check object type pszRepId = CPLGetXMLValue( psDO, "repID", "" ); if( EQUAL(pszRepId, "s1Level1ProductSchema") ) { /* Get annotation filename */ pszAnnotation = CPLGetXMLValue( psDO, "byteStream.fileLocation.href", ""); if( *pszAnnotation == '\0' ) { continue; } } else if( EQUAL(pszRepId, "s1Level1CalibrationSchema") ) { pszCalibration = CPLGetXMLValue( psDO, "byteStream.fileLocation.href", ""); if( *pszCalibration == '\0' ) { continue; } } else { continue; } } CSLDestroy(papszTokens); if (pszAnnotation == nullptr || pszCalibration == nullptr ) { continue; } //open Annotation XML file CPLString osAnnotationFilePath = CPLFormFilename( osPath, pszAnnotation, nullptr ); if( psAnnotation ) CPLDestroyXMLNode(psAnnotation); psAnnotation = CPLParseXMLFile( osAnnotationFilePath ); if( psAnnotation == nullptr ) continue; /* -------------------------------------------------------------------- */ /* Get overall image information. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = atoi(CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.numberOfSamples", "-1" )); poDS->nRasterYSize = atoi(CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.numberOfLines", "-1" )); if (poDS->nRasterXSize <= 1 || poDS->nRasterYSize <= 1) { CPLError( CE_Failure, CPLE_OpenFailed, "Non-sane raster dimensions provided in manifest.safe. " "If this is a valid SENTINEL-1 scene, please contact your " "data provider for a corrected dataset." ); delete poDS; CPLDestroyXMLNode(psAnnotation); return nullptr; } CPLString osProductType = CPLGetXMLValue( psAnnotation, "=product.adsHeader.productType", "UNK" ); CPLString osMissionId = CPLGetXMLValue( psAnnotation, "=product.adsHeader.missionId", "UNK" ); CPLString osPolarisation = CPLGetXMLValue( psAnnotation, "=product.adsHeader.polarisation", "UNK" ); CPLString osMode = CPLGetXMLValue( psAnnotation, "=product.adsHeader.mode", "UNK" ); CPLString osSwath = CPLGetXMLValue( psAnnotation, "=product.adsHeader.swath", "UNK" ); oMapSwaths2Pols[osSwath].insert(osPolarisation); if (osSelectedSubDS1.empty()) { // If not subdataset was selected, // open the first one we can find. osSelectedSubDS1 = osSwath; } if (!EQUAL(osSelectedSubDS1.c_str(), osSwath.c_str())) { //do not mix swath, otherwise it does not work for SLC products continue; } if (!osSelectedSubDS2.empty() && (osSelectedSubDS2.find(osPolarisation)== std::string::npos)) { // Add only selected polarisations. continue; } poDS->SetMetadataItem("PRODUCT_TYPE", osProductType.c_str()); poDS->SetMetadataItem("MISSION_ID", osMissionId.c_str()); poDS->SetMetadataItem("MODE", osMode.c_str()); poDS->SetMetadataItem("SWATH", osSwath.c_str()); /* -------------------------------------------------------------------- */ /* Get dataType (so we can recognize complex data), and the */ /* bitsPerSample. */ /* -------------------------------------------------------------------- */ const char *pszDataType = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.outputPixels", "" ); GDALDataType eDataType; if( EQUAL(pszDataType,"16 bit Signed Integer") ) eDataType = GDT_CInt16; else if( EQUAL(pszDataType,"16 bit Unsigned Integer") ) eDataType = GDT_UInt16; else { delete poDS; CPLError( CE_Failure, CPLE_AppDefined, "dataType=%s: not a supported configuration.", pszDataType ); CPLDestroyXMLNode(psAnnotation); return nullptr; } /* Extract pixel spacing information */ const char *pszPixelSpacing = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.rangePixelSpacing", "UNK" ); poDS->SetMetadataItem( "PIXEL_SPACING", pszPixelSpacing ); const char *pszLineSpacing = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.azimuthPixelSpacing", "UNK" ); poDS->SetMetadataItem( "LINE_SPACING", pszLineSpacing ); /* -------------------------------------------------------------------- */ /* Form full filename (path of manifest.safe + measurement file). */ /* -------------------------------------------------------------------- */ char *pszFullname = CPLStrdup(CPLFormFilename( osPath, pszMeasurement, nullptr )); /* -------------------------------------------------------------------- */ /* Try and open the file. */ /* -------------------------------------------------------------------- */ GDALDataset *poBandFile = reinterpret_cast<GDALDataset *>( GDALOpen( pszFullname, GA_ReadOnly ) ); if( poBandFile == nullptr ) { // NOP } else if (poBandFile->GetRasterCount() == 0) { GDALClose( (GDALRasterBandH) poBandFile ); } else { poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles, osAnnotationFilePath ); poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles, pszFullname ); /* -------------------------------------------------------------------- */ /* Create the band. */ /* -------------------------------------------------------------------- */ SAFERasterBand *poBand = new SAFERasterBand( poDS, eDataType, osSwath.c_str(), osPolarisation.c_str(), poBandFile ); poDS->SetBand( poDS->GetRasterCount() + 1, poBand ); } CPLFree( pszFullname ); } } //loop through all Swath/pols to add subdatasets int iSubDS = 1; for (std::map<CPLString, std::set<CPLString> >::iterator iterSwath=oMapSwaths2Pols.begin(); iterSwath!=oMapSwaths2Pols.end(); ++iterSwath) { CPLString osSubDS1 = iterSwath->first; CPLString osSubDS2; for (std::set<CPLString>::iterator iterPol=iterSwath->second.begin(); iterPol!=iterSwath->second.end(); ++iterPol) { if (!osSubDS2.empty()) { osSubDS2 += "+"; } osSubDS2 += *iterPol; //Create single band SubDataset SAFEDataset::AddSubDataset(poDS, iSubDS, CPLSPrintf("SENTINEL1_DS:%s:%s_%s", osPath.c_str(), osSubDS1.c_str(), (*iterPol).c_str()), CPLSPrintf("Single band with %s swath and %s polarisation", osSubDS1.c_str(), (*iterPol).c_str()) ); iSubDS++; } if (iterSwath->second.size()>1) { //Create single band SubDataset with all polarisations SAFEDataset::AddSubDataset(poDS, iSubDS, CPLSPrintf("SENTINEL1_DS:%s:%s", osPath.c_str(), osSubDS1.c_str()), CPLSPrintf("%s swath with all polarisations as bands", osSubDS1.c_str()) ); iSubDS++; } } if (poDS->GetRasterCount() == 0) { CPLError( CE_Failure, CPLE_OpenFailed, "Measurement bands not found." ); delete poDS; if( psAnnotation ) CPLDestroyXMLNode(psAnnotation); return nullptr; } /* -------------------------------------------------------------------- */ /* Collect more metadata elements */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /* Platform information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psPlatformAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "platform"); if (psPlatformAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:familyName", "" ); poDS->SetMetadataItem( "SATELLITE_IDENTIFIER", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:familyName.abbreviation", "" ); poDS->SetMetadataItem( "SENSOR_IDENTIFIER", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:extension" ".s1sarl1:instrumentMode.s1sarl1:mode", "UNK" ); poDS->SetMetadataItem( "BEAM_MODE", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:extension" ".s1sarl1:instrumentMode.s1sarl1:swath", "UNK" ); poDS->SetMetadataItem( "BEAM_SWATH", pszItem ); } /* -------------------------------------------------------------------- */ /* Acquisition Period information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAcquisitionAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "acquisitionPeriod"); if (psAcquisitionAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psAcquisitionAttrs, "metadataWrap.xmlData.safe:acquisitionPeriod" ".safe:startTime", "UNK" ); poDS->SetMetadataItem( "ACQUISITION_START_TIME", pszItem ); pszItem = CPLGetXMLValue( psAcquisitionAttrs, "metadataWrap.xmlData.safe:acquisitionPeriod" ".safe:stopTime", "UNK" ); poDS->SetMetadataItem( "ACQUISITION_STOP_TIME", pszItem ); } /* -------------------------------------------------------------------- */ /* Processing information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psProcessingAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "processing"); if (psProcessingAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psProcessingAttrs, "metadataWrap.xmlData.safe:processing.safe:facility.name", "UNK" ); poDS->SetMetadataItem( "FACILITY_IDENTIFIER", pszItem ); } /* -------------------------------------------------------------------- */ /* Measurement Orbit Reference information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psOrbitAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "measurementOrbitReference"); if (psOrbitAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psOrbitAttrs, "metadataWrap.xmlData.safe:orbitReference" ".safe:orbitNumber", "UNK" ); poDS->SetMetadataItem( "ORBIT_NUMBER", pszItem ); pszItem = CPLGetXMLValue( psOrbitAttrs, "metadataWrap.xmlData.safe:orbitReference" ".safe:extension.s1:orbitProperties.s1:pass", "UNK" ); poDS->SetMetadataItem( "ORBIT_DIRECTION", pszItem ); } /* -------------------------------------------------------------------- */ /* Collect Annotation Processing Information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psProcessingInfo = CPLGetXMLNode( psAnnotation, "=product.imageAnnotation.processingInformation" ); if ( psProcessingInfo != nullptr ) { OGRSpatialReference oLL, oPrj; const char *pszEllipsoidName = CPLGetXMLValue( psProcessingInfo, "ellipsoidName", "" ); const double minor_axis = CPLAtof(CPLGetXMLValue( psProcessingInfo, "ellipsoidSemiMinorAxis", "0.0" )); const double major_axis = CPLAtof(CPLGetXMLValue( psProcessingInfo, "ellipsoidSemiMajorAxis", "0.0" )); if ( EQUAL(pszEllipsoidName, "") || ( minor_axis == 0.0 ) || ( major_axis == 0.0 ) ) { CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete" " ellipsoid information. Using wgs-84 parameters.\n"); oLL.SetWellKnownGeogCS( "WGS84" ); oPrj.SetWellKnownGeogCS( "WGS84" ); } else if ( EQUAL( pszEllipsoidName, "WGS84" ) ) { oLL.SetWellKnownGeogCS( "WGS84" ); oPrj.SetWellKnownGeogCS( "WGS84" ); } else { const double inv_flattening = major_axis/(major_axis - minor_axis); oLL.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening); oPrj.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening); } CPLFree( poDS->pszGCPProjection ); poDS->pszGCPProjection = nullptr; oLL.exportToWkt( &(poDS->pszGCPProjection) ); } /* -------------------------------------------------------------------- */ /* Collect GCPs. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psGeoGrid = CPLGetXMLNode( psAnnotation, "=product.geolocationGrid.geolocationGridPointList" ); if( psGeoGrid != nullptr ) { /* count GCPs */ poDS->nGCPCount = 0; for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != nullptr; psNode = psNode->psNext ) { if( EQUAL(psNode->pszValue,"geolocationGridPoint") ) poDS->nGCPCount++ ; } poDS->pasGCPList = reinterpret_cast<GDAL_GCP *>( CPLCalloc( sizeof(GDAL_GCP), poDS->nGCPCount ) ); poDS->nGCPCount = 0; for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != nullptr; psNode = psNode->psNext ) { GDAL_GCP *psGCP = poDS->pasGCPList + poDS->nGCPCount; if( !EQUAL(psNode->pszValue,"geolocationGridPoint") ) continue; poDS->nGCPCount++ ; char szID[32]; snprintf( szID, sizeof(szID), "%d", poDS->nGCPCount ); psGCP->pszId = CPLStrdup( szID ); psGCP->pszInfo = CPLStrdup(""); psGCP->dfGCPPixel = CPLAtof(CPLGetXMLValue(psNode,"pixel","0")); psGCP->dfGCPLine = CPLAtof(CPLGetXMLValue(psNode,"line","0")); psGCP->dfGCPX = CPLAtof(CPLGetXMLValue(psNode,"longitude","")); psGCP->dfGCPY = CPLAtof(CPLGetXMLValue(psNode,"latitude","")); psGCP->dfGCPZ = CPLAtof(CPLGetXMLValue(psNode,"height","")); } } CPLDestroyXMLNode(psAnnotation); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ const CPLString osDescription = osMDFilename; /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( osDescription ); poDS->SetPhysicalFilename( osMDFilename ); poDS->SetSubdatasetName( osDescription ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" ); return poDS; }
bool OGRGeomediaDriver::FindDriverLib() { // Default name and path of driver library const char* aszDefaultLibName[] = { "libmdbodbc.so", "libmdbodbc.so.0" /* for Ubuntu 8.04 support */ }; const int nLibNames = sizeof(aszDefaultLibName) / sizeof(aszDefaultLibName[0]); const char* libPath[] = { "/usr/lib", "/usr/local/lib" }; const int nLibPaths = sizeof(libPath) / sizeof(libPath[0]); CPLString strLibPath(""); const char* pszDrvCfg = CPLGetConfigOption("MDBDRIVER_PATH", NULL); if ( NULL != pszDrvCfg ) { // Directory or file path strLibPath = pszDrvCfg; VSIStatBuf sStatBuf = { 0 }; if ( VSIStat( pszDrvCfg, &sStatBuf ) == 0 && VSI_ISDIR( sStatBuf.st_mode ) ) { // Find default library in custom directory const char* pszDriverFile = CPLFormFilename( pszDrvCfg, aszDefaultLibName[0], NULL ); CPLAssert( 0 != pszDriverFile ); strLibPath = pszDriverFile; } if ( LibraryExists( strLibPath.c_str() ) ) { // Save custom driver path osDriverFile = strLibPath; return true; } } // Try to find library in default path for ( int i = 0; i < nLibPaths; i++ ) { for ( int j = 0; j < nLibNames; j++ ) { const char* pszDriverFile = CPLFormFilename( libPath[i], aszDefaultLibName[j], NULL ); CPLAssert( 0 != pszDriverFile ); if ( LibraryExists( pszDriverFile ) ) { // Save default driver path osDriverFile = pszDriverFile; return true; } } } CPLError(CE_Failure, CPLE_AppDefined, "Geomedia: MDB Tools driver not found!\n"); // Driver not found! return false; }
int OGROpenFileGDBDataSource::Open( const char* pszFilename ) { FileGDBTable oTable; m_pszName = CPLStrdup(pszFilename); m_osDirName = pszFilename; int nInterestTable = -1; const char* pszFilenameWithoutPath = CPLGetFilename(pszFilename); if( strlen(pszFilenameWithoutPath) == strlen("a00000000.gdbtable") && pszFilenameWithoutPath[0] == 'a' && sscanf(pszFilenameWithoutPath, "a%08x.gdbtable", &nInterestTable) == 1 ) { m_osDirName = CPLGetPath(m_osDirName); } else { nInterestTable = -1; } if( EQUAL(CPLGetExtension(m_osDirName), "zip") && strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) != 0 ) { m_osDirName = "/vsizip/" + m_osDirName; } else if( EQUAL(CPLGetExtension(m_osDirName), "tar") && strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) != 0 ) { m_osDirName = "/vsitar/" + m_osDirName; } if( strncmp(m_osDirName, "/vsizip/", strlen("/vsizip/")) == 0 || strncmp(m_osDirName, "/vsitar/", strlen("/vsitar/")) == 0) { /* Look for one subdirectory ending with .gdb extension */ char** papszDir = CPLReadDir(m_osDirName); int iCandidate = -1; for( int i=0; papszDir && papszDir[i] != NULL; i++ ) { VSIStatBufL sStat; if( EQUAL(CPLGetExtension(papszDir[i]), "gdb") && VSIStatL( CPLSPrintf("%s/%s", m_osDirName.c_str(), papszDir[i]), &sStat ) == 0 && VSI_ISDIR(sStat.st_mode) ) { if( iCandidate < 0 ) iCandidate = i; else { iCandidate = -1; break; } } } if( iCandidate >= 0 ) { m_osDirName += "/"; m_osDirName += papszDir[iCandidate]; } CSLDestroy(papszDir); } m_papszFiles = VSIReadDir(m_osDirName); /* Explore catalog table */ const char* psza00000001 = CPLFormFilename(m_osDirName, "a00000001", "gdbtable"); if( !FileExists(psza00000001) || !oTable.Open(psza00000001) ) { if( nInterestTable >= 0 && FileExists(m_pszName) ) { const char* pszLyrName = CPLSPrintf("a%08x", nInterestTable); OGROpenFileGDBLayer* poLayer = new OGROpenFileGDBLayer( m_pszName, pszLyrName, "", ""); const char* pszTablX = CPLResetExtension(m_pszName, "gdbtablx"); if( (!FileExists(pszTablX) && poLayer->GetLayerDefn()->GetFieldCount() == 0 && poLayer->GetFeatureCount() == 0) || !poLayer->IsValidLayerDefn() ) { delete poLayer; return FALSE; } m_apoLayers.push_back(poLayer); return TRUE; } return FALSE; } if( !(oTable.GetFieldCount() >= 2 && oTable.GetField(0)->GetName() == "Name" && oTable.GetField(0)->GetType() == FGFT_STRING && oTable.GetField(1)->GetName() == "FileFormat" && (oTable.GetField(1)->GetType() == FGFT_INT16 || oTable.GetField(1)->GetType() == FGFT_INT32) ) ) { return FALSE; } int iGDBItems = -1; /* V10 */ int iGDBFeatureClasses = -1; /* V9.X */ int iGDBObjectClasses = -1; /* V9.X */ int i; std::vector<std::string> aosTableNames; for(i=0;i<oTable.GetTotalRecordCount();i++) { if( !oTable.SelectRow(i) ) { if( oTable.HasGotError() ) break; aosTableNames.push_back(""); continue; } const OGRField* psField = oTable.GetFieldValue(0); if( psField != NULL ) { aosTableNames.push_back(psField->String); if( strcmp(psField->String, "GDB_Items") == 0 ) { iGDBItems = i; } else if( strcmp(psField->String, "GDB_FeatureClasses") == 0 ) { iGDBFeatureClasses = i; } else if( strcmp(psField->String, "GDB_ObjectClasses") == 0 ) { iGDBObjectClasses = i; } m_osMapNameToIdx[psField->String] = 1 + i; } else { aosTableNames.push_back(""); } } oTable.Close(); if( iGDBItems >= 0 ) { int bRet = OpenFileGDBv10(iGDBItems, nInterestTable); if( !bRet ) return FALSE; } else if( iGDBFeatureClasses >= 0 && iGDBObjectClasses >= 0 ) { int bRet = OpenFileGDBv9(iGDBFeatureClasses, iGDBObjectClasses, nInterestTable); if( !bRet ) return FALSE; } else { CPLError(CE_Failure, CPLE_AppDefined, "No GDB_Items nor GDB_FeatureClasses table"); return FALSE; } if( m_apoLayers.size() == 0 && nInterestTable >= 0 ) { if( FileExists(m_pszName) ) { const char* pszLyrName; if( nInterestTable <= (int)aosTableNames.size() && aosTableNames[nInterestTable-1].size() != 0 ) pszLyrName = aosTableNames[nInterestTable-1].c_str(); else pszLyrName = CPLSPrintf("a%08x", nInterestTable); m_apoLayers.push_back(new OGROpenFileGDBLayer( m_pszName, pszLyrName, "", "")); } else { return FALSE; } } return TRUE; }
int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn, int bForceOpen, char** papszOpenOptions ) { pszName = CPLStrdup( pszFilename ); bUpdate = bUpdateIn; if (bUpdateIn && bForceOpen && EQUAL(pszFilename, "/vsistdout/")) return TRUE; /* For writable /vsizip/, do nothing more */ if (bUpdateIn && bForceOpen && strncmp(pszFilename, "/vsizip/", 8) == 0) return TRUE; CPLString osFilename(pszFilename); CPLString osBaseFilename = CPLGetFilename(pszFilename); CPLString osExt = GetRealExtension(osFilename); pszFilename = NULL; int bIgnoreExtension = EQUALN(osFilename, "CSV:", 4); int bUSGeonamesFile = FALSE; /* int bGeonamesOrgFile = FALSE; */ if (bIgnoreExtension) { osFilename = osFilename + 4; } /* Those are *not* real .XLS files, but text file with tab as column separator */ if (EQUAL(osBaseFilename, "NfdcFacilities.xls") || EQUAL(osBaseFilename, "NfdcRunways.xls") || EQUAL(osBaseFilename, "NfdcRemarks.xls") || EQUAL(osBaseFilename, "NfdcSchedules.xls")) { if (bUpdateIn) return FALSE; bIgnoreExtension = TRUE; } else if ((EQUALN(osBaseFilename, "NationalFile_", 13) || EQUALN(osBaseFilename, "POP_PLACES_", 11) || EQUALN(osBaseFilename, "HIST_FEATURES_", 14) || EQUALN(osBaseFilename, "US_CONCISE_", 11) || EQUALN(osBaseFilename, "AllNames_", 9) || EQUALN(osBaseFilename, "Feature_Description_History_", 28) || EQUALN(osBaseFilename, "ANTARCTICA_", 11) || EQUALN(osBaseFilename, "GOVT_UNITS_", 11) || EQUALN(osBaseFilename, "NationalFedCodes_", 17) || EQUALN(osBaseFilename, "AllStates_", 10) || EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) || (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_Features_", 10)) || (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) && (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) ) { if (bUpdateIn) return FALSE; bIgnoreExtension = TRUE; bUSGeonamesFile = TRUE; if (EQUAL(osExt, "zip") && strstr(osFilename, "/vsizip/") == NULL ) { osFilename = "/vsizip/" + osFilename; } } else if (EQUAL(osBaseFilename, "allCountries.txt") || EQUAL(osBaseFilename, "allCountries.zip")) { if (bUpdateIn) return FALSE; bIgnoreExtension = TRUE; /* bGeonamesOrgFile = TRUE; */ if (EQUAL(osExt, "zip") && strstr(osFilename, "/vsizip/") == NULL ) { osFilename = "/vsizip/" + osFilename; } } /* -------------------------------------------------------------------- */ /* Determine what sort of object this is. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStatBuf; if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) != 0 ) return FALSE; /* -------------------------------------------------------------------- */ /* Is this a single CSV file? */ /* -------------------------------------------------------------------- */ if( VSI_ISREG(sStatBuf.st_mode) && (bIgnoreExtension || EQUAL(osExt,"csv") || EQUAL(osExt,"tsv")) ) { if (EQUAL(CPLGetFilename(osFilename), "NfdcFacilities.xls")) { return OpenTable( osFilename, papszOpenOptions, "ARP"); } else if (EQUAL(CPLGetFilename(osFilename), "NfdcRunways.xls")) { OpenTable( osFilename, papszOpenOptions, "BaseEndPhysical"); OpenTable( osFilename, papszOpenOptions, "BaseEndDisplaced"); OpenTable( osFilename, papszOpenOptions, "ReciprocalEndPhysical"); OpenTable( osFilename, papszOpenOptions, "ReciprocalEndDisplaced"); return nLayers != 0; } else if (bUSGeonamesFile) { /* GNIS specific */ if (EQUALN(osBaseFilename, "NationalFedCodes_", 17) || EQUALN(osBaseFilename, "AllStatesFedCodes_", 18) || EQUALN(osBaseFilename, "ANTARCTICA_", 11) || (strlen(osBaseFilename) > 2 && EQUALN(osBaseFilename+2, "_FedCodes_", 10))) { OpenTable( osFilename, papszOpenOptions, NULL, "PRIMARY"); } else if (EQUALN(osBaseFilename, "GOVT_UNITS_", 11) || EQUALN(osBaseFilename, "Feature_Description_History_", 28)) { OpenTable( osFilename, papszOpenOptions, NULL, ""); } else { OpenTable( osFilename, papszOpenOptions, NULL, "PRIM"); OpenTable( osFilename, papszOpenOptions, NULL, "SOURCE"); } return nLayers != 0; } return OpenTable( osFilename, papszOpenOptions ); } /* -------------------------------------------------------------------- */ /* Is this a single a ZIP file with only a CSV file inside ? */ /* -------------------------------------------------------------------- */ if( strncmp(osFilename, "/vsizip/", 8) == 0 && EQUAL(osExt, "zip") && VSI_ISREG(sStatBuf.st_mode) ) { char** papszFiles = VSIReadDir(osFilename); if (CSLCount(papszFiles) != 1 || !EQUAL(CPLGetExtension(papszFiles[0]), "CSV")) { CSLDestroy(papszFiles); return FALSE; } osFilename = CPLFormFilename(osFilename, papszFiles[0], NULL); CSLDestroy(papszFiles); return OpenTable( osFilename, papszOpenOptions ); } /* -------------------------------------------------------------------- */ /* Otherwise it has to be a directory. */ /* -------------------------------------------------------------------- */ if( !VSI_ISDIR(sStatBuf.st_mode) ) return FALSE; /* -------------------------------------------------------------------- */ /* Scan through for entries ending in .csv. */ /* -------------------------------------------------------------------- */ int nNotCSVCount = 0, i; char **papszNames = CPLReadDir( osFilename ); for( i = 0; papszNames != NULL && papszNames[i] != NULL; i++ ) { CPLString oSubFilename = CPLFormFilename( osFilename, papszNames[i], NULL ); if( EQUAL(papszNames[i],".") || EQUAL(papszNames[i],"..") ) continue; if (EQUAL(CPLGetExtension(oSubFilename),"csvt")) continue; if( VSIStatL( oSubFilename, &sStatBuf ) != 0 || !VSI_ISREG(sStatBuf.st_mode) ) { nNotCSVCount++; continue; } if (EQUAL(CPLGetExtension(oSubFilename),"csv")) { if( !OpenTable( oSubFilename, papszOpenOptions ) ) { CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str()); nNotCSVCount++; continue; } } /* GNIS specific */ else if ( strlen(papszNames[i]) > 2 && EQUALN(papszNames[i]+2, "_Features_", 10) && EQUAL(CPLGetExtension(papszNames[i]), "txt") ) { int bRet = OpenTable( oSubFilename, papszOpenOptions, NULL, "PRIM"); bRet |= OpenTable( oSubFilename, papszOpenOptions, NULL, "SOURCE"); if ( !bRet ) { CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str()); nNotCSVCount++; continue; } } /* GNIS specific */ else if ( strlen(papszNames[i]) > 2 && EQUALN(papszNames[i]+2, "_FedCodes_", 10) && EQUAL(CPLGetExtension(papszNames[i]), "txt") ) { if ( !OpenTable( oSubFilename, papszOpenOptions, NULL, "PRIMARY") ) { CPLDebug("CSV", "Cannot open %s", oSubFilename.c_str()); nNotCSVCount++; continue; } } else { nNotCSVCount++; continue; } } CSLDestroy( papszNames ); /* -------------------------------------------------------------------- */ /* We presume that this is indeed intended to be a CSV */ /* datasource if over half the files were .csv files. */ /* -------------------------------------------------------------------- */ return bForceOpen || nNotCSVCount < nLayers; }
int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen, char ** papszLimitedFileList ) { pszName = CPLStrdup( pszFilename ); /* -------------------------------------------------------------------- */ /* Is the given path a directory or a regular file? */ /* -------------------------------------------------------------------- */ VSIStatBufL stat; if( VSIStatExL( pszFilename, &stat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0 || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_AppDefined, "%s is neither a file or directory, Tiger access failed.\n", pszFilename ); return FALSE; } /* -------------------------------------------------------------------- */ /* Build a list of filenames we figure are Tiger files. */ /* -------------------------------------------------------------------- */ char **papszFileList = nullptr; if( VSI_ISREG(stat.st_mode) ) { char szModule[128]; if( strlen(CPLGetFilename(pszFilename)) == 0 ) { return FALSE; } pszPath = CPLStrdup( CPLGetPath(pszFilename) ); strncpy( szModule, CPLGetFilename(pszFilename), sizeof(szModule)-1 ); /* Make sure the buffer is 0 terminated */ szModule[sizeof(szModule)-1] = '\0'; /* And now remove last character of filename */ szModule[strlen(szModule)-1] = '\0'; papszFileList = CSLAddString( papszFileList, szModule ); } else { char **candidateFileList = VSIReadDir( pszFilename ); pszPath = CPLStrdup( pszFilename ); for( int i = 0; candidateFileList != nullptr && candidateFileList[i] != nullptr; i++ ) { size_t nCandidateLen = strlen(candidateFileList[i]); if( papszLimitedFileList != nullptr && CSLFindString(papszLimitedFileList, CPLGetBasename(candidateFileList[i])) == -1 ) { continue; } if( nCandidateLen > 4 && candidateFileList[i][nCandidateLen-4] == '.' && candidateFileList[i][nCandidateLen-1] == '1') { char szModule[128]; snprintf( szModule, sizeof(szModule), "%s", candidateFileList[i] ); const size_t nLen = strlen(szModule); if( nLen ) szModule[nLen-1] = '\0'; papszFileList = CSLAddString(papszFileList, szModule); } } CSLDestroy( candidateFileList ); if( CSLCount(papszFileList) == 0 ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_OpenFailed, "No candidate Tiger files (TGR*.RT1) found in\n" "directory: %s", pszFilename ); CSLDestroy(papszFileList); return FALSE; } } /* -------------------------------------------------------------------- */ /* Loop over all these files trying to open them. In testopen */ /* mode we first read the first 80 characters, to verify that */ /* it looks like an Tiger file. Note that we don't keep the file */ /* open ... we don't want to occupy a lot of file handles when */ /* handling a whole directory. */ /* -------------------------------------------------------------------- */ papszModules = nullptr; for( int i = 0; papszFileList && papszFileList[i] != nullptr; i++ ) { if( bTestOpen || i == 0 ) { char *l_pszFilename = BuildFilename( papszFileList[i], "1" ); VSILFILE *fp = VSIFOpenL( l_pszFilename, "rb" ); CPLFree( l_pszFilename ); if( fp == nullptr ) continue; char szHeader[500] = {}; if( VSIFReadL( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 ) { VSIFCloseL( fp ); continue; } VSIFCloseL( fp ); char *pszRecStart = szHeader; szHeader[sizeof(szHeader)-1] = '\0'; bool bIsGDT = false; if( STARTS_WITH_CI(pszRecStart, "Copyright (C)") && strstr(pszRecStart,"Geographic Data Tech") != nullptr ) { bIsGDT = true; while( *pszRecStart != '\0' && *pszRecStart != 10 && *pszRecStart != 13 ) pszRecStart++; while( *pszRecStart == 10 || *pszRecStart == 13 ) pszRecStart++; } if( pszRecStart[0] != '1' ) continue; if( !isdigit(pszRecStart[1]) || !isdigit(pszRecStart[2]) || !isdigit(pszRecStart[3]) || !isdigit(pszRecStart[4]) ) continue; nVersionCode = atoi(TigerFileBase::GetField( pszRecStart, 2, 5 )); nVersion = TigerClassifyVersion( nVersionCode ); nVersion = TigerCheckVersion( nVersion, papszFileList[i] ); CPLDebug( "OGR", "Tiger Version Code=%d, Classified as %s ", nVersionCode, TigerVersionString(nVersion) ); if( nVersionCode != 0 && nVersionCode != 2 && nVersionCode != 3 && nVersionCode != 5 && nVersionCode != 21 && nVersionCode != 24 && pszRecStart[3] != '9' && pszRecStart[3] != DIGIT_ZERO && !bIsGDT ) continue; // we could (and should) add a bunch more validation here. } papszModules = CSLAddString( papszModules, papszFileList[i] ); } CSLDestroy( papszFileList ); nModules = CSLCount( papszModules ); if( nModules == 0 || papszModules == nullptr ) { if( !bTestOpen ) { if( VSI_ISREG(stat.st_mode) ) CPLError( CE_Failure, CPLE_OpenFailed, "No TIGER/Line files (TGR*.RT1) found in\n" "directory: %s", pszFilename ); else CPLError( CE_Failure, CPLE_OpenFailed, "File %s does not appear to be a TIGER/Line .RT1 file.", pszFilename ); } return FALSE; } /* -------------------------------------------------------------------- */ /* Do we have a user provided version override? */ /* -------------------------------------------------------------------- */ const char *pszRequestedVersion = CPLGetConfigOption( "TIGER_VERSION", nullptr ); if( pszRequestedVersion != nullptr ) { if( STARTS_WITH_CI(pszRequestedVersion, "TIGER_") ) { int iCode = 1; // Used after for. for( ; iCode < TIGER_Unknown; iCode++ ) { if( EQUAL(TigerVersionString((TigerVersion)iCode), pszRequestedVersion) ) { nVersion = (TigerVersion) iCode; break; } } if( iCode == TIGER_Unknown ) { CPLError( CE_Failure, CPLE_AppDefined, "Failed to recognise TIGER_VERSION setting: %s", pszRequestedVersion ); return FALSE; } CPLDebug( "OGR", "OVERRIDE Tiger Version %s ", TigerVersionString(nVersion) ); } else { nVersionCode = atoi(pszRequestedVersion); nVersion = TigerClassifyVersion( nVersionCode ); CPLDebug( "OGR", "OVERRIDE Tiger Version Code=%d, Classified as %s ", nVersionCode, TigerVersionString(nVersion) ); } } /* -------------------------------------------------------------------- */ /* Create the layers which appear to exist. */ /* -------------------------------------------------------------------- */ // RT1, RT2, RT3 AddLayer( new OGRTigerLayer( this, new TigerCompleteChain( this, papszModules[0]) )); /* should we have kept track of whether we encountered an RT4 file? */ // RT4 AddLayer( new OGRTigerLayer( this, new TigerAltName( this, papszModules[0]) )); // RT5 AddLayer( new OGRTigerLayer( this, new TigerFeatureIds( this, papszModules[0]) )); // RT6 AddLayer( new OGRTigerLayer( this, new TigerZipCodes( this, papszModules[0]) )); // RT7 AddLayer( new OGRTigerLayer( this, new TigerLandmarks( this, papszModules[0]) )); // RT8 AddLayer( new OGRTigerLayer( this, new TigerAreaLandmarks( this, papszModules[0]) )); // RT9 if (nVersion < TIGER_2002) { AddLayer( new OGRTigerLayer( this, new TigerKeyFeatures( this, papszModules[0]) )); } // RTA, RTS AddLayer( new OGRTigerLayer( this, new TigerPolygon( this, papszModules[0]) )); // RTB if (nVersion >= TIGER_2002) { AddLayer( new OGRTigerLayer( this, new TigerPolygonCorrections( this, papszModules[0]) )); } // RTC AddLayer( new OGRTigerLayer( this, new TigerEntityNames( this, papszModules[0]) )); // RTE if (nVersion >= TIGER_2002) { AddLayer( new OGRTigerLayer( this, new TigerPolygonEconomic( this, papszModules[0]) )); } // RTH AddLayer( new OGRTigerLayer( this, new TigerIDHistory( this, papszModules[0]) )); // RTI AddLayer( new OGRTigerLayer( this, new TigerPolyChainLink( this, papszModules[0]) )); // RTM AddLayer( new OGRTigerLayer( this, new TigerSpatialMetadata( this, papszModules[0] ) ) ); // RTP AddLayer( new OGRTigerLayer( this, new TigerPIP( this, papszModules[0]) )); // RTR AddLayer( new OGRTigerLayer( this, new TigerTLIDRange( this, papszModules[0]) )); // RTT if (nVersion >= TIGER_2002) { AddLayer( new OGRTigerLayer( this, new TigerZeroCellID( this, papszModules[0]) )); } // RTU if (nVersion >= TIGER_2002) { AddLayer( new OGRTigerLayer( this, new TigerOverUnder( this, papszModules[0]) )); } // RTZ AddLayer( new OGRTigerLayer( this, new TigerZipPlus4( this, papszModules[0]) )); return TRUE; }
int OGRTABDataSource::Create( const char * pszName, char **papszOptions ) { CPLAssert(m_pszName == nullptr); m_pszName = CPLStrdup(pszName); m_papszOptions = CSLDuplicate(papszOptions); m_bUpdate = TRUE; const char *pszOpt = CSLFetchNameValue(papszOptions, "FORMAT"); if( pszOpt != nullptr && EQUAL(pszOpt, "MIF") ) m_bCreateMIF = TRUE; else if( EQUAL(CPLGetExtension(pszName),"mif") || EQUAL(CPLGetExtension(pszName),"mid") ) m_bCreateMIF = TRUE; if( (pszOpt = CSLFetchNameValue(papszOptions,"SPATIAL_INDEX_MODE")) != nullptr ) { if( EQUAL(pszOpt, "QUICK") ) m_bQuickSpatialIndexMode = TRUE; else if( EQUAL(pszOpt, "OPTIMIZED") ) m_bQuickSpatialIndexMode = FALSE; } m_nBlockSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "512")); // Create a new empty directory. VSIStatBufL sStat; if( strlen(CPLGetExtension(pszName)) == 0 ) { if( VSIStatL( pszName, &sStat ) == 0 ) { if( !VSI_ISDIR(sStat.st_mode) ) { CPLError(CE_Failure, CPLE_OpenFailed, "Attempt to create dataset named %s,\n" "but that is an existing file.", pszName); return FALSE; } } else { if( VSIMkdir(pszName, 0755) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Unable to create directory %s.", pszName); return FALSE; } } m_pszDirectory = CPLStrdup(pszName); } // Create a new single file. else { IMapInfoFile *poFile = nullptr; const char *pszEncoding( CSLFetchNameValue( papszOptions, "ENCODING" ) ); const char *pszCharset( IMapInfoFile::EncodingToCharset( pszEncoding ) ); if( m_bCreateMIF ) { poFile = new MIFFile; if( poFile->Open(m_pszName, TABWrite, FALSE, pszCharset) != 0 ) { delete poFile; return FALSE; } } else { TABFile *poTabFile = new TABFile; if( poTabFile->Open(m_pszName, TABWrite, FALSE, m_nBlockSize, pszCharset) != 0 ) { delete poTabFile; return FALSE; } poFile = poTabFile; } m_nLayerCount = 1; m_papoLayers = static_cast<IMapInfoFile **>(CPLMalloc(sizeof(void *))); m_papoLayers[0] = poFile; m_pszDirectory = CPLStrdup(CPLGetPath(pszName)); m_bSingleFile = TRUE; } return TRUE; }
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(). */ /* -------------------------------------------------------------------- */ #ifdef WIN32 if( strlen(pszFilenameIn) == 2 && pszFilenameIn[1] == ':' ) { char szAltPath[10]; strcpy( szAltPath, pszFilenameIn ); strcat( szAltPath, "\\" ); pszFilename = CPLStrdup( szAltPath ); } else #endif pszFilename = CPLStrdup( pszFilenameIn ); /* -------------------------------------------------------------------- */ /* Initialize. */ /* -------------------------------------------------------------------- */ nHeaderBytes = 0; nHeaderBytesTried = 0; pabyHeader = NULL; bIsDirectory = FALSE; bStatOK = FALSE; nOpenFlags = nOpenFlagsIn; eAccess = (nOpenFlags & GDAL_OF_UPDATE) ? GA_Update : GA_ReadOnly; fpL = NULL; papszOpenOptions = NULL; #ifdef HAVE_READLINK bool bHasRetried = false; #endif /* -------------------------------------------------------------------- */ /* Collect information about the file. */ /* -------------------------------------------------------------------- */ VSIStatBufL sStat; #ifdef HAVE_READLINK retry: #endif bool bPotentialDirectory = false; /* Check if the filename might be a directory of a special virtual file system */ if( strncmp(pszFilename, "/vsizip/", strlen("/vsizip/")) == 0 || strncmp(pszFilename, "/vsitar/", strlen("/vsitar/")) == 0 ) { const char* pszExt = CPLGetExtension(pszFilename); if( EQUAL(pszExt, "zip") || EQUAL(pszExt, "tar") || EQUAL(pszExt, "gz") ) bPotentialDirectory = true; } else if( strncmp(pszFilename, "/vsicurl/", strlen("/vsicurl/")) == 0 ) { bPotentialDirectory = true; } if( bPotentialDirectory ) { /* 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 ) { bStatOK = TRUE; if( VSI_ISDIR( sStat.st_mode ) ) bIsDirectory = TRUE; } } if( !bIsDirectory ) fpL = VSIFOpenL( pszFilename, (eAccess == GA_Update) ? "r+b" : "rb" ); if( fpL != NULL ) { bStatOK = TRUE; pabyHeader = (GByte *) CPLCalloc(1025,1); nHeaderBytesTried = 1024; nHeaderBytes = (int) VSIFReadL( pabyHeader, 1, nHeaderBytesTried, fpL ); VSIRewindL( fpL ); /* If we cannot read anything, check if it is not a directory instead */ if( nHeaderBytes == 0 && VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 && VSI_ISDIR( sStat.st_mode ) ) { VSIFCloseL(fpL); fpL = NULL; CPLFree(pabyHeader); pabyHeader = NULL; bIsDirectory = TRUE; } } else if( !bStatOK ) { if( VSIStatExL( pszFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) == 0 ) { bStatOK = TRUE; if( VSI_ISDIR( sStat.st_mode ) ) bIsDirectory = TRUE; } #ifdef HAVE_READLINK else if ( !bHasRetried && strncmp(pszFilename, "/vsi", strlen("/vsi")) != 0 ) { /* If someone creates a file with "ln -sf /vsicurl/http://download.osgeo.org/gdal/data/gtiff/utm.tif my_remote_utm.tif" */ /* we will be able to open it by passing my_remote_utm.tif */ /* This helps a lot for GDAL based readers that only provide file explorers to open datasets */ char szPointerFilename[2048]; int nBytes = readlink(pszFilename, szPointerFilename, sizeof(szPointerFilename)); if (nBytes != -1) { szPointerFilename[MIN(nBytes, (int)sizeof(szPointerFilename)-1)] = 0; CPLFree(pszFilename); pszFilename = CPLStrdup(szPointerFilename); papszSiblingsIn = NULL; bHasRetried = true; goto retry; } } #endif } /* -------------------------------------------------------------------- */ /* Capture sibling list either from passed in values, or by */ /* scanning for them only if requested through GetSiblingFiles(). */ /* -------------------------------------------------------------------- */ if( papszSiblingsIn != NULL ) { papszSiblingFiles = CSLDuplicate( papszSiblingsIn ); bHasGotSiblingFiles = TRUE; } else if( bStatOK && !bIsDirectory ) { const char* pszOptionVal = CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" ); if (EQUAL(pszOptionVal, "EMPTY_DIR")) { papszSiblingFiles = CSLAddString( NULL, CPLGetFilename(pszFilename) ); bHasGotSiblingFiles = TRUE; } else if( CSLTestBoolean(pszOptionVal) ) { /* skip reading the directory */ papszSiblingFiles = NULL; bHasGotSiblingFiles = TRUE; } else { /* will be lazy loaded */ papszSiblingFiles = NULL; bHasGotSiblingFiles = FALSE; } } else { papszSiblingFiles = NULL; bHasGotSiblingFiles = TRUE; } }