LCOV - code coverage report
Current view: directory - port - cpl_vsil.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 221 197 89.1 %
Date: 2012-12-26 Functions: 33 28 84.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: cpl_vsil.cpp 25340 2012-12-21 20:30:21Z rouault $
       3                 :  *
       4                 :  * Project:  VSI Virtual File System
       5                 :  * Purpose:  Implementation VSI*L File API and other file system access
       6                 :  *           methods going through file virtualization.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "cpl_vsi_virtual.h"
      32                 : #include "cpl_multiproc.h"
      33                 : #include "cpl_string.h"
      34                 : #include <string>
      35                 : 
      36                 : CPL_CVSID("$Id: cpl_vsil.cpp 25340 2012-12-21 20:30:21Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                             VSIReadDir()                             */
      40                 : /************************************************************************/
      41                 : 
      42                 : /**
      43                 :  * \brief Read names in a directory.
      44                 :  *
      45                 :  * This function abstracts access to directory contains.  It returns a
      46                 :  * list of strings containing the names of files, and directories in this
      47                 :  * directory.  The resulting string list becomes the responsibility of the
      48                 :  * application and should be freed with CSLDestroy() when no longer needed.
      49                 :  *
      50                 :  * Note that no error is issued via CPLError() if the directory path is
      51                 :  * invalid, though NULL is returned.
      52                 :  * 
      53                 :  * This function used to be known as CPLReadDir(), but the old name is now 
      54                 :  * deprecated. 
      55                 :  *
      56                 :  * @param pszPath the relative, or absolute path of a directory to read.  
      57                 :  * UTF-8 encoded.
      58                 :  * @return The list of entries in the directory, or NULL if the directory
      59                 :  * doesn't exist.  Filenames are returned in UTF-8 encoding.
      60                 :  */
      61                 : 
      62           13032 : char **VSIReadDir(const char *pszPath)
      63                 : {
      64                 :     VSIFilesystemHandler *poFSHandler = 
      65           13032 :         VSIFileManager::GetHandler( pszPath );
      66                 : 
      67           13032 :     return poFSHandler->ReadDir( pszPath );
      68                 : }
      69                 : 
      70                 : /************************************************************************/
      71                 : /*                             VSIReadRecursive()                       */
      72                 : /************************************************************************/
      73                 : 
      74                 : typedef struct
      75                 : {
      76                 :     char **papszFiles;
      77                 :     int nCount;
      78                 :     int i;
      79                 :     char* pszPath;
      80                 :     char* pszDisplayedPath;
      81               0 : }  VSIReadDirRecursiveTask;
      82                 : 
      83                 : /**
      84                 :  * \brief Read names in a directory recursively.
      85                 :  *
      86                 :  * This function abstracts access to directory contents and subdirectories.
      87                 :  * It returns a list of strings containing the names of files and directories 
      88                 :  * in this directory and all subdirectories.  The resulting string list becomes
      89                 :  * the responsibility of the application and should be freed with CSLDestroy()
      90                 :  *  when no longer needed.
      91                 :  *
      92                 :  * Note that no error is issued via CPLError() if the directory path is
      93                 :  * invalid, though NULL is returned.
      94                 :  * 
      95                 :  * @param pszPath the relative, or absolute path of a directory to read.  
      96                 :  * UTF-8 encoded.
      97                 :  *
      98                 :  * @return The list of entries in the directory and subdirectories 
      99                 :  * or NULL if the directory doesn't exist.  Filenames are returned in UTF-8 
     100                 :  * encoding.
     101                 :  * @since GDAL 1.10.0
     102                 :  *
     103                 :  */
     104                 : 
     105               2 : char **VSIReadDirRecursive( const char *pszPathIn )
     106                 : {
     107               2 :     CPLStringList oFiles = NULL;
     108               2 :     char **papszFiles = NULL;
     109                 :     VSIStatBufL psStatBuf;
     110               2 :     CPLString osTemp1, osTemp2;
     111               2 :     int i = 0;
     112               2 :     int nCount = -1;
     113                 : 
     114               2 :     std::vector<VSIReadDirRecursiveTask> aoStack;
     115               2 :     char* pszPath = CPLStrdup(pszPathIn);
     116               2 :     char* pszDisplayedPath = NULL;
     117                 : 
     118            2004 :     while(TRUE)
     119                 :     {
     120            2006 :         if( nCount < 0 )
     121                 :         {
     122                 :             // get listing
     123            1004 :             papszFiles = VSIReadDir( pszPath );
     124                 : 
     125                 :             // get files and directories inside listing
     126            1004 :             nCount = papszFiles ? CSLCount( papszFiles ) : 0;
     127            1004 :             i = 0;
     128                 :         }
     129                 : 
     130            2012 :         for ( ; i < nCount; i++ )
     131                 :         {
     132                 :             // build complete file name for stat
     133            1008 :             osTemp1.clear();
     134            1008 :             osTemp1.append( pszPath );
     135            1008 :             osTemp1.append( "/" );
     136            1008 :             osTemp1.append( papszFiles[i] );
     137                 : 
     138                 :             // if is file, add it
     139            1008 :             if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) != 0 )
     140               0 :                 continue;
     141                 : 
     142            1008 :             if( VSI_ISREG( psStatBuf.st_mode ) )
     143                 :             {
     144               6 :                 if( pszDisplayedPath )
     145                 :                 {
     146               4 :                     osTemp1.clear();
     147               4 :                     osTemp1.append( pszDisplayedPath );
     148               4 :                     osTemp1.append( "/" );
     149               4 :                     osTemp1.append( papszFiles[i] );
     150               4 :                     oFiles.AddString( osTemp1 );
     151                 :                 }
     152                 :                 else
     153               2 :                     oFiles.AddString( papszFiles[i] );
     154                 :             }
     155            1002 :             else if ( VSI_ISDIR( psStatBuf.st_mode ) )
     156                 :             {
     157                 :                 // add directory entry
     158            1002 :                 osTemp2.clear();
     159            1002 :                 if( pszDisplayedPath )
     160                 :                 {
     161            1000 :                     osTemp2.append( pszDisplayedPath );
     162            1000 :                     osTemp2.append( "/" );
     163                 :                 }
     164            1002 :                 osTemp2.append( papszFiles[i] );
     165            1002 :                 osTemp2.append( "/" );
     166            1002 :                 oFiles.AddString( osTemp2.c_str() );
     167                 : 
     168                 :                 VSIReadDirRecursiveTask sTask;
     169            1002 :                 sTask.papszFiles = papszFiles;
     170            1002 :                 sTask.nCount = nCount;
     171            1002 :                 sTask.i = i;
     172            1002 :                 sTask.pszPath = CPLStrdup(pszPath);
     173            1002 :                 sTask.pszDisplayedPath = pszDisplayedPath ? CPLStrdup(pszDisplayedPath) : NULL;
     174            1002 :                 aoStack.push_back(sTask);
     175                 : 
     176            1002 :                 CPLFree(pszPath);
     177            1002 :                 pszPath = CPLStrdup( osTemp1.c_str() );
     178                 : 
     179                 :                 char* pszDisplayedPathNew;
     180            1002 :                 if( pszDisplayedPath )
     181            1000 :                     pszDisplayedPathNew = CPLStrdup( CPLSPrintf("%s/%s", pszDisplayedPath, papszFiles[i]) );
     182                 :                 else
     183               2 :                     pszDisplayedPathNew = CPLStrdup( papszFiles[i] );
     184            1002 :                 CPLFree(pszDisplayedPath);
     185            1002 :                 pszDisplayedPath = pszDisplayedPathNew;
     186                 : 
     187            1002 :                 i = 0;
     188            1002 :                 papszFiles = NULL;
     189            1002 :                 nCount = -1;
     190                 : 
     191            1002 :                 break;
     192                 :             }
     193                 :         }
     194                 : 
     195            2006 :         if( nCount >= 0 )
     196                 :         {
     197            1004 :             CSLDestroy( papszFiles );
     198                 : 
     199            1004 :             if( aoStack.size() )
     200                 :             {
     201            1002 :                 int iLast = (int)aoStack.size() - 1;
     202            1002 :                 CPLFree(pszPath);
     203            1002 :                 CPLFree(pszDisplayedPath);
     204            1002 :                 nCount = aoStack[iLast].nCount;
     205            1002 :                 papszFiles = aoStack[iLast].papszFiles;
     206            1002 :                 i = aoStack[iLast].i + 1;
     207            1002 :                 pszPath = aoStack[iLast].pszPath;
     208            1002 :                 pszDisplayedPath = aoStack[iLast].pszDisplayedPath;
     209                 : 
     210            1002 :                 aoStack.resize(iLast);
     211                 :             }
     212                 :             else
     213                 :                 break;
     214                 :         }
     215                 :     }
     216                 : 
     217               2 :     CPLFree(pszPath);
     218               2 :     CPLFree(pszDisplayedPath);
     219                 : 
     220               2 :     return oFiles.StealList();
     221                 : }
     222                 : 
     223                 : 
     224                 : /************************************************************************/
     225                 : /*                             CPLReadDir()                             */
     226                 : /*                                                                      */
     227                 : /*      This is present only to provide ABI compatability with older    */
     228                 : /*      versions.                                                       */
     229                 : /************************************************************************/
     230                 : #undef CPLReadDir
     231                 : 
     232                 : CPL_C_START
     233                 : char CPL_DLL **CPLReadDir( const char *pszPath );
     234                 : CPL_C_END
     235                 : 
     236               0 : char **CPLReadDir( const char *pszPath )
     237                 : {
     238               0 :     return VSIReadDir(pszPath);
     239                 : }
     240                 : 
     241                 : /************************************************************************/
     242                 : /*                              VSIMkdir()                              */
     243                 : /************************************************************************/
     244                 : 
     245                 : /**
     246                 :  * \brief Create a directory. 
     247                 :  * 
     248                 :  * Create a new directory with the indicated mode.  The mode is ignored
     249                 :  * on some platforms.  A reasonable default mode value would be 0666.
     250                 :  * This method goes through the VSIFileHandler virtualization and may
     251                 :  * work on unusual filesystems such as in memory.
     252                 :  *
     253                 :  * Analog of the POSIX mkdir() function.
     254                 :  *
     255                 :  * @param pszPathname the path to the directory to create. UTF-8 encoded.
     256                 :  * @param mode the permissions mode.
     257                 :  *
     258                 :  * @return 0 on success or -1 on an error.
     259                 :  */
     260                 : 
     261             141 : int VSIMkdir( const char *pszPathname, long mode )
     262                 : 
     263                 : {
     264                 :     VSIFilesystemHandler *poFSHandler = 
     265             141 :         VSIFileManager::GetHandler( pszPathname );
     266                 : 
     267             141 :     return poFSHandler->Mkdir( pszPathname, mode );
     268                 : }
     269                 : 
     270                 : /************************************************************************/
     271                 : /*                             VSIUnlink()                              */
     272                 : /*************************a***********************************************/
     273                 : 
     274                 : /**
     275                 :  * \brief Delete a file.
     276                 :  * 
     277                 :  * Deletes a file object from the file system. 
     278                 :  * 
     279                 :  * This method goes through the VSIFileHandler virtualization and may
     280                 :  * work on unusual filesystems such as in memory.
     281                 :  *
     282                 :  * Analog of the POSIX unlink() function.
     283                 :  *
     284                 :  * @param pszFilename the path of the file to be deleted. UTF-8 encoded.
     285                 :  *
     286                 :  * @return 0 on success or -1 on an error.
     287                 :  */
     288                 : 
     289            9766 : int VSIUnlink( const char * pszFilename )
     290                 : 
     291                 : {
     292                 :     VSIFilesystemHandler *poFSHandler = 
     293            9766 :         VSIFileManager::GetHandler( pszFilename );
     294                 : 
     295            9766 :     return poFSHandler->Unlink( pszFilename );
     296                 : }
     297                 : 
     298                 : /************************************************************************/
     299                 : /*                             VSIRename()                              */
     300                 : /************************************************************************/
     301                 : 
     302                 : /**
     303                 :  * \brief Rename a file.
     304                 :  * 
     305                 :  * Renames a file object in the file system.  It should be possible
     306                 :  * to rename a file onto a new filesystem, but it is safest if this 
     307                 :  * function is only used to rename files that remain in the same directory.
     308                 :  * 
     309                 :  * This method goes through the VSIFileHandler virtualization and may
     310                 :  * work on unusual filesystems such as in memory.
     311                 :  *
     312                 :  * Analog of the POSIX rename() function.
     313                 :  *
     314                 :  * @param oldpath the name of the file to be renamed.  UTF-8 encoded.
     315                 :  * @param newpath the name the file should be given.  UTF-8 encoded.
     316                 :  *
     317                 :  * @return 0 on success or -1 on an error.
     318                 :  */
     319                 : 
     320              14 : int VSIRename( const char * oldpath, const char * newpath )
     321                 : 
     322                 : {
     323                 :     VSIFilesystemHandler *poFSHandler = 
     324              14 :         VSIFileManager::GetHandler( oldpath );
     325                 : 
     326              14 :     return poFSHandler->Rename( oldpath, newpath );
     327                 : }
     328                 : 
     329                 : /************************************************************************/
     330                 : /*                              VSIRmdir()                              */
     331                 : /************************************************************************/
     332                 : 
     333                 : /**
     334                 :  * \brief Delete a directory.
     335                 :  * 
     336                 :  * Deletes a directory object from the file system.  On some systems
     337                 :  * the directory must be empty before it can be deleted.
     338                 :  * 
     339                 :  * This method goes through the VSIFileHandler virtualization and may
     340                 :  * work on unusual filesystems such as in memory.
     341                 :  *
     342                 :  * Analog of the POSIX rmdir() function.
     343                 :  *
     344                 :  * @param pszDirname the path of the directory to be deleted.  UTF-8 encoded.
     345                 :  *
     346                 :  * @return 0 on success or -1 on an error.
     347                 :  */
     348                 : 
     349             450 : int VSIRmdir( const char * pszDirname )
     350                 : 
     351                 : {
     352                 :     VSIFilesystemHandler *poFSHandler = 
     353             450 :         VSIFileManager::GetHandler( pszDirname );
     354                 : 
     355             450 :     return poFSHandler->Rmdir( pszDirname );
     356                 : }
     357                 : 
     358                 : /************************************************************************/
     359                 : /*                              VSIStatL()                              */
     360                 : /************************************************************************/
     361                 : 
     362                 : /**
     363                 :  * \brief Get filesystem object info.
     364                 :  * 
     365                 :  * Fetches status information about a filesystem object (file, directory, etc).
     366                 :  * The returned information is placed in the VSIStatBufL structure.   For
     367                 :  * portability only the st_size (size in bytes), and st_mode (file type). 
     368                 :  * This method is similar to VSIStat(), but will work on large files on 
     369                 :  * systems where this requires special calls. 
     370                 :  * 
     371                 :  * This method goes through the VSIFileHandler virtualization and may
     372                 :  * work on unusual filesystems such as in memory.
     373                 :  *
     374                 :  * Analog of the POSIX stat() function.
     375                 :  *
     376                 :  * @param pszFilename the path of the filesystem object to be queried.  UTF-8 encoded.
     377                 :  * @param psStatBuf the structure to load with information. 
     378                 :  *
     379                 :  * @return 0 on success or -1 on an error.
     380                 :  */
     381                 : 
     382           12268 : int VSIStatL( const char * pszFilename, VSIStatBufL *psStatBuf )
     383                 : 
     384                 : {
     385           12268 :     return VSIStatExL(pszFilename, psStatBuf, 0);
     386                 : }
     387                 : 
     388                 : 
     389                 : /************************************************************************/
     390                 : /*                            VSIStatExL()                              */
     391                 : /************************************************************************/
     392                 : 
     393                 : /**
     394                 :  * \brief Get filesystem object info.
     395                 :  *
     396                 :  * Fetches status information about a filesystem object (file, directory, etc).
     397                 :  * The returned information is placed in the VSIStatBufL structure.   For
     398                 :  * portability only the st_size (size in bytes), and st_mode (file type).
     399                 :  * This method is similar to VSIStat(), but will work on large files on
     400                 :  * systems where this requires special calls.
     401                 :  *
     402                 :  * This method goes through the VSIFileHandler virtualization and may
     403                 :  * work on unusual filesystems such as in memory.
     404                 :  *
     405                 :  * Analog of the POSIX stat() function, with an extra parameter to specify
     406                 :  * which information is needed, which offers a potential for speed optimizations
     407                 :  * on specialized and potentially slow virtual filesystem objects (/vsigzip/, /vsicurl/)
     408                 :  *
     409                 :  * @param pszFilename the path of the filesystem object to be queried.  UTF-8 encoded.
     410                 :  * @param psStatBuf the structure to load with information.
     411                 :  * @param nFlags 0 to get all information, or VSI_STAT_EXISTS_FLAG, VSI_STAT_NATURE_FLAG or
     412                 :  *                  VSI_STAT_SIZE_FLAG, or a combination of those to get partial info.
     413                 :  *
     414                 :  * @return 0 on success or -1 on an error.
     415                 :  *
     416                 :  * @since GDAL 1.8.0
     417                 :  */
     418                 : 
     419           64637 : int VSIStatExL( const char * pszFilename, VSIStatBufL *psStatBuf, int nFlags )
     420                 : 
     421                 : {
     422                 :     char    szAltPath[4];
     423                 :     /* enable to work on "C:" as if it were "C:\" */
     424           64637 :     if( strlen(pszFilename) == 2 && pszFilename[1] == ':' )
     425                 :     {
     426               0 :         szAltPath[0] = pszFilename[0];
     427               0 :         szAltPath[1] = pszFilename[1];
     428               0 :         szAltPath[2] = '\\';
     429               0 :         szAltPath[3] = '\0';
     430                 : 
     431               0 :         pszFilename = szAltPath;
     432                 :     }
     433                 : 
     434                 :     VSIFilesystemHandler *poFSHandler =
     435           64637 :         VSIFileManager::GetHandler( pszFilename );
     436                 : 
     437           64637 :     if (nFlags == 0)
     438           12268 :         nFlags = VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG | VSI_STAT_SIZE_FLAG;
     439                 : 
     440           64637 :     return poFSHandler->Stat( pszFilename, psStatBuf, nFlags );
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                       VSIIsCaseSensitiveFS()                         */
     445                 : /************************************************************************/
     446                 : 
     447                 : /**
     448                 :  * \brief Returns if the filenames of the filesystem are case sensitive.
     449                 :  *
     450                 :  * This method retrieves to which filesystem belongs the passed filename
     451                 :  * and return TRUE if the filenames of that filesystem are case sensitive.
     452                 :  *
     453                 :  * Currently, this will return FALSE only for Windows real filenames. Other
     454                 :  * VSI virtual filesystems are case sensitive.
     455                 :  *
     456                 :  * This methods avoid ugly #ifndef WIN32 / #endif code, that is wrong when
     457                 :  * dealing with virtual filenames.
     458                 :  *
     459                 :  * @param pszFilename the path of the filesystem object to be tested.  UTF-8 encoded.
     460                 :  *
     461                 :  * @return TRUE if the filenames of the filesystem are case sensitive.
     462                 :  *
     463                 :  * @since GDAL 1.8.0
     464                 :  */
     465           11894 : int VSIIsCaseSensitiveFS( const char * pszFilename )
     466                 : {
     467                 :     VSIFilesystemHandler *poFSHandler =
     468           11894 :         VSIFileManager::GetHandler( pszFilename );
     469                 :         
     470           11894 :     return poFSHandler->IsCaseSensitive( pszFilename );
     471                 : }
     472                 : 
     473                 : /************************************************************************/
     474                 : /*                             VSIFOpenL()                              */
     475                 : /************************************************************************/
     476                 : 
     477                 : /**
     478                 :  * \brief Open file.
     479                 :  *
     480                 :  * This function opens a file with the desired access.  Large files (larger
     481                 :  * than 2GB) should be supported.  Binary access is always implied and
     482                 :  * the "b" does not need to be included in the pszAccess string.
     483                 :  *
     484                 :  * Note that the "VSILFILE *" returned since GDAL 1.8.0 by this function is 
     485                 :  * *NOT* a standard C library FILE *, and cannot be used with any functions 
     486                 :  * other than the "VSI*L" family of functions.  They aren't "real" FILE objects.
     487                 :  *
     488                 :  * On windows it is possible to define the configuration option 
     489                 :  * GDAL_FILE_IS_UTF8 to have pszFilename treated as being in the local
     490                 :  * encoding instead of UTF-8, retoring the pre-1.8.0 behavior of VSIFOpenL().
     491                 :  *
     492                 :  * This method goes through the VSIFileHandler virtualization and may
     493                 :  * work on unusual filesystems such as in memory.
     494                 :  *
     495                 :  * Analog of the POSIX fopen() function.
     496                 :  *
     497                 :  * @param pszFilename the file to open.  UTF-8 encoded.
     498                 :  * @param pszAccess access requested (ie. "r", "r+", "w".  
     499                 :  *
     500                 :  * @return NULL on failure, or the file handle.
     501                 :  */
     502                 : 
     503          100368 : VSILFILE *VSIFOpenL( const char * pszFilename, const char * pszAccess )
     504                 : 
     505                 : {
     506                 :     VSIFilesystemHandler *poFSHandler = 
     507          100368 :         VSIFileManager::GetHandler( pszFilename );
     508                 :         
     509          100367 :     VSILFILE* fp = (VSILFILE *) poFSHandler->Open( pszFilename, pszAccess );
     510                 : 
     511                 :     VSIDebug3( "VSIFOpenL(%s,%s) = %p", pszFilename, pszAccess, fp );
     512                 :         
     513          100368 :     return fp;
     514                 : }
     515                 : 
     516                 : /************************************************************************/
     517                 : /*                             VSIFCloseL()                             */
     518                 : /************************************************************************/
     519                 : 
     520                 : /**
     521                 :  * \brief Close file.
     522                 :  *
     523                 :  * This function closes the indicated file.
     524                 :  *
     525                 :  * This method goes through the VSIFileHandler virtualization and may
     526                 :  * work on unusual filesystems such as in memory.
     527                 :  *
     528                 :  * Analog of the POSIX fclose() function.
     529                 :  *
     530                 :  * @param fp file handle opened with VSIFOpenL().
     531                 :  *
     532                 :  * @return 0 on success or -1 on failure.
     533                 :  */
     534                 : 
     535           69980 : int VSIFCloseL( VSILFILE * fp )
     536                 : 
     537                 : {
     538           69980 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     539                 :     
     540                 :     VSIDebug1( "VSICloseL(%p)", fp );
     541                 :     
     542           69980 :     int nResult = poFileHandle->Close();
     543                 :     
     544           69980 :     delete poFileHandle;
     545                 : 
     546           69980 :     return nResult;
     547                 : }
     548                 : 
     549                 : /************************************************************************/
     550                 : /*                             VSIFSeekL()                              */
     551                 : /************************************************************************/
     552                 : 
     553                 : /**
     554                 :  * \brief Seek to requested offset.
     555                 :  *
     556                 :  * Seek to the desired offset (nOffset) in the indicated file. 
     557                 :  *
     558                 :  * This method goes through the VSIFileHandler virtualization and may
     559                 :  * work on unusual filesystems such as in memory.
     560                 :  *
     561                 :  * Analog of the POSIX fseek() call.
     562                 :  *
     563                 :  * @param fp file handle opened with VSIFOpenL(). 
     564                 :  * @param nOffset offset in bytes.
     565                 :  * @param nWhence one of SEEK_SET, SEEK_CUR or SEEK_END.
     566                 :  *
     567                 :  * @return 0 on success or -1 one failure.
     568                 :  */
     569                 : 
     570         3691452 : int VSIFSeekL( VSILFILE * fp, vsi_l_offset nOffset, int nWhence )
     571                 : 
     572                 : {
     573         3691452 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     574                 :     
     575         3691452 :     return poFileHandle->Seek( nOffset, nWhence );
     576                 : }
     577                 : 
     578                 : /************************************************************************/
     579                 : /*                             VSIFTellL()                              */
     580                 : /************************************************************************/
     581                 : 
     582                 : /**
     583                 :  * \brief Tell current file offset.
     584                 :  *
     585                 :  * Returns the current file read/write offset in bytes from the beginning of
     586                 :  * the file. 
     587                 :  *
     588                 :  * This method goes through the VSIFileHandler virtualization and may
     589                 :  * work on unusual filesystems such as in memory.
     590                 :  *
     591                 :  * Analog of the POSIX ftell() call.
     592                 :  *
     593                 :  * @param fp file handle opened with VSIFOpenL(). 
     594                 :  *
     595                 :  * @return file offset in bytes.
     596                 :  */
     597                 : 
     598         1012464 : vsi_l_offset VSIFTellL( VSILFILE * fp )
     599                 : 
     600                 : {
     601         1012464 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     602                 :     
     603         1012464 :     return poFileHandle->Tell();
     604                 : }
     605                 : 
     606                 : /************************************************************************/
     607                 : /*                             VSIRewindL()                             */
     608                 : /************************************************************************/
     609                 : 
     610             631 : void VSIRewindL( VSILFILE * fp )
     611                 : 
     612                 : {
     613             631 :     VSIFSeekL( fp, 0, SEEK_SET );
     614             631 : }
     615                 : 
     616                 : /************************************************************************/
     617                 : /*                             VSIFFlushL()                             */
     618                 : /************************************************************************/
     619                 : 
     620                 : /**
     621                 :  * \brief Flush pending writes to disk.
     622                 :  *
     623                 :  * For files in write or update mode and on filesystem types where it is
     624                 :  * applicable, all pending output on the file is flushed to the physical disk.
     625                 :  *
     626                 :  * This method goes through the VSIFileHandler virtualization and may
     627                 :  * work on unusual filesystems such as in memory.
     628                 :  *
     629                 :  * Analog of the POSIX fflush() call.
     630                 :  *
     631                 :  * @param fp file handle opened with VSIFOpenL(). 
     632                 :  *
     633                 :  * @return 0 on success or -1 on error.
     634                 :  */
     635                 : 
     636            4339 : int VSIFFlushL( VSILFILE * fp )
     637                 : 
     638                 : {
     639            4339 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     640                 :     
     641            4339 :     return poFileHandle->Flush();
     642                 : }
     643                 : 
     644                 : /************************************************************************/
     645                 : /*                             VSIFReadL()                              */
     646                 : /************************************************************************/
     647                 : 
     648                 : /**
     649                 :  * \brief Read bytes from file.
     650                 :  *
     651                 :  * Reads nCount objects of nSize bytes from the indicated file at the
     652                 :  * current offset into the indicated buffer.
     653                 :  *
     654                 :  * This method goes through the VSIFileHandler virtualization and may
     655                 :  * work on unusual filesystems such as in memory.
     656                 :  *
     657                 :  * Analog of the POSIX fread() call.
     658                 :  *
     659                 :  * @param pBuffer the buffer into which the data should be read (at least
     660                 :  * nCount * nSize bytes in size. 
     661                 :  * @param nSize size of objects to read in bytes.
     662                 :  * @param nCount number of objects to read.
     663                 :  * @param fp file handle opened with VSIFOpenL(). 
     664                 :  *
     665                 :  * @return number of objects successfully read. 
     666                 :  */
     667                 : 
     668         7340099 : size_t VSIFReadL( void * pBuffer, size_t nSize, size_t nCount, VSILFILE * fp )
     669                 : 
     670                 : {
     671         7340099 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     672                 :     
     673         7340099 :     return poFileHandle->Read( pBuffer, nSize, nCount );
     674                 : }
     675                 : 
     676                 : 
     677                 : /************************************************************************/
     678                 : /*                       VSIFReadMultiRangeL()                          */
     679                 : /************************************************************************/
     680                 : 
     681                 : /**
     682                 :  * \brief Read several ranges of bytes from file.
     683                 :  *
     684                 :  * Reads nRanges objects of panSizes[i] bytes from the indicated file at the
     685                 :  * offset panOffsets[i] into the buffer ppData[i].
     686                 :  *
     687                 :  * Ranges must be sorted in ascending start offset, and must not overlap each
     688                 :  * other.
     689                 :  *
     690                 :  * This method goes through the VSIFileHandler virtualization and may
     691                 :  * work on unusual filesystems such as in memory or /vsicurl/.
     692                 :  *
     693                 :  * @param nRanges number of ranges to read.
     694                 :  * @param ppData array of nRanges buffer into which the data should be read
     695                 :  *               (ppData[i] must be at list panSizes[i] bytes).
     696                 :  * @param panOffsets array of nRanges offsets at which the data should be read.
     697                 :  * @param panSizes array of nRanges sizes of objects to read (in bytes).
     698                 :  * @param fp file handle opened with VSIFOpenL().
     699                 :  *
     700                 :  * @return 0 in case of success, -1 otherwise.
     701                 :  * @since GDAL 1.9.0
     702                 :  */
     703                 : 
     704               1 : int VSIFReadMultiRangeL( int nRanges, void ** ppData,
     705                 :                          const vsi_l_offset* panOffsets,
     706                 :                          const size_t* panSizes, VSILFILE * fp )
     707                 : {
     708               1 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     709                 : 
     710               1 :     return poFileHandle->ReadMultiRange( nRanges, ppData, panOffsets, panSizes );
     711                 : }
     712                 : 
     713                 : /************************************************************************/
     714                 : /*                             VSIFWriteL()                             */
     715                 : /************************************************************************/
     716                 : 
     717                 : /**
     718                 :  * \brief Write bytes to file.
     719                 :  *
     720                 :  * Writess nCount objects of nSize bytes to the indicated file at the
     721                 :  * current offset into the indicated buffer.
     722                 :  *
     723                 :  * This method goes through the VSIFileHandler virtualization and may
     724                 :  * work on unusual filesystems such as in memory.
     725                 :  *
     726                 :  * Analog of the POSIX fwrite() call.
     727                 :  *
     728                 :  * @param pBuffer the buffer from which the data should be written (at least
     729                 :  * nCount * nSize bytes in size. 
     730                 :  * @param nSize size of objects to read in bytes.
     731                 :  * @param nCount number of objects to read.
     732                 :  * @param fp file handle opened with VSIFOpenL(). 
     733                 :  *
     734                 :  * @return number of objects successfully written.
     735                 :  */
     736                 : 
     737         2487487 : size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp )
     738                 : 
     739                 : {
     740         2487487 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     741                 :     
     742         2487487 :     return poFileHandle->Write( pBuffer, nSize, nCount );
     743                 : }
     744                 : 
     745                 : /************************************************************************/
     746                 : /*                              VSIFEofL()                              */
     747                 : /************************************************************************/
     748                 : 
     749                 : /**
     750                 :  * \brief Test for end of file.
     751                 :  *
     752                 :  * Returns TRUE (non-zero) if an end-of-file condition occured during the
     753                 :  * previous read operation. The end-of-file flag is cleared by a successfull
     754                 :  * VSIFSeekL() call.
     755                 :  *
     756                 :  * This method goes through the VSIFileHandler virtualization and may
     757                 :  * work on unusual filesystems such as in memory.
     758                 :  *
     759                 :  * Analog of the POSIX feof() call.
     760                 :  *
     761                 :  * @param fp file handle opened with VSIFOpenL(). 
     762                 :  *
     763                 :  * @return TRUE if at EOF else FALSE.
     764                 :  */
     765                 : 
     766          104855 : int VSIFEofL( VSILFILE * fp )
     767                 : 
     768                 : {
     769          104855 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     770                 :     
     771          104855 :     return poFileHandle->Eof();
     772                 : }
     773                 : 
     774                 : /************************************************************************/
     775                 : /*                            VSIFTruncateL()                           */
     776                 : /************************************************************************/
     777                 : 
     778                 : /**
     779                 :  * \brief Truncate/expand the file to the specified size
     780                 : 
     781                 :  * This method goes through the VSIFileHandler virtualization and may
     782                 :  * work on unusual filesystems such as in memory.
     783                 :  *
     784                 :  * Analog of the POSIX ftruncate() call.
     785                 :  *
     786                 :  * @param fp file handle opened with VSIFOpenL().
     787                 :  * @param nNewSize new size in bytes.
     788                 :  *
     789                 :  * @return 0 on success
     790                 :  * @since GDAL 1.9.0
     791                 :  */
     792                 : 
     793             102 : int VSIFTruncateL( VSILFILE * fp, vsi_l_offset nNewSize )
     794                 : 
     795                 : {
     796             102 :     VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
     797                 : 
     798             102 :     return poFileHandle->Truncate(nNewSize);
     799                 : }
     800                 : 
     801                 : /************************************************************************/
     802                 : /*                            VSIFPrintfL()                             */
     803                 : /************************************************************************/
     804                 : 
     805                 : /**
     806                 :  * \brief Formatted write to file.
     807                 :  *
     808                 :  * Provides fprintf() style formatted output to a VSI*L file.  This formats
     809                 :  * an internal buffer which is written using VSIFWriteL(). 
     810                 :  *
     811                 :  * Analog of the POSIX fprintf() call.
     812                 :  *
     813                 :  * @param fp file handle opened with VSIFOpenL(). 
     814                 :  * @param pszFormat the printf style format string. 
     815                 :  * 
     816                 :  * @return the number of bytes written or -1 on an error.
     817                 :  */
     818                 : 
     819           27086 : int VSIFPrintfL( VSILFILE *fp, const char *pszFormat, ... )
     820                 : 
     821                 : {
     822                 :     va_list args;
     823           27086 :     CPLString osResult;
     824                 : 
     825           27086 :     va_start( args, pszFormat );
     826           27086 :     osResult.vPrintf( pszFormat, args );
     827           27086 :     va_end( args );
     828                 : 
     829           27086 :     return VSIFWriteL( osResult.c_str(), 1, osResult.length(), fp );
     830                 : }
     831                 : 
     832                 : /************************************************************************/
     833                 : /*                              VSIFPutcL()                              */
     834                 : /************************************************************************/
     835                 : 
     836             181 : int VSIFPutcL( int nChar, VSILFILE * fp )
     837                 : 
     838                 : {
     839             181 :     unsigned char cChar = (unsigned char)nChar;
     840             181 :     return VSIFWriteL(&cChar, 1, 1, fp);
     841                 : }
     842                 : 
     843                 : /************************************************************************/
     844                 : /* ==================================================================== */
     845                 : /*                           VSIFileManager()                           */
     846                 : /* ==================================================================== */
     847                 : /************************************************************************/
     848                 : 
     849                 : /*
     850                 : ** Notes on Multithreading:
     851                 : **
     852                 : ** The VSIFileManager maintains a list of file type handlers (mem, large
     853                 : ** file, etc).  It should be thread safe as long as all the handlers are
     854                 : ** instantiated before multiple threads begin to operate. 
     855                 : **/
     856                 : 
     857                 : /************************************************************************/
     858                 : /*                           VSIFileManager()                           */
     859                 : /************************************************************************/
     860                 : 
     861             712 : VSIFileManager::VSIFileManager()
     862                 : 
     863                 : {
     864             712 :     poDefaultHandler = NULL;
     865             712 : }
     866                 : 
     867                 : /************************************************************************/
     868                 : /*                          ~VSIFileManager()                           */
     869                 : /************************************************************************/
     870                 : 
     871             687 : VSIFileManager::~VSIFileManager()
     872                 : {
     873             687 :     std::map<std::string,VSIFilesystemHandler*>::const_iterator iter;
     874                 : 
     875            8244 :     for( iter = oHandlers.begin();
     876                 :          iter != oHandlers.end();
     877                 :          ++iter )
     878                 :     {
     879            7557 :         delete iter->second;
     880                 :     }
     881                 : 
     882             687 :     delete poDefaultHandler;
     883             687 : }
     884                 : 
     885                 : 
     886                 : /************************************************************************/
     887                 : /*                                Get()                                 */
     888                 : /************************************************************************/
     889                 : 
     890                 : static VSIFileManager *poManager = NULL;
     891                 : 
     892          210773 : VSIFileManager *VSIFileManager::Get()
     893                 : 
     894                 : {
     895                 :     static void* hMutex = NULL;
     896                 :     static volatile int nConstructerPID = 0;
     897          210773 :     if( poManager != NULL )
     898                 :     {
     899          210061 :         if( nConstructerPID != 0 )
     900                 :         {
     901            8544 :             int nCurrentPID = (int)CPLGetPID();
     902            8544 :             if( nConstructerPID != nCurrentPID )
     903                 :             {
     904                 :                 //printf("Thread %d: Waiting for VSIFileManager to be finished by other thread.\n", nCurrentPID);
     905                 :                 {
     906               0 :                     CPLMutexHolder oHolder( &hMutex );
     907                 :                 }
     908                 :                 //printf("Thread %d: End of wait for VSIFileManager construction to be finished\n", nCurrentPID);
     909               0 :                 CPLAssert(nConstructerPID == 0);
     910                 :             }
     911                 :         }
     912          210061 :         return poManager;
     913                 :     }
     914                 : 
     915             712 :     CPLMutexHolder oHolder2( &hMutex );
     916             712 :     if( poManager == NULL )
     917                 :     {
     918             712 :         nConstructerPID = (int)CPLGetPID();
     919                 :         //printf("Thread %d: VSIFileManager in construction\n", nConstructerPID);
     920             712 :         poManager = new VSIFileManager;
     921             712 :         VSIInstallLargeFileHandler();
     922             712 :         VSIInstallSubFileHandler();
     923             712 :         VSIInstallMemFileHandler();
     924                 : #ifdef HAVE_LIBZ
     925             712 :         VSIInstallGZipFileHandler();
     926             712 :         VSIInstallZipFileHandler();
     927                 : #endif
     928                 : #ifdef HAVE_CURL
     929             712 :         VSIInstallCurlFileHandler();
     930             712 :         VSIInstallCurlStreamingFileHandler();
     931                 : #endif
     932             712 :         VSIInstallStdinHandler();
     933             712 :         VSIInstallStdoutHandler();
     934             712 :         VSIInstallSparseFileHandler();
     935             712 :         VSIInstallTarFileHandler();
     936                 :         //printf("Thread %d: VSIFileManager construction finished\n", nConstructerPID);
     937             712 :         nConstructerPID = 0;
     938                 :     }
     939                 :     
     940             712 :     return poManager;
     941                 : }
     942                 : 
     943                 : /************************************************************************/
     944                 : /*                             GetHandler()                             */
     945                 : /************************************************************************/
     946                 : 
     947          202229 : VSIFilesystemHandler *VSIFileManager::GetHandler( const char *pszPath )
     948                 : 
     949                 : {
     950          202229 :     VSIFileManager *poThis = Get();
     951          202229 :     std::map<std::string,VSIFilesystemHandler*>::const_iterator iter;
     952          202229 :     int nPathLen = strlen(pszPath);
     953                 : 
     954         2059918 :     for( iter = poThis->oHandlers.begin();
     955                 :          iter != poThis->oHandlers.end();
     956                 :          ++iter )
     957                 :     {
     958         1906034 :         const char* pszIterKey = iter->first.c_str();
     959         1906036 :         int nIterKeyLen = iter->first.size();
     960         1906025 :         if( strncmp(pszPath,pszIterKey,nIterKeyLen) == 0 )
     961           47651 :             return iter->second;
     962                 : 
     963                 :         /* "/vsimem\foo" should be handled as "/vsimem/foo" */
     964         5052227 :         if (nIterKeyLen && nPathLen > nIterKeyLen &&
     965         1596927 :             pszIterKey[nIterKeyLen-1] == '/' &&
     966         1596926 :             pszPath[nIterKeyLen-1] == '\\' &&
     967                 :             strncmp(pszPath,pszIterKey,nIterKeyLen-1) == 0 )
     968               4 :             return iter->second;
     969                 : 
     970                 :         /* /vsimem should be treated as a match for /vsimem/ */
     971         1858370 :         if( nPathLen == nIterKeyLen - 1
     972                 :             && strncmp(pszPath,pszIterKey,nIterKeyLen-1) == 0 )
     973             681 :             return iter->second;
     974                 :     }
     975                 :     
     976          153892 :     return poThis->poDefaultHandler;
     977                 : }
     978                 : 
     979                 : /************************************************************************/
     980                 : /*                           InstallHandler()                           */
     981                 : /************************************************************************/
     982                 : 
     983            8544 : void VSIFileManager::InstallHandler( const std::string& osPrefix,
     984                 :                                      VSIFilesystemHandler *poHandler )
     985                 : 
     986                 : {
     987            8544 :     if( osPrefix == "" )
     988             712 :         Get()->poDefaultHandler = poHandler;
     989                 :     else
     990            7832 :         Get()->oHandlers[osPrefix] = poHandler;
     991            8544 : }
     992                 : 
     993                 : /************************************************************************/
     994                 : /*                       VSICleanupFileManager()                        */
     995                 : /************************************************************************/
     996                 : 
     997            1033 : void VSICleanupFileManager()
     998                 : 
     999                 : {
    1000            1033 :     if( poManager )
    1001                 :     {
    1002             687 :         delete poManager;
    1003             687 :         poManager = NULL;
    1004                 :     }
    1005            1033 : }
    1006                 : 
    1007                 : /************************************************************************/
    1008                 : /*                           ReadMultiRange()                           */
    1009                 : /************************************************************************/
    1010                 : 
    1011               0 : int VSIVirtualHandle::ReadMultiRange( int nRanges, void ** ppData,
    1012                 :                                       const vsi_l_offset* panOffsets,
    1013                 :                                       const size_t* panSizes )
    1014                 : {
    1015               0 :     int nRet = 0;
    1016               0 :     vsi_l_offset nCurOffset = Tell();
    1017               0 :     for(int i=0;i<nRanges;i++)
    1018                 :     {
    1019               0 :         if (Seek(panOffsets[i], SEEK_SET) < 0)
    1020                 :         {
    1021               0 :             nRet = -1;
    1022               0 :             break;
    1023                 :         }
    1024                 : 
    1025               0 :         size_t nRead = Read(ppData[i], 1, panSizes[i]);
    1026               0 :         if (panSizes[i] != nRead)
    1027                 :         {
    1028               0 :             nRet = -1;
    1029               0 :             break;
    1030                 :         }
    1031                 :     }
    1032                 : 
    1033               0 :     Seek(nCurOffset, SEEK_SET);
    1034                 : 
    1035               0 :     return nRet;
    1036                 : }

Generated by: LCOV version 1.7