LCOV - code coverage report
Current view: directory - port - cpl_vsil_unix_stdio_64.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 94 93 98.9 %
Date: 2011-12-18 Functions: 22 20 90.9 %

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_vsil_unix_stdio_64.cpp 23506 2011-12-10 13:43:59Z rouault $
       3                 :  *
       4                 :  * Project:  CPL - Common Portability Library
       5                 :  * Purpose:  Implement VSI large file api for Unix platforms with fseek64()
       6                 :  *           and ftell64() such as IRIX. 
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  **********************************************************************
      10                 :  * Copyright (c) 2001, Frank Warmerdam
      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 OR
      23                 :  * 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                 :  * NB: Note that in wrappers we are always saving the error state (errno
      32                 :  * variable) to avoid side effects during debug prints or other possible
      33                 :  * standard function calls (error states will be overwritten after such
      34                 :  * a call).
      35                 :  *
      36                 :  ****************************************************************************/
      37                 : 
      38                 : #include "cpl_port.h"
      39                 : 
      40                 : #if !defined(WIN32) && !defined(WIN32CE)
      41                 : 
      42                 : #include "cpl_vsi_virtual.h"
      43                 : #include "cpl_string.h"
      44                 : 
      45                 : #include <unistd.h>
      46                 : #include <sys/stat.h>
      47                 : #include <sys/types.h>
      48                 : #include <dirent.h>
      49                 : #include <errno.h>
      50                 : 
      51                 : CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 23506 2011-12-10 13:43:59Z rouault $");
      52                 : 
      53                 : #if defined(UNIX_STDIO_64)
      54                 : 
      55                 : #ifndef VSI_FTELL64
      56                 : #define VSI_FTELL64 ftell64
      57                 : #endif
      58                 : #ifndef VSI_FSEEK64
      59                 : #define VSI_FSEEK64 fseek64
      60                 : #endif
      61                 : #ifndef VSI_FOPEN64
      62                 : #define VSI_FOPEN64 fopen64
      63                 : #endif
      64                 : #ifndef VSI_STAT64
      65                 : #define VSI_STAT64 stat64
      66                 : #endif
      67                 : #ifndef VSI_STAT64_T
      68                 : #define VSI_STAT64_T stat64
      69                 : #endif
      70                 : #ifndef VSI_FTRUNCATE64
      71                 : #define VSI_FTRUNCATE64 ftruncate64
      72                 : #endif
      73                 : 
      74                 : #else /* not UNIX_STDIO_64 */
      75                 : 
      76                 : #ifndef VSI_FTELL64
      77                 : #define VSI_FTELL64 ftell
      78                 : #endif
      79                 : #ifndef VSI_FSEEK64
      80                 : #define VSI_FSEEK64 fseek
      81                 : #endif
      82                 : #ifndef VSI_FOPEN64
      83                 : #define VSI_FOPEN64 fopen
      84                 : #endif
      85                 : #ifndef VSI_STAT64
      86                 : #define VSI_STAT64 stat
      87                 : #endif
      88                 : #ifndef VSI_STAT64_T
      89                 : #define VSI_STAT64_T stat
      90                 : #endif
      91                 : #ifndef VSI_FTRUNCATE64
      92                 : #define VSI_FTRUNCATE64 ftruncate
      93                 : #endif
      94                 : 
      95                 : #endif /* ndef UNIX_STDIO_64 */
      96                 : 
      97                 : /************************************************************************/
      98                 : /* ==================================================================== */
      99                 : /*                       VSIUnixStdioFilesystemHandler                  */
     100                 : /* ==================================================================== */
     101                 : /************************************************************************/
     102                 : 
     103                 : class VSIUnixStdioFilesystemHandler : public VSIFilesystemHandler 
     104            1275 : {
     105                 : public:
     106                 :     virtual VSIVirtualHandle *Open( const char *pszFilename, 
     107                 :                                     const char *pszAccess);
     108                 :     virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
     109                 :     virtual int      Unlink( const char *pszFilename );
     110                 :     virtual int      Rename( const char *oldpath, const char *newpath );
     111                 :     virtual int      Mkdir( const char *pszDirname, long nMode );
     112                 :     virtual int      Rmdir( const char *pszDirname );
     113                 :     virtual char   **ReadDir( const char *pszDirname );
     114                 : };
     115                 : 
     116                 : /************************************************************************/
     117                 : /* ==================================================================== */
     118                 : /*                        VSIUnixStdioHandle                            */
     119                 : /* ==================================================================== */
     120                 : /************************************************************************/
     121                 : 
     122                 : class VSIUnixStdioHandle : public VSIVirtualHandle
     123           43922 : {
     124                 :   public:
     125                 :     FILE          *fp;
     126                 :     vsi_l_offset  nOffset;
     127                 :     int           bLastOpWrite;
     128                 :     int           bLastOpRead;
     129                 :     int           bAtEOF;
     130                 : 
     131                 :     virtual int       Seek( vsi_l_offset nOffset, int nWhence );
     132                 :     virtual vsi_l_offset Tell();
     133                 :     virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
     134                 :     virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
     135                 :     virtual int       Eof();
     136                 :     virtual int       Flush();
     137                 :     virtual int       Close();
     138                 :     virtual int       Truncate( vsi_l_offset nNewSize );
     139                 : };
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                               Close()                                */
     143                 : /************************************************************************/
     144                 : 
     145           21961 : int VSIUnixStdioHandle::Close()
     146                 : 
     147                 : {
     148                 :     VSIDebug1( "VSIUnixStdioHandle::Close(%p)", fp );
     149                 : 
     150           21961 :     return fclose( fp );
     151                 : }
     152                 : 
     153                 : /************************************************************************/
     154                 : /*                                Seek()                                */
     155                 : /************************************************************************/
     156                 : 
     157          656091 : int VSIUnixStdioHandle::Seek( vsi_l_offset nOffset, int nWhence )
     158                 : 
     159                 : {
     160                 :     // seeks that do nothing are still surprisingly expensive with MSVCRT.
     161                 :     // try and short circuit if possible.
     162          656091 :     if( nWhence == SEEK_SET && nOffset == this->nOffset )
     163          179410 :         return 0;
     164                 : 
     165          476681 :     int     nResult = VSI_FSEEK64( fp, nOffset, nWhence );
     166          476681 :     int     nError = errno;
     167                 : 
     168                 : #ifdef VSI_DEBUG
     169                 : 
     170                 :     if( nWhence == SEEK_SET )
     171                 :     {
     172                 :         VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",SEEK_SET) = %d",
     173                 :                    fp, nOffset, nResult );
     174                 :     }
     175                 :     else if( nWhence == SEEK_END )
     176                 :     {
     177                 :         VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",SEEK_END) = %d",
     178                 :                    fp, nOffset, nResult );
     179                 :     }
     180                 :     else if( nWhence == SEEK_CUR )
     181                 :     {
     182                 :         VSIDebug3( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",SEEK_CUR) = %d",
     183                 :                    fp, nOffset, nResult );
     184                 :     }
     185                 :     else
     186                 :     {
     187                 :         VSIDebug4( "VSIUnixStdioHandle::Seek(%p," CPL_FRMT_GUIB ",%d-Unknown) = %d",
     188                 :                    fp, nOffset, nWhence, nResult );
     189                 :     }
     190                 : 
     191                 : #endif 
     192                 : 
     193          476681 :     if( nResult != -1 )
     194                 :     {
     195          476681 :         if( nWhence == SEEK_SET )
     196                 :         {
     197          202314 :             this->nOffset = nOffset;
     198                 :         }
     199          274367 :         else if( nWhence == SEEK_END )
     200                 :         {
     201          271184 :             this->nOffset = VSI_FTELL64( fp );
     202                 :         }
     203            3183 :         else if( nWhence == SEEK_CUR )
     204                 :         {
     205            3183 :             this->nOffset += nOffset;
     206                 :         }
     207                 :     }
     208                 :         
     209          476681 :     bLastOpWrite = FALSE;
     210          476681 :     bLastOpRead = FALSE;
     211          476681 :     bAtEOF = FALSE;
     212                 : 
     213          476681 :     errno = nError;
     214          476681 :     return nResult;
     215                 : }
     216                 : 
     217                 : /************************************************************************/
     218                 : /*                                Tell()                                */
     219                 : /************************************************************************/
     220                 : 
     221          759069 : vsi_l_offset VSIUnixStdioHandle::Tell()
     222                 : 
     223                 : {
     224                 : #ifdef notdef
     225                 :     vsi_l_offset    nOffset = VSI_FTELL64( fp );
     226                 :     int             nError = errno;
     227                 : 
     228                 :     VSIDebug2( "VSIUnixStdioHandle::Tell(%p) = %ld", fp, (long)nOffset );
     229                 : 
     230                 :     errno = nError;
     231                 :     return nOffset;
     232                 : #endif
     233          759069 :     return nOffset;
     234                 : }
     235                 : 
     236                 : /************************************************************************/
     237                 : /*                               Flush()                                */
     238                 : /************************************************************************/
     239                 : 
     240             939 : int VSIUnixStdioHandle::Flush()
     241                 : 
     242                 : {
     243                 :     VSIDebug1( "VSIUnixStdioHandle::Flush(%p)", fp );
     244                 : 
     245             939 :     return fflush( fp );
     246                 : }
     247                 : 
     248                 : /************************************************************************/
     249                 : /*                                Read()                                */
     250                 : /************************************************************************/
     251                 : 
     252         1992623 : size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
     253                 : 
     254                 : {
     255                 : /* -------------------------------------------------------------------- */
     256                 : /*      If a fwrite() is followed by an fread(), the POSIX rules are    */
     257                 : /*      that some of the write may still be buffered and lost.  We      */
     258                 : /*      are required to do a seek between to force flushing.   So we    */
     259                 : /*      keep careful track of what happened last to know if we          */
     260                 : /*      skipped a flushing seek that we may need to do now.             */
     261                 : /* -------------------------------------------------------------------- */
     262         1992623 :     if( bLastOpWrite )
     263             516 :         VSI_FSEEK64( fp, nOffset, SEEK_SET );
     264                 : 
     265                 : /* -------------------------------------------------------------------- */
     266                 : /*      Perform the read.                                               */
     267                 : /* -------------------------------------------------------------------- */
     268         1992623 :     size_t  nResult = fread( pBuffer, nSize, nCount, fp );
     269         1992623 :     int     nError = errno;
     270                 : 
     271                 :     VSIDebug4( "VSIUnixStdioHandle::Read(%p,%ld,%ld) = %ld", 
     272                 :                fp, (long)nSize, (long)nCount, (long)nResult );
     273                 : 
     274         1992623 :     errno = nError;
     275                 : 
     276                 : /* -------------------------------------------------------------------- */
     277                 : /*      Update current offset.                                          */
     278                 : /* -------------------------------------------------------------------- */
     279         1992623 :     nOffset += nSize * nResult;
     280         1992623 :     bLastOpWrite = FALSE;
     281         1992623 :     bLastOpRead = TRUE;
     282                 : 
     283         1992623 :     if (nResult != nCount)
     284           13700 :         bAtEOF = feof(fp);
     285                 :     
     286         1992623 :     return nResult;
     287                 : }
     288                 : 
     289                 : /************************************************************************/
     290                 : /*                               Write()                                */
     291                 : /************************************************************************/
     292                 : 
     293         1962606 : size_t VSIUnixStdioHandle::Write( const void * pBuffer, size_t nSize, 
     294                 :                                   size_t nCount )
     295                 : 
     296                 : {
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      If a fwrite() is followed by an fread(), the POSIX rules are    */
     299                 : /*      that some of the write may still be buffered and lost.  We      */
     300                 : /*      are required to do a seek between to force flushing.   So we    */
     301                 : /*      keep careful track of what happened last to know if we          */
     302                 : /*      skipped a flushing seek that we may need to do now.             */
     303                 : /* -------------------------------------------------------------------- */
     304         1962606 :     if( bLastOpRead )
     305            1204 :         VSI_FSEEK64( fp, nOffset, SEEK_SET );
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Perform the write.                                              */
     309                 : /* -------------------------------------------------------------------- */
     310         1962606 :     size_t  nResult = fwrite( pBuffer, nSize, nCount, fp );
     311         1962606 :     int     nError = errno;
     312                 : 
     313                 :     VSIDebug4( "VSIUnixStdioHandle::Write(%p,%ld,%ld) = %ld", 
     314                 :                fp, (long)nSize, (long)nCount, (long)nResult );
     315                 : 
     316         1962606 :     errno = nError;
     317                 : 
     318                 : /* -------------------------------------------------------------------- */
     319                 : /*      Update current offset.                                          */
     320                 : /* -------------------------------------------------------------------- */
     321         1962606 :     nOffset += nSize * nResult;
     322         1962606 :     bLastOpWrite = TRUE;
     323         1962606 :     bLastOpRead = FALSE;
     324                 :     
     325         1962606 :     return nResult;
     326                 : }
     327                 : 
     328                 : /************************************************************************/
     329                 : /*                                Eof()                                 */
     330                 : /************************************************************************/
     331                 : 
     332          290801 : int VSIUnixStdioHandle::Eof()
     333                 : 
     334                 : {
     335          290801 :     if( bAtEOF )
     336            2927 :         return 1;
     337                 :     else
     338          287874 :         return 0;
     339                 : }
     340                 : 
     341                 : /************************************************************************/
     342                 : /*                             Truncate()                               */
     343                 : /************************************************************************/
     344                 : 
     345               2 : int VSIUnixStdioHandle::Truncate( vsi_l_offset nNewSize )
     346                 : {
     347               2 :     fflush(fp);
     348               2 :     int nRet = VSI_FTRUNCATE64(fileno(fp), nNewSize);
     349               2 :     return nRet;
     350                 : }
     351                 : 
     352                 : 
     353                 : /************************************************************************/
     354                 : /* ==================================================================== */
     355                 : /*                       VSIUnixStdioFilesystemHandler                  */
     356                 : /* ==================================================================== */
     357                 : /************************************************************************/
     358                 : 
     359                 : /************************************************************************/
     360                 : /*                                Open()                                */
     361                 : /************************************************************************/
     362                 : 
     363                 : VSIVirtualHandle *
     364           39043 : VSIUnixStdioFilesystemHandler::Open( const char *pszFilename, 
     365                 :                                      const char *pszAccess )
     366                 : 
     367                 : {
     368           39043 :     FILE    *fp = VSI_FOPEN64( pszFilename, pszAccess );
     369           39043 :     int     nError = errno;
     370                 :     
     371                 :     VSIDebug3( "VSIUnixStdioFilesystemHandler::Open(\"%s\",\"%s\") = %p",
     372                 :                pszFilename, pszAccess, fp );
     373                 : 
     374           39043 :     if( fp == NULL )
     375                 :     {
     376           17082 :         errno = nError;
     377           17082 :         return NULL;
     378                 :     }
     379                 : 
     380           21961 :     VSIUnixStdioHandle *poHandle = new VSIUnixStdioHandle;
     381                 :     
     382           21961 :     poHandle->fp = fp;
     383           21961 :     poHandle->nOffset = 0;
     384           21961 :     poHandle->bLastOpWrite = FALSE;
     385           21961 :     poHandle->bLastOpRead = FALSE;
     386           21961 :     poHandle->bAtEOF = FALSE;
     387                 : 
     388           21961 :     errno = nError;
     389                 : 
     390                 : /* -------------------------------------------------------------------- */
     391                 : /*      If VSI_CACHE is set we want to use a cached reader instead      */
     392                 : /*      of more direct io on the underlying file.                       */
     393                 : /* -------------------------------------------------------------------- */
     394           41171 :     if( (EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb"))
     395                 :         && CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
     396                 :     {
     397               0 :         return VSICreateCachedFile( poHandle );
     398                 :     }
     399                 :     else
     400                 :     {
     401           21961 :         return poHandle;
     402                 :     }
     403                 : }
     404                 : 
     405                 : /************************************************************************/
     406                 : /*                                Stat()                                */
     407                 : /************************************************************************/
     408                 : 
     409           45222 : int VSIUnixStdioFilesystemHandler::Stat( const char * pszFilename, 
     410                 :                                          VSIStatBufL * pStatBuf,
     411                 :                                          int nFlags)
     412                 : 
     413                 : {
     414           45222 :     return( VSI_STAT64( pszFilename, pStatBuf ) );
     415                 : }
     416                 : 
     417                 : /************************************************************************/
     418                 : /*                               Unlink()                               */
     419                 : /************************************************************************/
     420                 : 
     421            2604 : int VSIUnixStdioFilesystemHandler::Unlink( const char * pszFilename )
     422                 : 
     423                 : {
     424            2604 :     return unlink( pszFilename );
     425                 : }
     426                 : 
     427                 : /************************************************************************/
     428                 : /*                               Rename()                               */
     429                 : /************************************************************************/
     430                 : 
     431              14 : int VSIUnixStdioFilesystemHandler::Rename( const char *oldpath,
     432                 :                                            const char *newpath )
     433                 : 
     434                 : {
     435              14 :     return rename( oldpath, newpath );
     436                 : }
     437                 : 
     438                 : /************************************************************************/
     439                 : /*                               Mkdir()                                */
     440                 : /************************************************************************/
     441                 : 
     442              74 : int VSIUnixStdioFilesystemHandler::Mkdir( const char * pszPathname,
     443                 :                                           long nMode )
     444                 : 
     445                 : {
     446              74 :     return mkdir( pszPathname, nMode );
     447                 : }
     448                 : 
     449                 : /************************************************************************/
     450                 : /*                               Rmdir()                                */
     451                 : /************************************************************************/
     452                 : 
     453              57 : int VSIUnixStdioFilesystemHandler::Rmdir( const char * pszPathname )
     454                 : 
     455                 : {
     456              57 :     return rmdir( pszPathname );
     457                 : }
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                              ReadDir()                               */
     461                 : /************************************************************************/
     462                 : 
     463            8737 : char **VSIUnixStdioFilesystemHandler::ReadDir( const char *pszPath )
     464                 : 
     465                 : {
     466                 :     DIR           *hDir;
     467                 :     struct dirent *psDirEntry;
     468            8737 :     CPLStringList  oDir;
     469                 : 
     470            8737 :     if (strlen(pszPath) == 0)
     471               4 :         pszPath = ".";
     472                 : 
     473            8737 :     if ( (hDir = opendir(pszPath)) != NULL )
     474                 :     {
     475                 :         // we want to avoid returning NULL for an empty list.
     476            7244 :         oDir.Assign( (char**) CPLCalloc(2,sizeof(char*)) );
     477                 : 
     478          432083 :         while( (psDirEntry = readdir(hDir)) != NULL )
     479          417595 :             oDir.AddString( psDirEntry->d_name );
     480                 : 
     481            7244 :         closedir( hDir );
     482                 :     }
     483                 :     else
     484                 :     {
     485                 :         /* Should we generate an error???  
     486                 :          * For now we'll just return NULL (at the end of the function)
     487                 :          */
     488                 :     }
     489                 : 
     490            8737 :     return oDir.StealList();
     491                 : }
     492                 : 
     493                 : /************************************************************************/
     494                 : /*                     VSIInstallLargeFileHandler()                     */
     495                 : /************************************************************************/
     496                 : 
     497             647 : void VSIInstallLargeFileHandler()
     498                 : 
     499                 : {
     500             647 :     VSIFileManager::InstallHandler( "", new VSIUnixStdioFilesystemHandler );
     501             647 : }
     502                 : 
     503                 : #endif /* ndef WIN32 */

Generated by: LCOV version 1.7