LCOV - code coverage report
Current view: directory - port - cpl_vsil_abstract_archive.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 258 208 80.6 %
Date: 2012-04-28 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            4794 : VSIArchiveEntryFileOffset::~VSIArchiveEntryFileOffset()
      45                 : {
      46            4794 : }
      47                 : 
      48                 : /************************************************************************/
      49                 : /*                        ~VSIArchiveReader()                           */
      50                 : /************************************************************************/
      51                 : 
      52             568 : VSIArchiveReader::~VSIArchiveReader()
      53                 : {
      54             568 : }
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                   VSIArchiveFilesystemHandler()                      */
      58                 : /************************************************************************/
      59                 : 
      60            2682 : VSIArchiveFilesystemHandler::VSIArchiveFilesystemHandler()
      61                 : {
      62            2682 :     hMutex = NULL;
      63            2682 : }
      64                 : 
      65                 : /************************************************************************/
      66                 : /*                   ~VSIArchiveFilesystemHandler()                     */
      67                 : /************************************************************************/
      68                 : 
      69            2594 : VSIArchiveFilesystemHandler::~VSIArchiveFilesystemHandler()
      70                 : 
      71                 : {
      72            2594 :     std::map<CPLString,VSIArchiveContent*>::const_iterator iter;
      73                 : 
      74            2658 :     for( iter = oFileList.begin(); iter != oFileList.end(); ++iter )
      75                 :     {
      76              64 :         VSIArchiveContent* content = iter->second;
      77                 :         int i;
      78            5516 :         for(i=0;i<content->nEntries;i++)
      79                 :         {
      80            5452 :             delete content->entries[i].file_pos;
      81            5452 :             CPLFree(content->entries[i].fileName);
      82                 :         }
      83              64 :         CPLFree(content->entries);
      84              64 :         delete content;
      85                 :     }
      86                 : 
      87            2594 :     if( hMutex != NULL )
      88              12 :         CPLDestroyMutex( hMutex );
      89            2594 :     hMutex = NULL;
      90            2594 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                       GetContentOfArchive()                          */
      94                 : /************************************************************************/
      95                 : 
      96            1628 : const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
      97                 :         (const char* archiveFilename, VSIArchiveReader* poReader)
      98                 : {
      99            1628 :     CPLMutexHolder oHolder( &hMutex );
     100                 : 
     101            1628 :     if (oFileList.find(archiveFilename) != oFileList.end() )
     102                 :     {
     103            1556 :         return oFileList[archiveFilename];
     104                 :     }
     105                 : 
     106              72 :     int bMustClose = (poReader == NULL);
     107              72 :     if (poReader == NULL)
     108                 :     {
     109              72 :         poReader = CreateReader(archiveFilename);
     110              72 :         if (!poReader)
     111               0 :             return NULL;
     112                 :     }
     113                 : 
     114              72 :     if (poReader->GotoFirstFile() == FALSE)
     115                 :     {
     116               0 :         if (bMustClose)
     117               0 :             delete(poReader);
     118               0 :         return NULL;
     119                 :     }
     120                 : 
     121              72 :     VSIArchiveContent* content = new VSIArchiveContent;
     122              72 :     content->nEntries = 0;
     123              72 :     content->entries = NULL;
     124              72 :     oFileList[archiveFilename] = content;
     125                 : 
     126              72 :     std::set<CPLString> oSet;
     127                 : 
     128            4770 :     do
     129                 :     {
     130            4770 :         CPLString osFileName = poReader->GetFileName();
     131            4770 :         const char* fileName = osFileName.c_str();
     132                 : 
     133                 :         /* Remove ./ pattern at the beginning of a filename */
     134            4770 :         if (fileName[0] == '.' && fileName[1] == '/')
     135                 :         {
     136               0 :             fileName += 2;
     137               0 :             if (fileName[0] == '\0')
     138               0 :                 continue;
     139                 :         }
     140                 : 
     141            4770 :         char* pszStrippedFileName = CPLStrdup(fileName);
     142                 :         char* pszIter;
     143          175520 :         for(pszIter = pszStrippedFileName;*pszIter;pszIter++)
     144                 :         {
     145          170750 :             if (*pszIter == '\\')
     146               0 :                 *pszIter = '/';
     147                 :         }
     148                 : 
     149                 :         int bIsDir = strlen(fileName) > 0 &&
     150            4770 :                       fileName[strlen(fileName)-1] == '/';
     151            4770 :         if (bIsDir)
     152                 :         {
     153                 :             /* Remove trailing slash */
     154              82 :             pszStrippedFileName[strlen(fileName)-1] = 0;
     155                 :         }
     156                 : 
     157            4770 :         if (oSet.find(pszStrippedFileName) == oSet.end())
     158                 :         {
     159            4770 :             oSet.insert(pszStrippedFileName);
     160                 : 
     161                 :             /* Add intermediate directory structure */
     162          175438 :             for(pszIter = pszStrippedFileName;*pszIter;pszIter++)
     163                 :             {
     164          170668 :                 if (*pszIter == '/')
     165                 :                 {
     166           12730 :                     char* pszStrippedFileName2 = CPLStrdup(pszStrippedFileName);
     167           12730 :                     pszStrippedFileName2[pszIter - pszStrippedFileName] = 0;
     168           12730 :                     if (oSet.find(pszStrippedFileName2) == oSet.end())
     169                 :                     {
     170             780 :                         oSet.insert(pszStrippedFileName2);
     171                 : 
     172                 :                         content->entries = (VSIArchiveEntry*)CPLRealloc(content->entries,
     173             780 :                                 sizeof(VSIArchiveEntry) * (content->nEntries + 1));
     174             780 :                         content->entries[content->nEntries].fileName = pszStrippedFileName2;
     175             780 :                         content->entries[content->nEntries].nModifiedTime = poReader->GetModifiedTime();
     176             780 :                         content->entries[content->nEntries].uncompressed_size = 0;
     177             780 :                         content->entries[content->nEntries].bIsDir = TRUE;
     178             780 :                         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             780 :                         content->nEntries++;
     184                 :                     }
     185                 :                     else
     186                 :                     {
     187           11950 :                         CPLFree(pszStrippedFileName2);
     188                 :                     }
     189                 :                 }
     190                 :             }
     191                 : 
     192                 :             content->entries = (VSIArchiveEntry*)CPLRealloc(content->entries,
     193            4770 :                                 sizeof(VSIArchiveEntry) * (content->nEntries + 1));
     194            4770 :             content->entries[content->nEntries].fileName = pszStrippedFileName;
     195            4770 :             content->entries[content->nEntries].nModifiedTime = poReader->GetModifiedTime();
     196            4770 :             content->entries[content->nEntries].uncompressed_size = poReader->GetFileSize();
     197            4770 :             content->entries[content->nEntries].bIsDir = bIsDir;
     198            4770 :             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            4770 :             content->nEntries++;
     204                 :         }
     205                 :         else
     206                 :         {
     207               0 :             CPLFree(pszStrippedFileName);
     208               0 :         }
     209            4770 :     } while(poReader->GotoNextFile());
     210                 : 
     211              72 :     if (bMustClose)
     212              72 :         delete(poReader);
     213                 : 
     214              72 :     return content;
     215                 : }
     216                 : 
     217                 : /************************************************************************/
     218                 : /*                        FindFileInArchive()                           */
     219                 : /************************************************************************/
     220                 : 
     221             532 : int VSIArchiveFilesystemHandler::FindFileInArchive(const char* archiveFilename,
     222                 :                                            const char* fileInArchiveName,
     223                 :                                            const VSIArchiveEntry** archiveEntry)
     224                 : {
     225             532 :     if (fileInArchiveName == NULL)
     226               0 :         return FALSE;
     227                 : 
     228             532 :     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
     229             532 :     if (content)
     230                 :     {
     231                 :         int i;
     232           51618 :         for(i=0;i<content->nEntries;i++)
     233                 :         {
     234           51552 :             if (strcmp(fileInArchiveName, content->entries[i].fileName) == 0)
     235                 :             {
     236             466 :                 if (archiveEntry)
     237             466 :                     *archiveEntry = &content->entries[i];
     238             466 :                 return TRUE;
     239                 :             }
     240                 :         }
     241                 :     }
     242              66 :     return FALSE;
     243                 : }
     244                 : 
     245                 : /************************************************************************/
     246                 : /*                           SplitFilename()                            */
     247                 : /************************************************************************/
     248                 : 
     249            3110 : char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
     250                 :                                                  CPLString &osFileInArchive,
     251                 :                                                  int bCheckMainFileExists)
     252                 : {
     253            3110 :     int i = 0;
     254                 : 
     255            3110 :     if (strcmp(pszFilename, GetPrefix()) == 0)
     256               0 :         return NULL;
     257                 : 
     258                 :     /* Allow natural chaining of VSI drivers without requiring double slash */
     259                 :     
     260            3110 :     CPLString osDoubleVsi(GetPrefix());
     261            3110 :     osDoubleVsi += "/vsi";
     262                 :     
     263            3110 :     if (strncmp(pszFilename, osDoubleVsi.c_str(), osDoubleVsi.size()) == 0)
     264             106 :         pszFilename += strlen(GetPrefix());
     265                 :     else
     266            3004 :         pszFilename += strlen(GetPrefix()) + 1;
     267                 : 
     268            3110 :     while(pszFilename[i])
     269                 :     {
     270           46102 :         std::vector<CPLString> oExtensions = GetExtensions();
     271           46102 :         std::vector<CPLString>::const_iterator iter;
     272           46102 :         int nToSkip = 0;
     273                 : 
     274          268492 :         for( iter = oExtensions.begin(); iter != oExtensions.end(); ++iter )
     275                 :         {
     276          225466 :             const CPLString& osExtension = *iter;
     277          225466 :             if (EQUALN(pszFilename + i, osExtension.c_str(), strlen(osExtension.c_str())))
     278                 :             {
     279            3076 :                 nToSkip = strlen(osExtension.c_str());
     280            3076 :                 break;
     281                 :             }
     282                 :         }
     283                 : 
     284           46102 :         if (nToSkip != 0)
     285                 :         {
     286                 :             VSIStatBufL statBuf;
     287            3076 :             char* archiveFilename = CPLStrdup(pszFilename);
     288            3076 :             int bArchiveFileExists = FALSE;
     289                 : 
     290            3348 :             if (archiveFilename[i + nToSkip] == '/' ||
     291             272 :                 archiveFilename[i + nToSkip] == '\\')
     292                 :             {
     293            2804 :                 archiveFilename[i + nToSkip] = 0;
     294                 :             }
     295                 : 
     296            3076 :             if (!bCheckMainFileExists)
     297                 :             {
     298             138 :                 bArchiveFileExists = TRUE;
     299                 :             }
     300                 :             else
     301                 :             {
     302            2938 :                 CPLMutexHolder oHolder( &hMutex );
     303                 : 
     304            2938 :                 if (oFileList.find(archiveFilename) != oFileList.end() )
     305                 :                 {
     306            2718 :                     bArchiveFileExists = TRUE;
     307            2938 :                 }
     308                 :             }
     309                 : 
     310            3076 :             if (!bArchiveFileExists)
     311                 :             {
     312                 :                 VSIFilesystemHandler *poFSHandler = 
     313             220 :                     VSIFileManager::GetHandler( archiveFilename );
     314             220 :                 if (poFSHandler->Stat(archiveFilename, &statBuf,
     315             220 :                                       VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
     316                 :                     !VSI_ISDIR(statBuf.st_mode))
     317                 :                 {
     318             162 :                     bArchiveFileExists = TRUE;
     319                 :                 }
     320                 :             }
     321                 : 
     322            3076 :             if (bArchiveFileExists)
     323                 :             {
     324            6036 :                 if (pszFilename[i + nToSkip] == '/' ||
     325             230 :                     pszFilename[i + nToSkip] == '\\')
     326                 :                 {
     327            2788 :                     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            2788 :                         char* pszPrevDir = strstr(pszArchiveInFileName, "/../");
     333            2788 :                         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            5576 :                     osFileInArchive = pszArchiveInFileName;
     347            2788 :                     CPLFree(pszArchiveInFileName);
     348                 :                 }
     349                 :                 else
     350             230 :                     osFileInArchive = "";
     351                 : 
     352                 :                 /* Remove trailing slash */
     353            3018 :                 if (osFileInArchive.size())
     354                 :                 {
     355            2788 :                     char lastC = osFileInArchive[strlen(osFileInArchive) - 1];
     356            2788 :                     if (lastC == '\\' || lastC == '/')
     357               4 :                         osFileInArchive.resize(strlen(osFileInArchive) - 1);
     358                 :                 }
     359                 : 
     360            3018 :                 return archiveFilename;
     361                 :             }
     362              58 :             CPLFree(archiveFilename);
     363                 :         }
     364           43084 :         i++;
     365                 :     }
     366              92 :     return NULL;
     367                 : }
     368                 : 
     369                 : /************************************************************************/
     370                 : /*                           OpenArchiveFile()                          */
     371                 : /************************************************************************/
     372                 : 
     373             476 : VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archiveFilename, 
     374                 :                                                                const char* fileInArchiveName)
     375                 : {
     376             476 :     VSIArchiveReader* poReader = CreateReader(archiveFilename);
     377                 : 
     378             476 :     if (poReader == NULL)
     379                 :     {
     380              12 :         return NULL;
     381                 :     }
     382                 : 
     383             488 :     if (fileInArchiveName == NULL || strlen(fileInArchiveName) == 0)
     384                 :     {
     385              24 :         if (poReader->GotoFirstFile() == FALSE)
     386                 :         {
     387               0 :             delete(poReader);
     388               0 :             return NULL;
     389                 :         }
     390                 : 
     391                 :         /* Skip optionnal leading subdir */
     392              24 :         CPLString osFileName = poReader->GetFileName();
     393              24 :         const char* fileName = osFileName.c_str();
     394              24 :         if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
     395                 :         {
     396               4 :             if (poReader->GotoNextFile() == FALSE)
     397                 :             {
     398               0 :                 delete(poReader);
     399               0 :                 return NULL;
     400                 :             }
     401                 :         }
     402                 : 
     403              24 :         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             440 :         const VSIArchiveEntry* archiveEntry = NULL;
     428             440 :         if (FindFileInArchive(archiveFilename, fileInArchiveName, &archiveEntry) == FALSE ||
     429                 :             archiveEntry->bIsDir)
     430                 :         {
     431              42 :             delete(poReader);
     432              42 :             return NULL;
     433                 :         }
     434             398 :         if (!poReader->GotoFileOffset(archiveEntry->file_pos))
     435                 :         {
     436               0 :             delete poReader;
     437               0 :             return NULL;
     438                 :         }
     439                 :     }
     440             422 :     return poReader;
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                                 Stat()                               */
     445                 : /************************************************************************/
     446                 : 
     447             116 : int VSIArchiveFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags )
     448                 : {
     449             116 :     int ret = -1;
     450             116 :     CPLString osFileInArchive;
     451                 : 
     452             116 :     memset(pStatBuf, 0, sizeof(VSIStatBufL));
     453                 : 
     454             116 :     char* archiveFilename = SplitFilename(pszFilename, osFileInArchive, TRUE);
     455             116 :     if (archiveFilename == NULL)
     456               4 :         return -1;
     457                 : 
     458             112 :     if (strlen(osFileInArchive) != 0)
     459                 :     {
     460                 :         if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Looking for %s %s\n",
     461                 :                                     archiveFilename, osFileInArchive.c_str());
     462                 : 
     463              92 :         const VSIArchiveEntry* archiveEntry = NULL;
     464              92 :         if (FindFileInArchive(archiveFilename, osFileInArchive, &archiveEntry))
     465                 :         {
     466                 :             /* Patching st_size with uncompressed file size */
     467              68 :             pStatBuf->st_size = (long)archiveEntry->uncompressed_size;
     468              68 :             pStatBuf->st_mtime = (time_t)archiveEntry->nModifiedTime;
     469              68 :             if (archiveEntry->bIsDir)
     470               0 :                 pStatBuf->st_mode = S_IFDIR;
     471                 :             else
     472              68 :                 pStatBuf->st_mode = S_IFREG;
     473              68 :             ret = 0;
     474                 :         }
     475                 :     }
     476                 :     else
     477                 :     {
     478              20 :         VSIArchiveReader* poReader = CreateReader(archiveFilename);
     479              20 :         CPLFree(archiveFilename);
     480              20 :         archiveFilename = NULL;
     481                 : 
     482              20 :         if (poReader != NULL && poReader->GotoFirstFile())
     483                 :         {
     484                 :             /* Skip optionnal leading subdir */
     485              20 :             CPLString osFileName = poReader->GetFileName();
     486              20 :             const char* fileName = osFileName.c_str();
     487              20 :             if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
     488                 :             {
     489               2 :                 if (poReader->GotoNextFile() == FALSE)
     490                 :                 {
     491               0 :                     delete(poReader);
     492               0 :                     return -1;
     493                 :                 }
     494                 :             }
     495                 : 
     496              20 :             if (poReader->GotoNextFile())
     497                 :             {
     498                 :                 /* Several files in archive --> treat as dir */
     499              10 :                 pStatBuf->st_size = 0;
     500              10 :                 pStatBuf->st_mode = S_IFDIR;
     501                 :             }
     502                 :             else
     503                 :             {
     504                 :                 /* Patching st_size with uncompressed file size */
     505              10 :                 pStatBuf->st_size = (long)poReader->GetFileSize();
     506              10 :                 pStatBuf->st_mtime = (time_t)poReader->GetModifiedTime();
     507              10 :                 pStatBuf->st_mode = S_IFREG;
     508                 :             }
     509                 : 
     510              20 :             ret = 0;
     511                 :         }
     512                 : 
     513              20 :         delete(poReader);
     514                 :     }
     515                 : 
     516             112 :     CPLFree(archiveFilename);
     517             112 :     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            1100 : char** VSIArchiveFilesystemHandler::ReadDir( const char *pszDirname )
     561                 : {
     562            1100 :     CPLString osInArchiveSubDir;
     563            1100 :     char* archiveFilename = SplitFilename(pszDirname, osInArchiveSubDir, TRUE);
     564            1100 :     if (archiveFilename == NULL)
     565               4 :         return NULL;
     566            1096 :     int lenInArchiveSubDir = strlen(osInArchiveSubDir);
     567                 : 
     568            1096 :     char **papszDir = NULL;
     569                 :     
     570            1096 :     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
     571            1096 :     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           24544 :     for(i=0;i<content->nEntries;i++)
     580                 :     {
     581           23448 :         const char* fileName = content->entries[i].fileName;
     582                 :         /* Only list entries at the same level of inArchiveSubDir */
     583           27636 :         if (lenInArchiveSubDir != 0 &&
     584                 :             strncmp(fileName, osInArchiveSubDir, lenInArchiveSubDir) == 0 &&
     585            3106 :             (fileName[lenInArchiveSubDir] == '/' || fileName[lenInArchiveSubDir] == '\\') &&
     586            1082 :             fileName[lenInArchiveSubDir + 1] != 0)
     587                 :         {
     588            1082 :             const char* slash = strchr(fileName + lenInArchiveSubDir + 1, '/');
     589            1082 :             if (slash == NULL)
     590             738 :                 slash = strchr(fileName + lenInArchiveSubDir + 1, '\\');
     591            1082 :             if (slash == NULL || slash[1] == 0)
     592                 :             {
     593             738 :                 char* tmpFileName = CPLStrdup(fileName);
     594             738 :                 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             738 :                 papszDir = CSLAddString(papszDir, tmpFileName + lenInArchiveSubDir + 1);
     602             738 :                 CPLFree(tmpFileName);
     603                 :             }
     604                 :         }
     605           22366 :         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             630 :             papszDir = CSLAddString(papszDir, fileName);
     611                 :         }
     612                 :     }
     613                 : 
     614            1096 :     CPLFree(archiveFilename);
     615            1096 :     return papszDir;
     616                 : }

Generated by: LCOV version 1.7