VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename, const char *pszAccess) { char* tarFilename; CPLString osTarInFileName; if (strchr(pszAccess, 'w') != NULL || strchr(pszAccess, '+') != NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Only read-only mode is supported for /vsitar"); return NULL; } tarFilename = SplitFilename(pszFilename, osTarInFileName, TRUE); if (tarFilename == NULL) return NULL; VSIArchiveReader* poReader = OpenArchiveFile(tarFilename, osTarInFileName); if (poReader == NULL) { CPLFree(tarFilename); return NULL; } CPLString osSubFileName("/vsisubfile/"); VSITarEntryFileOffset* pOffset = (VSITarEntryFileOffset*) poReader->GetFileOffset(); osSubFileName += CPLString().Printf(CPL_FRMT_GUIB, pOffset->nOffset); osSubFileName += "_"; osSubFileName += CPLString().Printf(CPL_FRMT_GUIB, poReader->GetFileSize()); osSubFileName += ","; delete pOffset; if (VSIIsTGZ(tarFilename)) { osSubFileName += "/vsigzip/"; osSubFileName += tarFilename; } else osSubFileName += tarFilename; delete(poReader); CPLFree(tarFilename); tarFilename = NULL; return (VSIVirtualHandle* )VSIFOpenL(osSubFileName, "rb"); }
int VSIArchiveFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf, CPL_UNUSED int nFlags ) { int ret = -1; CPLString osFileInArchive; memset(pStatBuf, 0, sizeof(VSIStatBufL)); char* archiveFilename = SplitFilename(pszFilename, osFileInArchive, TRUE); if (archiveFilename == NULL) return -1; if (strlen(osFileInArchive) != 0) { if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Looking for %s %s\n", archiveFilename, osFileInArchive.c_str()); const VSIArchiveEntry* archiveEntry = NULL; if (FindFileInArchive(archiveFilename, osFileInArchive, &archiveEntry)) { /* Patching st_size with uncompressed file size */ pStatBuf->st_size = archiveEntry->uncompressed_size; pStatBuf->st_mtime = (time_t)archiveEntry->nModifiedTime; if (archiveEntry->bIsDir) pStatBuf->st_mode = S_IFDIR; else pStatBuf->st_mode = S_IFREG; ret = 0; } } else { VSIArchiveReader* poReader = CreateReader(archiveFilename); CPLFree(archiveFilename); archiveFilename = NULL; if (poReader != NULL && poReader->GotoFirstFile()) { /* Skip optionnal leading subdir */ CPLString osFileName = poReader->GetFileName(); const char* fileName = osFileName.c_str(); if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\') { if (poReader->GotoNextFile() == FALSE) { delete(poReader); return -1; } } if (poReader->GotoNextFile()) { /* Several files in archive --> treat as dir */ pStatBuf->st_size = 0; pStatBuf->st_mode = S_IFDIR; } else { /* Patching st_size with uncompressed file size */ pStatBuf->st_size = poReader->GetFileSize(); pStatBuf->st_mtime = (time_t)poReader->GetModifiedTime(); pStatBuf->st_mode = S_IFREG; } ret = 0; } delete(poReader); } CPLFree(archiveFilename); return ret; }