const char *GDALPamDataset::BuildPamFilename() { if( psPam == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* What is the name of the physical file we are referencing? */ /* We allow an override via the psPam->pszPhysicalFile item. */ /* -------------------------------------------------------------------- */ if( psPam->pszPamFilename != NULL ) return psPam->pszPamFilename; const char *pszPhysicalFile = psPam->osPhysicalFilename; if( strlen(pszPhysicalFile) == 0 && GetDescription() != NULL ) pszPhysicalFile = GetDescription(); if( strlen(pszPhysicalFile) == 0 ) return NULL; /* -------------------------------------------------------------------- */ /* Try a proxy lookup, otherwise just add .aux.xml. */ /* -------------------------------------------------------------------- */ const char *pszProxyPam = PamGetProxy( pszPhysicalFile ); if( pszProxyPam != NULL ) psPam->pszPamFilename = CPLStrdup(pszProxyPam); else { psPam->pszPamFilename = (char*) CPLMalloc(strlen(pszPhysicalFile)+10); strcpy( psPam->pszPamFilename, pszPhysicalFile ); strcat( psPam->pszPamFilename, ".aux.xml" ); } return psPam->pszPamFilename; }
const char *PamAllocateProxy( const char *pszOriginal ) { InitProxyDB(); if( poProxyDB == NULL ) return NULL; CPLMutexHolderD( &hProxyDBLock ); poProxyDB->CheckLoadDB(); /* -------------------------------------------------------------------- */ /* Form the proxy filename based on the original path if */ /* possible, but dummy out any questionable characters, path */ /* delimiters and such. This is intended to make the proxy */ /* name be identifiable by folks digging around in the proxy */ /* database directory. */ /* */ /* We also need to be careful about length. */ /* -------------------------------------------------------------------- */ CPLString osRevProxyFile; int i; i = strlen(pszOriginal) - 1; while( i >= 0 && osRevProxyFile.size() < 220 ) { if( i > 6 && EQUALN(pszOriginal+i-5,":::OVR",6) ) i -= 6; // make some effort to break long names at path delimiters. if( (pszOriginal[i] == '/' || pszOriginal[i] == '\\') && osRevProxyFile.size() > 200 ) break; if( (pszOriginal[i] >= 'A' && pszOriginal[i] <= 'Z') || (pszOriginal[i] >= 'a' && pszOriginal[i] <= 'z') || (pszOriginal[i] >= '0' && pszOriginal[i] <= '9') || pszOriginal[i] == '.' ) osRevProxyFile += pszOriginal[i]; else osRevProxyFile += '_'; i--; } CPLString osOriginal = pszOriginal; CPLString osProxy; CPLString osCounter; osProxy = poProxyDB->osProxyDBDir + "/"; osCounter.Printf( "%06d_", poProxyDB->nUpdateCounter++ ); osProxy += osCounter; for( i = osRevProxyFile.size()-1; i >= 0; i-- ) osProxy += osRevProxyFile[i]; if( osOriginal.find(":::OVR") != CPLString::npos ) osProxy += ".ovr"; else osProxy += ".aux.xml"; /* -------------------------------------------------------------------- */ /* Add the proxy and the original to the proxy list and resave */ /* the database. */ /* -------------------------------------------------------------------- */ poProxyDB->aosOriginalFiles.push_back( osOriginal ); poProxyDB->aosProxyFiles.push_back( osProxy ); poProxyDB->SaveDB(); return PamGetProxy( pszOriginal ); }
CPLErr GDALPamDataset::TrySaveXML() { CPLXMLNode *psTree; CPLErr eErr = CE_None; nPamFlags &= ~GPF_DIRTY; if( psPam == NULL || (nPamFlags & GPF_NOSAVE) ) return CE_None; /* -------------------------------------------------------------------- */ /* Make sure we know the filename we want to store in. */ /* -------------------------------------------------------------------- */ if( !BuildPamFilename() ) return CE_None; /* -------------------------------------------------------------------- */ /* Build the XML representation of the auxilary metadata. */ /* -------------------------------------------------------------------- */ CPLString osVRTPath = CPLGetPath(psPam->pszPamFilename); psTree = SerializeToXML( osVRTPath ); if( psTree == NULL ) return CE_None; /* -------------------------------------------------------------------- */ /* If we are working with a subdataset, we need to integrate */ /* the subdataset tree within the whole existing pam tree, */ /* after removing any old version of the same subdataset. */ /* -------------------------------------------------------------------- */ if( psPam->osSubdatasetName.size() != 0 ) { CPLXMLNode *psOldTree, *psSubTree; CPLErrorReset(); CPLPushErrorHandler( CPLQuietErrorHandler ); psOldTree = CPLParseXMLFile( psPam->pszPamFilename ); CPLPopErrorHandler(); if( psOldTree == NULL ) psOldTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" ); for( psSubTree = psTree->psChild; psSubTree != NULL; psSubTree = psSubTree->psNext ) { if( psSubTree->eType != CXT_Element || !EQUAL(psSubTree->pszValue,"Subdataset") ) continue; if( !EQUAL(CPLGetXMLValue( psSubTree, "name", "" ), psPam->osSubdatasetName) ) continue; break; } if( psSubTree == NULL ) { psSubTree = CPLCreateXMLNode( psOldTree, CXT_Element, "Subdataset" ); CPLCreateXMLNode( CPLCreateXMLNode( psSubTree, CXT_Attribute, "name" ), CXT_Text, psPam->osSubdatasetName ); } CPLXMLNode *psOldPamDataset = CPLGetXMLNode( psSubTree, "PAMDataset"); if( psOldPamDataset != NULL ) { CPLRemoveXMLChild( psSubTree, psOldPamDataset ); CPLDestroyXMLNode( psOldPamDataset ); } CPLAddXMLChild( psSubTree, psTree ); psTree = psOldTree; } /* -------------------------------------------------------------------- */ /* Try saving the auxilary metadata. */ /* -------------------------------------------------------------------- */ const char *pszNewPam; int bSaved; CPLPushErrorHandler( CPLQuietErrorHandler ); bSaved = CPLSerializeXMLTreeToFile( psTree, psPam->pszPamFilename ); CPLPopErrorHandler(); /* -------------------------------------------------------------------- */ /* If it fails, check if we have a proxy directory for auxilary */ /* metadata to be stored in, and try to save there. */ /* -------------------------------------------------------------------- */ if( bSaved ) eErr = CE_None; else if( PamGetProxy(GetDescription()) == NULL && ((pszNewPam = PamAllocateProxy(GetDescription())) != NULL)) { CPLErrorReset(); CPLFree( psPam->pszPamFilename ); psPam->pszPamFilename = CPLStrdup(pszNewPam); eErr = TrySaveXML(); } else { CPLError( CE_Warning, CPLE_AppDefined, "Unable to save auxilary information in %s.", psPam->pszPamFilename ); eErr = CE_Warning; } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ CPLDestroyXMLNode( psTree ); return eErr; }