LCOV - code coverage report
Current view: directory - port - cpl_vsil_abstract_archive.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 258 209 81.0 %
Date: 2012-12-26 Functions: 21 10 47.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: cpl_vsil_abstract_archive.cpp 23817 2012-01-28 17:39:00Z rouault $
       3                 :  *
       4                 :  * Project:  CPL - Common Portability Library
       5                 :  * Purpose:  Implement VSI large file api for archive files.
       6                 :  * Author:   Even Rouault, even.rouault at mines-paris.org
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Even Rouault
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_vsi_virtual.h"
      31                 : #include "cpl_string.h"
      32                 : #include "cpl_multiproc.h"
      33                 : #include <map>
      34                 : #include <set>
      35                 : 
      36                 : #define ENABLE_DEBUG 0
      37                 : 
      38                 : CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 23817 2012-01-28 17:39:00Z rouault $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                    ~VSIArchiveEntryFileOffset()                      */
      42                 : /************************************************************************/
      43                 : 
      44            2465 : VSIArchiveEntryFileOffset::~VSIArchiveEntryFileOffset()
      45                 : {
      46            2465 : }
      47                 : 
      48                 : /************************************************************************/
      49                 : /*                        ~VSIArchiveReader()                           */
      50                 : /************************************************************************/
      51                 : 
      52             376 : VSIArchiveReader::~VSIArchiveReader()
      53                 : {
      54             376 : }
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                   VSIArchiveFilesystemHandler()                      */
      58                 : /************************************************************************/
      59                 : 
      60            1424 : VSIArchiveFilesystemHandler::VSIArchiveFilesystemHandler()
      61                 : {
      62            1424 :     hMutex = NULL;
      63            1424 : }
      64                 : 
      65                 : /************************************************************************/
      66                 : /*                   ~VSIArchiveFilesystemHandler()                     */
      67                 : /************************************************************************/
      68                 : 
      69            1374 : VSIArchiveFilesystemHandler::~VSIArchiveFilesystemHandler()
      70                 : 
      71                 : {
      72            1374 :     std::map<CPLString,VSIArchiveContent*>::const_iterator iter;
      73                 : 
      74            1423 :     for( iter = oFileList.begin(); iter != oFileList.end(); ++iter )
      75                 :     {
      76              49 :         VSIArchiveContent* content = iter->second;
      77                 :         int i;
      78            3870 :         for(i=0;i<content->nEntries;i++)
      79                 :         {
      80            3821 :             delete content->entries[i].file_pos;
      81            3821 :             CPLFree(content->entries[i].fileName);
      82                 :         }
      83              49 :         CPLFree(content->entries);
      84              49 :         delete content;
      85                 :     }
      86                 : 
      87            1374 :     if( hMutex != NULL )
      88               6 :         CPLDestroyMutex( hMutex );
      89            1374 :     hMutex = NULL;
      90            1374 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                       GetContentOfArchive()                          */
      94                 : /************************************************************************/
      95                 : 
      96            2913 : const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
      97                 :         (const char* archiveFilename, VSIArchiveReader* poReader)
      98                 : {
      99            2913 :     CPLMutexHolder oHolder( &hMutex );
     100                 : 
     101            2913 :     if (oFileList.find(archiveFilename) != oFileList.end() )
     102                 :     {
     103            2860 :         return oFileList[archiveFilename];
     104                 :     }
     105                 : 
     106              53 :     int bMustClose = (poReader == NULL);
     107              53 :     if (poReader == NULL)
     108                 :     {
     109              53 :         poReader = CreateReader(archiveFilename);
     110              53 :         if (!poReader)
     111               0 :             return NULL;
     112                 :     }
     113                 : 
     114              53 :     if (poReader->GotoFirstFile() == FALSE)
     115                 :     {
     116               0 :         if (bMustClose)
     117               0 :             delete(poReader);
     118               0 :         return NULL;
     119                 :     }
     120                 : 
     121              53 :     VSIArchiveContent* content = new VSIArchiveContent;
     122              53 :     content->nEntries = 0;
     123              53 :     content->entries = NULL;
     124              53 :     oFileList[archiveFilename] = content;
     125                 : 
     126              53 :     std::set<CPLString> oSet;
     127                 : 
     128            2449 :     do
     129                 :     {
     130            2449 :         CPLString osFileName = poReader->GetFileName();
     131            2449 :         const char* fileName = osFileName.c_str();
     132                 : 
     133                 :         /* Remove ./ pattern at the beginning of a filename */
     134            2449 :         if (fileName[0] == '.' && fileName[1] == '/')
     135                 :         {
     136               0 :             fileName += 2;
     137               0 :             if (fileName[0] == '\0')
     138               0 :                 continue;
     139                 :         }
     140                 : 
     141            2449 :         char* pszStrippedFileName = CPLStrdup(fileName);
     142                 :         char* pszIter;
     143           90438 :         for(pszIter = pszStrippedFileName;*pszIter;pszIter++)
     144                 :         {
     145           87989 :             if (*pszIter == '\\')
     146               0 :                 *pszIter = '/';
     147                 :         }
     148                 : 
     149                 :         int bIsDir = strlen(fileName) > 0 &&
     150            2449 :                       fileName[strlen(fileName)-1] == '/';
     151            2449 :         if (bIsDir)
     152                 :         {
     153                 :             /* Remove trailing slash */
     154              43 :             pszStrippedFileName[strlen(fileName)-1] = 0;
     155                 :         }
     156                 : 
     157            2449 :         if (oSet.find(pszStrippedFileName) == oSet.end())
     158                 :         {
     159            2449 :             oSet.insert(pszStrippedFileName);
     160                 : 
     161                 :             /* Add intermediate directory structure */
     162           90395 :             for(pszIter = pszStrippedFileName;*pszIter;pszIter++)
     163                 :             {
     164           87946 :                 if (*pszIter == '/')
     165                 :                 {
     166            7443 :                     char* pszStrippedFileName2 = CPLStrdup(pszStrippedFileName);
     167            7443 :                     pszStrippedFileName2[pszIter - pszStrippedFileName] = 0;
     168            7443 :                     if (oSet.find(pszStrippedFileName2) == oSet.end())
     169                 :                     {
     170            1421 :                         oSet.insert(pszStrippedFileName2);
     171                 : 
     172                 :                         content->entries = (VSIArchiveEntry*)CPLRealloc(content->entries,
     173            1421 :                                 sizeof(VSIArchiveEntry) * (content->nEntries + 1));
     174            1421 :                         content->entries[content->nEntries].fileName = pszStrippedFileName2;
     175            1421 :                         content->entries[content->nEntries].nModifiedTime = poReader->GetModifiedTime();
     176            1421 :                         content->entries[content->nEntries].uncompressed_size = 0;
     177            1421 :                         content->entries[content->nEntries].bIsDir = TRUE;
     178            1421 :                         content->entries[content->nEntries].file_pos = NULL;
     179                 :                         if (ENABLE_DEBUG)
     180                 :                             CPLDebug("VSIArchive", "[%d] %s : " CPL_FRMT_GUIB " bytes", content->nEntries+1,
     181                 :                                 content->entries[content->nEntries].fileName,
     182                 :                                 content->entries[content->nEntries].uncompressed_size);
     183            1421 :                         content->nEntries++;
     184                 :                     }
     185                 :                     else
     186                 :                     {
     187            6022 :                         CPLFree(pszStrippedFileName2);
     188                 :                     }
     189                 :                 }
     190                 :             }
     191                 : 
     192                 :             content->entries = (VSIArchiveEntry*)CPLRealloc(content->entries,
     193            2449 :                                 sizeof(VSIArchiveEntry) * (content->nEntries + 1));
     194            2449 :             content->entries[content->nEntries].fileName = pszStrippedFileName;
     195            2449 :             content->entries[content->nEntries].nModifiedTime = poReader->GetModifiedTime();
     196            2449 :             content->entries[content->nEntries].uncompressed_size = poReader->GetFileSize();
     197            2449 :             content->entries[content->nEntries].bIsDir = bIsDir;
     198            2449 :             content->entries[content->nEntries].file_pos = poReader->GetFileOffset();
     199                 :             if (ENABLE_DEBUG)
     200                 :                 CPLDebug("VSIArchive", "[%d] %s : " CPL_FRMT_GUIB " bytes", content->nEntries+1,
     201                 :                     content->entries[content->nEntries].fileName,
     202                 :                     content->entries[content->nEntries].uncompressed_size);
     203            2449 :             content->nEntries++;
     204                 :         }
     205                 :         else
     206                 :         {
     207               0 :             CPLFree(pszStrippedFileName);
     208               0 :         }
     209            2449 :     } while(poReader->GotoNextFile());
     210                 : 
     211              53 :     if (bMustClose)
     212              53 :         delete(poReader);
     213                 : 
     214              53 :     return content;
     215                 : }
     216                 : 
     217                 : /************************************************************************/
     218                 : /*                        FindFileInArchive()                           */
     219                 : /************************************************************************/
     220                 : 
     221            1345 : int VSIArchiveFilesystemHandler::FindFileInArchive(const char* archiveFilename,
     222                 :                                            const char* fileInArchiveName,
     223                 :                                            const VSIArchiveEntry** archiveEntry)
     224                 : {
     225            1345 :     if (fileInArchiveName == NULL)
     226               0 :         return FALSE;
     227                 : 
     228            1345 :     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
     229            1345 :     if (content)
     230                 :     {
     231                 :         int i;
     232          527688 :         for(i=0;i<content->nEntries;i++)
     233                 :         {
     234          527647 :             if (strcmp(fileInArchiveName, content->entries[i].fileName) == 0)
     235                 :             {
     236            1304 :                 if (archiveEntry)
     237            1304 :                     *archiveEntry = &content->entries[i];
     238            1304 :                 return TRUE;
     239                 :             }
     240                 :         }
     241                 :     }
     242              41 :     return FALSE;
     243                 : }
     244                 : 
     245                 : /************************************************************************/
     246                 : /*                           SplitFilename()                            */
     247                 : /************************************************************************/
     248                 : 
     249            5691 : char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
     250                 :                                                  CPLString &osFileInArchive,
     251                 :                                                  int bCheckMainFileExists)
     252                 : {
     253            5691 :     int i = 0;
     254                 : 
     255            5691 :     if (strcmp(pszFilename, GetPrefix()) == 0)
     256               0 :         return NULL;
     257                 : 
     258                 :     /* Allow natural chaining of VSI drivers without requiring double slash */
     259                 :     
     260            5691 :     CPLString osDoubleVsi(GetPrefix());
     261            5691 :     osDoubleVsi += "/vsi";
     262                 :     
     263            5691 :     if (strncmp(pszFilename, osDoubleVsi.c_str(), osDoubleVsi.size()) == 0)
     264            4060 :         pszFilename += strlen(GetPrefix());
     265                 :     else
     266            1631 :         pszFilename += strlen(GetPrefix()) + 1;
     267                 : 
     268            5691 :     while(pszFilename[i])
     269                 :     {
     270          107134 :         std::vector<CPLString> oExtensions = GetExtensions();
     271          107134 :         std::vector<CPLString>::const_iterator iter;
     272          107134 :         int nToSkip = 0;
     273                 : 
     274          618065 :         for( iter = oExtensions.begin(); iter != oExtensions.end(); ++iter )
     275                 :         {
     276          516605 :             const CPLString& osExtension = *iter;
     277          516605 :             if (EQUALN(pszFilename + i, osExtension.c_str(), strlen(osExtension.c_str())))
     278                 :             {
     279            5674 :                 nToSkip = strlen(osExtension.c_str());
     280            5674 :                 break;
     281                 :             }
     282                 :         }
     283                 : 
     284          107134 :         if (nToSkip != 0)
     285                 :         {
     286                 :             VSIStatBufL statBuf;
     287            5674 :             char* archiveFilename = CPLStrdup(pszFilename);
     288            5674 :             int bArchiveFileExists = FALSE;
     289                 : 
     290            5855 :             if (archiveFilename[i + nToSkip] == '/' ||
     291             181 :                 archiveFilename[i + nToSkip] == '\\')
     292                 :             {
     293            5493 :                 archiveFilename[i + nToSkip] = 0;
     294                 :             }
     295                 : 
     296            5674 :             if (!bCheckMainFileExists)
     297                 :             {
     298              71 :                 bArchiveFileExists = TRUE;
     299                 :             }
     300                 :             else
     301                 :             {
     302            5603 :                 CPLMutexHolder oHolder( &hMutex );
     303                 : 
     304            5603 :                 if (oFileList.find(archiveFilename) != oFileList.end() )
     305                 :                 {
     306            5457 :                     bArchiveFileExists = TRUE;
     307            5603 :                 }
     308                 :             }
     309                 : 
     310            5674 :             if (!bArchiveFileExists)
     311                 :             {
     312                 :                 VSIFilesystemHandler *poFSHandler = 
     313             146 :                     VSIFileManager::GetHandler( archiveFilename );
     314             146 :                 if (poFSHandler->Stat(archiveFilename, &statBuf,
     315             146 :                                       VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
     316                 :                     !VSI_ISDIR(statBuf.st_mode))
     317                 :                 {
     318             117 :                     bArchiveFileExists = TRUE;
     319                 :                 }
     320                 :             }
     321                 : 
     322            5674 :             if (bArchiveFileExists)
     323                 :             {
     324           11290 :                 if (pszFilename[i + nToSkip] == '/' ||
     325             160 :                     pszFilename[i + nToSkip] == '\\')
     326                 :                 {
     327            5485 :                     char* pszArchiveInFileName = CPLStrdup(pszFilename + i + nToSkip + 1);
     328                 : 
     329                 :                     /* Replace a/../b by b and foo/a/../b by foo/b */
     330               0 :                     while(TRUE)
     331                 :                     {
     332            5485 :                         char* pszPrevDir = strstr(pszArchiveInFileName, "/../");
     333            5485 :                         if (pszPrevDir == NULL || pszPrevDir == pszArchiveInFileName)
     334                 :                             break;
     335                 : 
     336               0 :                         char* pszPrevSlash = pszPrevDir - 1;
     337               0 :                         while(pszPrevSlash != pszArchiveInFileName &&
     338                 :                                 *pszPrevSlash != '/')
     339               0 :                             pszPrevSlash --;
     340               0 :                         if (pszPrevSlash == pszArchiveInFileName)
     341               0 :                             memmove(pszArchiveInFileName, pszPrevDir + nToSkip, strlen(pszPrevDir + nToSkip) + 1);
     342                 :                         else
     343               0 :                             memmove(pszPrevSlash + 1, pszPrevDir + nToSkip, strlen(pszPrevDir + nToSkip) + 1);
     344                 :                     }
     345                 : 
     346           10970 :                     osFileInArchive = pszArchiveInFileName;
     347            5485 :                     CPLFree(pszArchiveInFileName);
     348                 :                 }
     349                 :                 else
     350             160 :                     osFileInArchive = "";
     351                 : 
     352                 :                 /* Remove trailing slash */
     353            5645 :                 if (osFileInArchive.size())
     354                 :                 {
     355            5485 :                     char lastC = osFileInArchive[strlen(osFileInArchive) - 1];
     356            5485 :                     if (lastC == '\\' || lastC == '/')
     357               2 :                         osFileInArchive.resize(strlen(osFileInArchive) - 1);
     358                 :                 }
     359                 : 
     360            5645 :                 return archiveFilename;
     361                 :             }
     362              29 :             CPLFree(archiveFilename);
     363                 :         }
     364          101489 :         i++;
     365                 :     }
     366              46 :     return NULL;
     367                 : }
     368                 : 
     369                 : /************************************************************************/
     370                 : /*                           OpenArchiveFile()                          */
     371                 : /************************************************************************/
     372                 : 
     373             312 : VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archiveFilename, 
     374                 :                                                                const char* fileInArchiveName)
     375                 : {
     376             312 :     VSIArchiveReader* poReader = CreateReader(archiveFilename);
     377                 : 
     378             312 :     if (poReader == NULL)
     379                 :     {
     380               6 :         return NULL;
     381                 :     }
     382                 : 
     383             322 :     if (fileInArchiveName == NULL || strlen(fileInArchiveName) == 0)
     384                 :     {
     385              16 :         if (poReader->GotoFirstFile() == FALSE)
     386                 :         {
     387               0 :             delete(poReader);
     388               0 :             return NULL;
     389                 :         }
     390                 : 
     391                 :         /* Skip optionnal leading subdir */
     392              16 :         CPLString osFileName = poReader->GetFileName();
     393              16 :         const char* fileName = osFileName.c_str();
     394              16 :         if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
     395                 :         {
     396               3 :             if (poReader->GotoNextFile() == FALSE)
     397                 :             {
     398               0 :                 delete(poReader);
     399               0 :                 return NULL;
     400                 :             }
     401                 :         }
     402                 : 
     403              16 :         if (poReader->GotoNextFile())
     404                 :         {
     405               0 :             CPLString msg;
     406                 :             msg.Printf("Support only 1 file in archive file %s when no explicit in-archive filename is specified",
     407               0 :                        archiveFilename);
     408               0 :             const VSIArchiveContent* content = GetContentOfArchive(archiveFilename, poReader);
     409               0 :             if (content)
     410                 :             {
     411                 :                 int i;
     412               0 :                 msg += "\nYou could try one of the following :\n";
     413               0 :                 for(i=0;i<content->nEntries;i++)
     414                 :                 {
     415               0 :                     msg += CPLString().Printf("  %s/%s/%s\n", GetPrefix(), archiveFilename, content->entries[i].fileName);
     416                 :                 }
     417                 :             }
     418                 : 
     419               0 :             CPLError(CE_Failure, CPLE_NotSupported, "%s", msg.c_str());
     420                 : 
     421               0 :             delete(poReader);
     422               0 :             return NULL;
     423               0 :         }
     424                 :     }
     425                 :     else
     426                 :     {
     427             290 :         const VSIArchiveEntry* archiveEntry = NULL;
     428             290 :         if (FindFileInArchive(archiveFilename, fileInArchiveName, &archiveEntry) == FALSE ||
     429                 :             archiveEntry->bIsDir)
     430                 :         {
     431              27 :             delete(poReader);
     432              27 :             return NULL;
     433                 :         }
     434             263 :         if (!poReader->GotoFileOffset(archiveEntry->file_pos))
     435                 :         {
     436               0 :             delete poReader;
     437               0 :             return NULL;
     438                 :         }
     439                 :     }
     440             279 :     return poReader;
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                                 Stat()                               */
     445                 : /************************************************************************/
     446                 : 
     447            1068 : int VSIArchiveFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags )
     448                 : {
     449            1068 :     int ret = -1;
     450            1068 :     CPLString osFileInArchive;
     451                 : 
     452            1068 :     memset(pStatBuf, 0, sizeof(VSIStatBufL));
     453                 : 
     454            1068 :     char* archiveFilename = SplitFilename(pszFilename, osFileInArchive, TRUE);
     455            1068 :     if (archiveFilename == NULL)
     456               2 :         return -1;
     457                 : 
     458            1066 :     if (strlen(osFileInArchive) != 0)
     459                 :     {
     460                 :         if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Looking for %s %s\n",
     461                 :                                     archiveFilename, osFileInArchive.c_str());
     462                 : 
     463            1055 :         const VSIArchiveEntry* archiveEntry = NULL;
     464            1055 :         if (FindFileInArchive(archiveFilename, osFileInArchive, &archiveEntry))
     465                 :         {
     466                 :             /* Patching st_size with uncompressed file size */
     467            1041 :             pStatBuf->st_size = (long)archiveEntry->uncompressed_size;
     468            1041 :             pStatBuf->st_mtime = (time_t)archiveEntry->nModifiedTime;
     469            1041 :             if (archiveEntry->bIsDir)
     470            1002 :                 pStatBuf->st_mode = S_IFDIR;
     471                 :             else
     472              39 :                 pStatBuf->st_mode = S_IFREG;
     473            1041 :             ret = 0;
     474                 :         }
     475                 :     }
     476                 :     else
     477                 :     {
     478              11 :         VSIArchiveReader* poReader = CreateReader(archiveFilename);
     479              11 :         CPLFree(archiveFilename);
     480              11 :         archiveFilename = NULL;
     481                 : 
     482              11 :         if (poReader != NULL && poReader->GotoFirstFile())
     483                 :         {
     484                 :             /* Skip optionnal leading subdir */
     485              11 :             CPLString osFileName = poReader->GetFileName();
     486              11 :             const char* fileName = osFileName.c_str();
     487              11 :             if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
     488                 :             {
     489               1 :                 if (poReader->GotoNextFile() == FALSE)
     490                 :                 {
     491               0 :                     delete(poReader);
     492               0 :                     return -1;
     493                 :                 }
     494                 :             }
     495                 : 
     496              11 :             if (poReader->GotoNextFile())
     497                 :             {
     498                 :                 /* Several files in archive --> treat as dir */
     499               6 :                 pStatBuf->st_size = 0;
     500               6 :                 pStatBuf->st_mode = S_IFDIR;
     501                 :             }
     502                 :             else
     503                 :             {
     504                 :                 /* Patching st_size with uncompressed file size */
     505               5 :                 pStatBuf->st_size = (long)poReader->GetFileSize();
     506               5 :                 pStatBuf->st_mtime = (time_t)poReader->GetModifiedTime();
     507               5 :                 pStatBuf->st_mode = S_IFREG;
     508                 :             }
     509                 : 
     510              11 :             ret = 0;
     511                 :         }
     512                 : 
     513              11 :         delete(poReader);
     514                 :     }
     515                 : 
     516            1066 :     CPLFree(archiveFilename);
     517            1066 :     return ret;
     518                 : }
     519                 : 
     520                 : /************************************************************************/
     521                 : /*                              Unlink()                                */
     522                 : /************************************************************************/
     523                 : 
     524               0 : int VSIArchiveFilesystemHandler::Unlink( const char *pszFilename )
     525                 : {
     526               0 :     return -1;
     527                 : }
     528                 : 
     529                 : /************************************************************************/
     530                 : /*                             Rename()                                 */
     531                 : /************************************************************************/
     532                 : 
     533               0 : int VSIArchiveFilesystemHandler::Rename( const char *oldpath, const char *newpath )
     534                 : {
     535               0 :     return -1;
     536                 : }
     537                 : 
     538                 : /************************************************************************/
     539                 : /*                             Mkdir()                                  */
     540                 : /************************************************************************/
     541                 : 
     542               0 : int VSIArchiveFilesystemHandler::Mkdir( const char *pszDirname, long nMode )
     543                 : {
     544               0 :     return -1;
     545                 : }
     546                 : 
     547                 : /************************************************************************/
     548                 : /*                             Rmdir()                                  */
     549                 : /************************************************************************/
     550                 : 
     551               0 : int VSIArchiveFilesystemHandler::Rmdir( const char *pszDirname )
     552                 : {
     553               0 :     return -1;
     554                 : }
     555                 : 
     556                 : /************************************************************************/
     557                 : /*                             ReadDir()                                */
     558                 : /************************************************************************/
     559                 : 
     560            1570 : char** VSIArchiveFilesystemHandler::ReadDir( const char *pszDirname )
     561                 : {
     562            1570 :     CPLString osInArchiveSubDir;
     563            1570 :     char* archiveFilename = SplitFilename(pszDirname, osInArchiveSubDir, TRUE);
     564            1570 :     if (archiveFilename == NULL)
     565               2 :         return NULL;
     566            1568 :     int lenInArchiveSubDir = strlen(osInArchiveSubDir);
     567                 : 
     568            1568 :     char **papszDir = NULL;
     569                 :     
     570            1568 :     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
     571            1568 :     if (!content)
     572                 :     {
     573               0 :         CPLFree(archiveFilename);
     574               0 :         return NULL;
     575                 :     }
     576                 : 
     577                 :     if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Read dir %s", pszDirname);
     578                 :     int i;
     579         1015406 :     for(i=0;i<content->nEntries;i++)
     580                 :     {
     581         1013838 :         const char* fileName = content->entries[i].fileName;
     582                 :         /* Only list entries at the same level of inArchiveSubDir */
     583         2018942 :         if (lenInArchiveSubDir != 0 &&
     584                 :             strncmp(fileName, osInArchiveSubDir, lenInArchiveSubDir) == 0 &&
     585          504059 :             (fileName[lenInArchiveSubDir] == '/' || fileName[lenInArchiveSubDir] == '\\') &&
     586          501045 :             fileName[lenInArchiveSubDir + 1] != 0)
     587                 :         {
     588          501045 :             const char* slash = strchr(fileName + lenInArchiveSubDir + 1, '/');
     589          501045 :             if (slash == NULL)
     590            1371 :                 slash = strchr(fileName + lenInArchiveSubDir + 1, '\\');
     591          501045 :             if (slash == NULL || slash[1] == 0)
     592                 :             {
     593            1371 :                 char* tmpFileName = CPLStrdup(fileName);
     594            1371 :                 if (slash != NULL)
     595                 :                 {
     596               0 :                     tmpFileName[strlen(tmpFileName)-1] = 0;
     597                 :                 }
     598                 :                 if (ENABLE_DEBUG)
     599                 :                     CPLDebug("VSIArchive", "Add %s as in directory %s\n",
     600                 :                             tmpFileName + lenInArchiveSubDir + 1, pszDirname);
     601            1371 :                 papszDir = CSLAddString(papszDir, tmpFileName + lenInArchiveSubDir + 1);
     602            1371 :                 CPLFree(tmpFileName);
     603                 :             }
     604                 :         }
     605          512793 :         else if (lenInArchiveSubDir == 0 &&
     606                 :                  strchr(fileName, '/') == NULL && strchr(fileName, '\\') == NULL)
     607                 :         {
     608                 :             /* Only list toplevel files and directories */
     609                 :             if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Add %s as in directory %s\n", fileName, pszDirname);
     610             358 :             papszDir = CSLAddString(papszDir, fileName);
     611                 :         }
     612                 :     }
     613                 : 
     614            1568 :     CPLFree(archiveFilename);
     615            1568 :     return papszDir;
     616                 : }

Generated by: LCOV version 1.7