LCOV - code coverage report
Current view: directory - port - cpl_vsisimple.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 139 105 75.5 %
Date: 2012-12-26 Functions: 30 24 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: cpl_vsisimple.cpp 25139 2012-10-15 23:21:44Z rouault $
       3                 :  *
       4                 :  * Project:  Common Portability Library 
       5                 :  * Purpose:  Simple implementation of POSIX VSI functions.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1998, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************
      29                 :  *
      30                 :  * NB: Note that in wrappers we are always saving the error state (errno
      31                 :  * variable) to avoid side effects during debug prints or other possible
      32                 :  * standard function calls (error states will be overwritten after such
      33                 :  * a call).
      34                 :  *
      35                 :  ****************************************************************************/
      36                 : 
      37                 : #include "cpl_config.h"
      38                 : #include "cpl_port.h"
      39                 : #include "cpl_vsi.h"
      40                 : #include "cpl_error.h"
      41                 : #include "cpl_string.h"
      42                 : 
      43                 : /* Uncomment to check consistent usage of VSIMalloc(), VSIRealloc(), */
      44                 : /* VSICalloc(), VSIFree(), VSIStrdup() */
      45                 : //#define DEBUG_VSIMALLOC
      46                 : 
      47                 : /* Uncomment to compute memory usage statistics. */
      48                 : /* DEBUG_VSIMALLOC must also be defined */
      49                 : //#define DEBUG_VSIMALLOC_STATS
      50                 : 
      51                 : /* Highly experimental, and likely buggy. Do not use, except for fixing it! */
      52                 : /* DEBUG_VSIMALLOC must also be defined */
      53                 : //#define DEBUG_VSIMALLOC_MPROTECT
      54                 : 
      55                 : #ifdef DEBUG_VSIMALLOC_MPROTECT
      56                 : #include <sys/mman.h>
      57                 : #endif
      58                 : 
      59                 : /* Uncomment to print every memory allocation or deallocation. */
      60                 : /* DEBUG_VSIMALLOC must also be defined */
      61                 : //#define DEBUG_VSIMALLOC_VERBOSE
      62                 : 
      63                 : CPL_CVSID("$Id: cpl_vsisimple.cpp 25139 2012-10-15 23:21:44Z rouault $");
      64                 : 
      65                 : /* for stat() */
      66                 : 
      67                 : /* Unix or Windows NT/2000/XP */
      68                 : #if !defined(WIN32) && !defined(WIN32CE)
      69                 : #  include <unistd.h>
      70                 : #elif !defined(WIN32CE) /* not Win32 platform */
      71                 : #  include <io.h>
      72                 : #  include <fcntl.h>
      73                 : #  include <direct.h>
      74                 : #endif
      75                 : 
      76                 : /* Windows CE or other platforms */
      77                 : #if defined(WIN32CE)
      78                 : #  include <wce_io.h>
      79                 : #  include <wce_stat.h>
      80                 : #  include <wce_stdio.h>
      81                 : #  include <wce_string.h>
      82                 : #  include <wce_time.h>
      83                 : # define time wceex_time
      84                 : #else
      85                 : #  include <sys/stat.h>
      86                 : #  include <time.h>
      87                 : #endif
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                              VSIFOpen()                              */
      91                 : /************************************************************************/
      92                 : 
      93           13413 : FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
      94                 : 
      95                 : {
      96           13413 :     FILE *fp = NULL;
      97                 :     int     nError;
      98                 : 
      99                 : #if defined(WIN32) && !defined(WIN32CE)
     100                 :     if( CSLTestBoolean(
     101                 :             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     102                 :     {
     103                 :         wchar_t *pwszFilename = 
     104                 :             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
     105                 :         wchar_t *pwszAccess = 
     106                 :             CPLRecodeToWChar( pszAccess, CPL_ENC_UTF8, CPL_ENC_UCS2 );
     107                 : 
     108                 :         fp = _wfopen( pwszFilename, pwszAccess );
     109                 : 
     110                 :         CPLFree( pwszFilename );
     111                 :         CPLFree( pwszAccess );
     112                 :     }
     113                 :     else
     114                 : #endif
     115           13413 :     fp = fopen( (char *) pszFilename, (char *) pszAccess );
     116                 : 
     117           13413 :     nError = errno;
     118                 :     VSIDebug3( "VSIFOpen(%s,%s) = %p", pszFilename, pszAccess, fp );
     119           13413 :     errno = nError;
     120                 : 
     121           13413 :     return( fp );
     122                 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                             VSIFClose()                              */
     126                 : /************************************************************************/
     127                 : 
     128           11845 : int VSIFClose( FILE * fp )
     129                 : 
     130                 : {
     131                 :     VSIDebug1( "VSIClose(%p)", fp );
     132                 : 
     133           11845 :     return( fclose(fp) );
     134                 : }
     135                 : 
     136                 : /************************************************************************/
     137                 : /*                              VSIFSeek()                              */
     138                 : /************************************************************************/
     139                 : 
     140          407865 : int VSIFSeek( FILE * fp, long nOffset, int nWhence )
     141                 : 
     142                 : {
     143          407865 :     int     nResult = fseek( fp, nOffset, nWhence );
     144          407865 :     int     nError = errno;
     145                 : 
     146                 : #ifdef VSI_DEBUG
     147                 :     if( nWhence == SEEK_SET )
     148                 :     {
     149                 :         VSIDebug3( "VSIFSeek(%p,%ld,SEEK_SET) = %d", fp, nOffset, nResult );
     150                 :     }
     151                 :     else if( nWhence == SEEK_END )
     152                 :     {
     153                 :         VSIDebug3( "VSIFSeek(%p,%ld,SEEK_END) = %d", fp, nOffset, nResult );
     154                 :     }
     155                 :     else if( nWhence == SEEK_CUR )
     156                 :     {
     157                 :         VSIDebug3( "VSIFSeek(%p,%ld,SEEK_CUR) = %d", fp, nOffset, nResult );
     158                 :     }
     159                 :     else
     160                 :     {
     161                 :         VSIDebug4( "VSIFSeek(%p,%ld,%d-Unknown) = %d",
     162                 :                    fp, nOffset, nWhence, nResult );
     163                 :     }
     164                 : #endif 
     165                 : 
     166          407865 :     errno = nError;
     167          407865 :     return nResult;
     168                 : }
     169                 : 
     170                 : /************************************************************************/
     171                 : /*                              VSIFTell()                              */
     172                 : /************************************************************************/
     173                 : 
     174         2516368 : long VSIFTell( FILE * fp )
     175                 : 
     176                 : {
     177         2516368 :     long    nOffset = ftell(fp);
     178         2516368 :     int     nError = errno;
     179                 : 
     180                 :     VSIDebug2( "VSIFTell(%p) = %ld", fp, nOffset );
     181                 : 
     182         2516368 :     errno = nError;
     183         2516368 :     return nOffset;
     184                 : }
     185                 : 
     186                 : /************************************************************************/
     187                 : /*                             VSIRewind()                              */
     188                 : /************************************************************************/
     189                 : 
     190            7758 : void VSIRewind( FILE * fp )
     191                 : 
     192                 : {
     193                 :     VSIDebug1("VSIRewind(%p)", fp );
     194            7758 :     rewind( fp );
     195            7758 : }
     196                 : 
     197                 : /************************************************************************/
     198                 : /*                              VSIFRead()                              */
     199                 : /************************************************************************/
     200                 : 
     201          416313 : size_t VSIFRead( void * pBuffer, size_t nSize, size_t nCount, FILE * fp )
     202                 : 
     203                 : {
     204          416313 :     size_t  nResult = fread( pBuffer, nSize, nCount, fp );
     205          416313 :     int     nError = errno;
     206                 : 
     207                 :     VSIDebug4( "VSIFRead(%p,%ld,%ld) = %ld", 
     208                 :                fp, (long)nSize, (long)nCount, (long)nResult );
     209                 : 
     210          416313 :     errno = nError;
     211          416313 :     return nResult;
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /*                             VSIFWrite()                              */
     216                 : /************************************************************************/
     217                 : 
     218            1611 : size_t VSIFWrite( const void *pBuffer, size_t nSize, size_t nCount, FILE * fp )
     219                 : 
     220                 : {
     221            1611 :     size_t  nResult = fwrite( pBuffer, nSize, nCount, fp );
     222            1611 :     int     nError = errno;
     223                 : 
     224                 :     VSIDebug4( "VSIFWrite(%p,%ld,%ld) = %ld", 
     225                 :                fp, (long)nSize, (long)nCount, (long)nResult );
     226                 : 
     227            1611 :     errno = nError;
     228            1611 :     return nResult;
     229                 : }
     230                 : 
     231                 : /************************************************************************/
     232                 : /*                             VSIFFlush()                              */
     233                 : /************************************************************************/
     234                 : 
     235               2 : void VSIFFlush( FILE * fp )
     236                 : 
     237                 : {
     238                 :     VSIDebug1( "VSIFFlush(%p)", fp );
     239               2 :     fflush( fp );
     240               2 : }
     241                 : 
     242                 : /************************************************************************/
     243                 : /*                              VSIFGets()                              */
     244                 : /************************************************************************/
     245                 : 
     246         1468767 : char *VSIFGets( char *pszBuffer, int nBufferSize, FILE * fp )
     247                 : 
     248                 : {
     249         1468767 :     return( fgets( pszBuffer, nBufferSize, fp ) );
     250                 : }
     251                 : 
     252                 : /************************************************************************/
     253                 : /*                              VSIFGetc()                              */
     254                 : /************************************************************************/
     255                 : 
     256            8386 : int VSIFGetc( FILE * fp )
     257                 : 
     258                 : {
     259            8386 :     return( fgetc( fp ) );
     260                 : }
     261                 : 
     262                 : /************************************************************************/
     263                 : /*                             VSIUngetc()                              */
     264                 : /************************************************************************/
     265                 : 
     266             132 : int VSIUngetc( int c, FILE * fp )
     267                 : 
     268                 : {
     269             132 :     return( ungetc( c, fp ) );
     270                 : }
     271                 : 
     272                 : /************************************************************************/
     273                 : /*                             VSIFPrintf()                             */
     274                 : /*                                                                      */
     275                 : /*      This is a little more complicated than just calling             */
     276                 : /*      fprintf() because of the variable arguments.  Instead we        */
     277                 : /*      have to use vfprintf().                                         */
     278                 : /************************************************************************/
     279                 : 
     280              95 : int     VSIFPrintf( FILE * fp, const char * pszFormat, ... )
     281                 : 
     282                 : {
     283                 :     va_list     args;
     284                 :     int         nReturn;
     285                 : 
     286              95 :     va_start( args, pszFormat );
     287              95 :     nReturn = vfprintf( fp, pszFormat, args );
     288              95 :     va_end( args );
     289                 : 
     290              95 :     return( nReturn );
     291                 : }
     292                 : 
     293                 : /************************************************************************/
     294                 : /*                              VSIFEof()                               */
     295                 : /************************************************************************/
     296                 : 
     297          241302 : int VSIFEof( FILE * fp )
     298                 : 
     299                 : {
     300          241302 :     return( feof( fp ) );
     301                 : }
     302                 : 
     303                 : /************************************************************************/
     304                 : /*                              VSIFPuts()                              */
     305                 : /************************************************************************/
     306                 : 
     307               0 : int VSIFPuts( const char * pszString, FILE * fp )
     308                 : 
     309                 : {
     310               0 :     return fputs( pszString, fp );
     311                 : }
     312                 : 
     313                 : /************************************************************************/
     314                 : /*                              VSIFPutc()                              */
     315                 : /************************************************************************/
     316                 : 
     317               0 : int VSIFPutc( int nChar, FILE * fp )
     318                 : 
     319                 : {
     320               0 :     return( fputc( nChar, fp ) );
     321                 : }
     322                 : 
     323                 : 
     324                 : #ifdef DEBUG_VSIMALLOC_STATS
     325                 : #include "cpl_multiproc.h"
     326                 : 
     327                 : static void* hMemStatMutex = 0;
     328                 : static size_t nCurrentTotalAllocs = 0;
     329                 : static size_t nMaxTotalAllocs = 0;
     330                 : static GUIntBig nVSIMallocs = 0;
     331                 : static GUIntBig nVSICallocs = 0;
     332                 : static GUIntBig nVSIReallocs = 0;
     333                 : static GUIntBig nVSIFrees = 0;
     334                 : 
     335                 : /*size_t GetMaxTotalAllocs()
     336                 : {
     337                 :     return nMaxTotalAllocs;
     338                 : }*/
     339                 : 
     340                 : /************************************************************************/
     341                 : /*                         VSIShowMemStats()                            */
     342                 : /************************************************************************/
     343                 : 
     344                 : void VSIShowMemStats()
     345                 : {
     346                 :     char* pszShowMemStats = getenv("CPL_SHOW_MEM_STATS");
     347                 :     if (pszShowMemStats == NULL || pszShowMemStats[0] == '\0' )
     348                 :         return;
     349                 :     printf("Current VSI memory usage        : " CPL_FRMT_GUIB " bytes\n",
     350                 :             (GUIntBig)nCurrentTotalAllocs);
     351                 :     printf("Maximum VSI memory usage        : " CPL_FRMT_GUIB " bytes\n",
     352                 :             (GUIntBig)nMaxTotalAllocs);
     353                 :     printf("Number of calls to VSIMalloc()  : " CPL_FRMT_GUIB "\n",
     354                 :             nVSIMallocs);
     355                 :     printf("Number of calls to VSICalloc()  : " CPL_FRMT_GUIB "\n",
     356                 :             nVSICallocs);
     357                 :     printf("Number of calls to VSIRealloc() : " CPL_FRMT_GUIB "\n",
     358                 :             nVSIReallocs);
     359                 :     printf("Number of calls to VSIFree()    : " CPL_FRMT_GUIB "\n",
     360                 :             nVSIFrees);
     361                 :     printf("VSIMalloc + VSICalloc - VSIFree : " CPL_FRMT_GUIB "\n",
     362                 :             nVSIMallocs + nVSICallocs - nVSIFrees);
     363                 : }
     364                 : #endif
     365                 : 
     366                 : #ifdef DEBUG_VSIMALLOC
     367                 : static GIntBig nMaxPeakAllocSize = -1;
     368                 : static GIntBig nMaxCumulAllocSize = -1;
     369                 : #endif
     370                 : 
     371                 : /************************************************************************/
     372                 : /*                             VSICalloc()                              */
     373                 : /************************************************************************/
     374                 : 
     375         6788136 : void *VSICalloc( size_t nCount, size_t nSize )
     376                 : 
     377                 : {
     378                 : #ifdef DEBUG_VSIMALLOC
     379                 :     size_t nMul = nCount * nSize;
     380                 :     if (nCount != 0 && nMul / nCount != nSize)
     381                 :     {
     382                 :         fprintf(stderr, "Overflow in VSICalloc(%d, %d)\n",
     383                 :                 (int)nCount, (int)nSize);
     384                 :         return NULL;
     385                 :     }
     386                 :     if (nMaxPeakAllocSize < 0)
     387                 :     {
     388                 :         char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
     389                 :         nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
     390                 :         char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
     391                 :         nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
     392                 :     }
     393                 :     if (nMaxPeakAllocSize > 0 && (GIntBig)nMul > nMaxPeakAllocSize)
     394                 :         return NULL;
     395                 : #ifdef DEBUG_VSIMALLOC_STATS
     396                 :     if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nMul > nMaxCumulAllocSize)
     397                 :         return NULL;
     398                 : #endif
     399                 : 
     400                 : #ifdef DEBUG_VSIMALLOC_MPROTECT
     401                 :     char* ptr = NULL;
     402                 :     size_t nPageSize = getpagesize();
     403                 :     posix_memalign((void**)&ptr, nPageSize, (3 * sizeof(void*) + nMul + nPageSize - 1) & ~(nPageSize - 1));
     404                 :     if (ptr == NULL)
     405                 :         return NULL;
     406                 :     memset(ptr + 2 * sizeof(void*), 0, nMul);
     407                 : #else
     408                 :     char* ptr = (char*) calloc(1, 3 * sizeof(void*) + nMul);
     409                 :     if (ptr == NULL)
     410                 :         return NULL;
     411                 : #endif
     412                 : 
     413                 :     ptr[0] = 'V';
     414                 :     ptr[1] = 'S';
     415                 :     ptr[2] = 'I';
     416                 :     ptr[3] = 'M';
     417                 :     memcpy(ptr + sizeof(void*), &nMul, sizeof(void*));
     418                 :     ptr[2 * sizeof(void*) + nMul + 0] = 'E';
     419                 :     ptr[2 * sizeof(void*) + nMul + 1] = 'V';
     420                 :     ptr[2 * sizeof(void*) + nMul + 2] = 'S';
     421                 :     ptr[2 * sizeof(void*) + nMul + 3] = 'I';
     422                 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
     423                 :     {
     424                 :         CPLMutexHolderD(&hMemStatMutex);
     425                 : #ifdef DEBUG_VSIMALLOC_VERBOSE
     426                 :         fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p\n",
     427                 :                 (void*)CPLGetPID(), (int)nCount, (int)nSize, ptr + 2 * sizeof(void*));
     428                 : #endif
     429                 : #ifdef DEBUG_VSIMALLOC_STATS
     430                 :         nVSICallocs ++;
     431                 :         if (nMaxTotalAllocs == 0)
     432                 :             atexit(VSIShowMemStats);
     433                 :         nCurrentTotalAllocs += nMul;
     434                 :         if (nCurrentTotalAllocs > nMaxTotalAllocs)
     435                 :             nMaxTotalAllocs = nCurrentTotalAllocs;
     436                 : #endif
     437                 :     }
     438                 : #endif
     439                 :     return ptr + 2 * sizeof(void*);
     440                 : #else
     441         6788136 :     return( calloc( nCount, nSize ) );
     442                 : #endif
     443                 : }
     444                 : 
     445                 : /************************************************************************/
     446                 : /*                             VSIMalloc()                              */
     447                 : /************************************************************************/
     448                 : 
     449        45468395 : void *VSIMalloc( size_t nSize )
     450                 : 
     451                 : {
     452                 : #ifdef DEBUG_VSIMALLOC
     453                 :     if (nMaxPeakAllocSize < 0)
     454                 :     {
     455                 :         char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
     456                 :         nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
     457                 :         char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
     458                 :         nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
     459                 :     }
     460                 :     if (nMaxPeakAllocSize > 0 && (GIntBig)nSize > nMaxPeakAllocSize)
     461                 :         return NULL;
     462                 : #ifdef DEBUG_VSIMALLOC_STATS
     463                 :     if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nSize > nMaxCumulAllocSize)
     464                 :         return NULL;
     465                 : #endif
     466                 : 
     467                 : #ifdef DEBUG_VSIMALLOC_MPROTECT
     468                 :     char* ptr = NULL;
     469                 :     size_t nPageSize = getpagesize();
     470                 :     posix_memalign((void**)&ptr, nPageSize, (3 * sizeof(void*) + nSize + nPageSize - 1) & ~(nPageSize - 1));
     471                 : #else
     472                 :     char* ptr = (char*) malloc(3 * sizeof(void*) + nSize);
     473                 : #endif
     474                 :     if (ptr == NULL)
     475                 :         return NULL;
     476                 :     ptr[0] = 'V';
     477                 :     ptr[1] = 'S';
     478                 :     ptr[2] = 'I';
     479                 :     ptr[3] = 'M';
     480                 :     memcpy(ptr + sizeof(void*), &nSize, sizeof(void*));
     481                 :     ptr[2 * sizeof(void*) + nSize + 0] = 'E';
     482                 :     ptr[2 * sizeof(void*) + nSize + 1] = 'V';
     483                 :     ptr[2 * sizeof(void*) + nSize + 2] = 'S';
     484                 :     ptr[2 * sizeof(void*) + nSize + 3] = 'I';
     485                 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
     486                 :     {
     487                 :         CPLMutexHolderD(&hMemStatMutex);
     488                 : #ifdef DEBUG_VSIMALLOC_VERBOSE
     489                 :         fprintf(stderr, "Thread[%p] VSIMalloc(%d) = %p\n",
     490                 :                 (void*)CPLGetPID(), (int)nSize, ptr + 2 * sizeof(void*));
     491                 : #endif
     492                 : #ifdef DEBUG_VSIMALLOC_STATS
     493                 :         nVSIMallocs ++;
     494                 :         if (nMaxTotalAllocs == 0)
     495                 :             atexit(VSIShowMemStats);
     496                 :         nCurrentTotalAllocs += nSize;
     497                 :         if (nCurrentTotalAllocs > nMaxTotalAllocs)
     498                 :             nMaxTotalAllocs = nCurrentTotalAllocs;
     499                 : #endif
     500                 :     }
     501                 : #endif
     502                 :     return ptr + 2 * sizeof(void*);
     503                 : #else
     504        45468395 :     return( malloc( nSize ) );
     505                 : #endif
     506                 : }
     507                 : 
     508                 : #ifdef DEBUG_VSIMALLOC
     509                 : void VSICheckMarkerBegin(char* ptr)
     510                 : {
     511                 :     if (memcmp(ptr, "VSIM", 4) != 0)
     512                 :     {
     513                 :         CPLError(CE_Fatal, CPLE_AppDefined,
     514                 :                  "Inconsistant use of VSI memory allocation primitives for %p : %c%c%c%c",
     515                 :                  ptr, ptr[0], ptr[1], ptr[2], ptr[3]);
     516                 :     }
     517                 : }
     518                 : 
     519                 : void VSICheckMarkerEnd(char* ptr, size_t nEnd)
     520                 : {
     521                 :     if (memcmp(ptr + nEnd, "EVSI", 4) != 0)
     522                 :     {
     523                 :         CPLError(CE_Fatal, CPLE_AppDefined,
     524                 :                  "Memory has been written after the end of %p", ptr);
     525                 :     }
     526                 : }
     527                 : 
     528                 : #endif
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                             VSIRealloc()                             */
     532                 : /************************************************************************/      
     533                 : 
     534        17217430 : void * VSIRealloc( void * pData, size_t nNewSize )
     535                 : 
     536                 : {
     537                 : #ifdef DEBUG_VSIMALLOC
     538                 :     if (pData == NULL)
     539                 :         return VSIMalloc(nNewSize);
     540                 :         
     541                 :     char* ptr = ((char*)pData) - 2 * sizeof(void*);
     542                 :     VSICheckMarkerBegin(ptr);
     543                 : 
     544                 :     size_t nOldSize;
     545                 :     memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
     546                 :     VSICheckMarkerEnd(ptr, 2 * sizeof(void*) + nOldSize);
     547                 :     ptr[2 * sizeof(void*) + nOldSize + 0] = 'I';
     548                 :     ptr[2 * sizeof(void*) + nOldSize + 1] = 'S';
     549                 :     ptr[2 * sizeof(void*) + nOldSize + 2] = 'V';
     550                 :     ptr[2 * sizeof(void*) + nOldSize + 3] = 'E';
     551                 : 
     552                 :     if (nMaxPeakAllocSize < 0)
     553                 :     {
     554                 :         char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
     555                 :         nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
     556                 :     }
     557                 :     if (nMaxPeakAllocSize > 0 && (GIntBig)nNewSize > nMaxPeakAllocSize)
     558                 :         return NULL;
     559                 : #ifdef DEBUG_VSIMALLOC_STATS
     560                 :     if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nNewSize - (GIntBig)nOldSize > nMaxCumulAllocSize)
     561                 :         return NULL;
     562                 : #endif
     563                 : 
     564                 : #ifdef DEBUG_VSIMALLOC_MPROTECT
     565                 :     char* newptr = NULL;
     566                 :     size_t nPageSize = getpagesize();
     567                 :     posix_memalign((void**)&newptr, nPageSize, (nNewSize + 3 * sizeof(void*) + nPageSize - 1) & ~(nPageSize - 1));
     568                 :     if (newptr == NULL)
     569                 :         return NULL;
     570                 :     memcpy(newptr + 2 * sizeof(void*), pData, nOldSize);
     571                 :     ptr[0] = 'M';
     572                 :     ptr[1] = 'I';
     573                 :     ptr[2] = 'S';
     574                 :     ptr[3] = 'V';
     575                 :     free(ptr);
     576                 :     newptr[0] = 'V';
     577                 :     newptr[1] = 'S';
     578                 :     newptr[2] = 'I';
     579                 :     newptr[3] = 'M';
     580                 : #else
     581                 :     void* newptr = realloc(ptr, nNewSize + 3 * sizeof(void*));
     582                 :     if (newptr == NULL)
     583                 :         return NULL;
     584                 : #endif
     585                 :     ptr = (char*) newptr;
     586                 :     memcpy(ptr + sizeof(void*), &nNewSize, sizeof(void*));
     587                 :     ptr[2 * sizeof(void*) + nNewSize + 0] = 'E';
     588                 :     ptr[2 * sizeof(void*) + nNewSize + 1] = 'V';
     589                 :     ptr[2 * sizeof(void*) + nNewSize + 2] = 'S';
     590                 :     ptr[2 * sizeof(void*) + nNewSize + 3] = 'I';
     591                 : 
     592                 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
     593                 :     {
     594                 :         CPLMutexHolderD(&hMemStatMutex);
     595                 : #ifdef DEBUG_VSIMALLOC_VERBOSE
     596                 :         fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p\n",
     597                 :                 (void*)CPLGetPID(), pData, (int)nNewSize, ptr + 2 * sizeof(void*));
     598                 : #endif
     599                 : #ifdef DEBUG_VSIMALLOC_STATS
     600                 :         nVSIReallocs ++;
     601                 :         nCurrentTotalAllocs -= nOldSize;
     602                 :         nCurrentTotalAllocs += nNewSize;
     603                 :         if (nCurrentTotalAllocs > nMaxTotalAllocs)
     604                 :             nMaxTotalAllocs = nCurrentTotalAllocs;
     605                 : #endif
     606                 :     }
     607                 : #endif
     608                 :     return ptr + 2 * sizeof(void*);
     609                 : #else
     610        17217430 :     return( realloc( pData, nNewSize ) );
     611                 : #endif
     612                 : }
     613                 : 
     614                 : /************************************************************************/
     615                 : /*                              VSIFree()                               */
     616                 : /************************************************************************/
     617                 : 
     618        72628608 : void VSIFree( void * pData )
     619                 : 
     620                 : {
     621                 : #ifdef DEBUG_VSIMALLOC
     622                 :     if (pData == NULL)
     623                 :         return;
     624                 : 
     625                 :     char* ptr = ((char*)pData) - 2 * sizeof(void*);
     626                 :     VSICheckMarkerBegin(ptr);
     627                 :     size_t nOldSize;
     628                 :     memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
     629                 :     VSICheckMarkerEnd(ptr, 2 * sizeof(void*) + nOldSize);
     630                 :     ptr[0] = 'M';
     631                 :     ptr[1] = 'I';
     632                 :     ptr[2] = 'S';
     633                 :     ptr[3] = 'V';
     634                 :     ptr[2 * sizeof(void*) + nOldSize + 0] = 'I';
     635                 :     ptr[2 * sizeof(void*) + nOldSize + 1] = 'S';
     636                 :     ptr[2 * sizeof(void*) + nOldSize + 2] = 'V';
     637                 :     ptr[2 * sizeof(void*) + nOldSize + 3] = 'E';
     638                 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
     639                 :     {
     640                 :         CPLMutexHolderD(&hMemStatMutex);
     641                 : #ifdef DEBUG_VSIMALLOC_VERBOSE
     642                 :         fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n",
     643                 :                 (void*)CPLGetPID(), pData, (int)nOldSize);
     644                 : #endif
     645                 : #ifdef DEBUG_VSIMALLOC_STATS
     646                 :         nVSIFrees ++;
     647                 :         nCurrentTotalAllocs -= nOldSize;
     648                 : #endif
     649                 :     }
     650                 : #endif
     651                 : 
     652                 : #ifdef DEBUG_VSIMALLOC_MPROTECT
     653                 :     mprotect(ptr, nOldSize + 2 * sizeof(void*), PROT_NONE);
     654                 : #else
     655                 :     free(ptr);
     656                 : #endif
     657                 : 
     658                 : #else
     659        72628608 :     if( pData != NULL )
     660        58782723 :         free( pData );
     661                 : #endif
     662        72628608 : }
     663                 : 
     664                 : /************************************************************************/
     665                 : /*                             VSIStrdup()                              */
     666                 : /************************************************************************/
     667                 : 
     668         5540552 : char *VSIStrdup( const char * pszString )
     669                 : 
     670                 : {
     671                 : #ifdef DEBUG_VSIMALLOC
     672                 :     int nSize = strlen(pszString) + 1;
     673                 :     char* ptr = (char*) VSIMalloc(nSize);
     674                 :     if (ptr == NULL)
     675                 :         return NULL;
     676                 :     memcpy(ptr, pszString, nSize);
     677                 :     return ptr;
     678                 : #else
     679         5540552 :     return( strdup( pszString ) );
     680                 : #endif
     681                 : }
     682                 : 
     683                 : /************************************************************************/
     684                 : /*                          VSICheckMul2()                              */
     685                 : /************************************************************************/
     686                 : 
     687           31571 : static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag)
     688                 : {
     689           31571 :     size_t res = mul1 * mul2;
     690           31571 :     if (mul1 != 0)
     691                 :     {
     692           31570 :         if (res / mul1 == mul2)
     693                 :         {
     694           31570 :             if (pbOverflowFlag)
     695           31570 :                 *pbOverflowFlag = FALSE;
     696           31570 :             return res;
     697                 :         }
     698                 :         else
     699                 :         {
     700               0 :             if (pbOverflowFlag)
     701               0 :                 *pbOverflowFlag = TRUE;
     702                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     703                 :                      "Multiplication overflow : %lu * %lu",
     704               0 :                      (unsigned long)mul1, (unsigned long)mul2);
     705                 :         }
     706                 :     }
     707                 :     else
     708                 :     {
     709               1 :         if (pbOverflowFlag)
     710               1 :              *pbOverflowFlag = FALSE;
     711                 :     }
     712               1 :     return 0;
     713                 : }
     714                 : 
     715                 : /************************************************************************/
     716                 : /*                          VSICheckMul3()                              */
     717                 : /************************************************************************/
     718                 : 
     719           15849 : static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverflowFlag)
     720                 : {
     721           15849 :     if (mul1 != 0)
     722                 :     {
     723           15849 :         size_t res = mul1 * mul2;
     724           15849 :         if (res / mul1 == mul2)
     725                 :         {
     726           15849 :             size_t res2 = res * mul3;
     727           15849 :             if (mul3 != 0)
     728                 :             {
     729           15849 :                 if (res2 / mul3 == res)
     730                 :                 {
     731           15847 :                     if (pbOverflowFlag)
     732           15847 :                         *pbOverflowFlag = FALSE;
     733           15847 :                     return res2;
     734                 :                 }
     735                 :                 else
     736                 :                 {
     737               2 :                     if (pbOverflowFlag)
     738               2 :                         *pbOverflowFlag = TRUE;
     739                 :                     CPLError(CE_Failure, CPLE_OutOfMemory,
     740                 :                      "Multiplication overflow : %lu * %lu * %lu",
     741               2 :                      (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
     742                 :                 }
     743                 :             }
     744                 :             else
     745                 :             {
     746               0 :                 if (pbOverflowFlag)
     747               0 :                     *pbOverflowFlag = FALSE;
     748                 :             }
     749                 :         }
     750                 :         else
     751                 :         {
     752               0 :             if (pbOverflowFlag)
     753               0 :                 *pbOverflowFlag = TRUE;
     754                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     755                 :                      "Multiplication overflow : %lu * %lu * %lu",
     756               0 :                      (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
     757                 :         }
     758                 :     }
     759                 :     else
     760                 :     {
     761               0 :         if (pbOverflowFlag)
     762               0 :              *pbOverflowFlag = FALSE;
     763                 :     }
     764               2 :     return 0;
     765                 : }
     766                 : 
     767                 : 
     768                 : 
     769                 : /**
     770                 :  VSIMalloc2 allocates (nSize1 * nSize2) bytes.
     771                 :  In case of overflow of the multiplication, or if memory allocation fails, a
     772                 :  NULL pointer is returned and a CE_Failure error is raised with CPLError().
     773                 :  If nSize1 == 0 || nSize2 == 0, a NULL pointer will also be returned.
     774                 :  CPLFree() or VSIFree() can be used to free memory allocated by this function.
     775                 : */
     776           31572 : void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 )
     777                 : {
     778           31572 :     int bOverflowFlag = FALSE;
     779                 :     size_t nSizeToAllocate;
     780                 :     void* pReturn;
     781                 : 
     782           31572 :     nSizeToAllocate = VSICheckMul2( nSize1, nSize2, &bOverflowFlag );
     783           31571 :     if (bOverflowFlag)
     784               0 :         return NULL;
     785                 : 
     786           31571 :     if (nSizeToAllocate == 0)
     787              64 :         return NULL;
     788                 : 
     789           31507 :     pReturn = VSIMalloc(nSizeToAllocate);
     790                 : 
     791           31508 :     if( pReturn == NULL )
     792                 :     {
     793                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     794                 :                   "VSIMalloc2(): Out of memory allocating %lu bytes.\n",
     795               0 :                   (unsigned long)nSizeToAllocate );
     796                 :     }
     797                 : 
     798           31508 :     return pReturn;
     799                 : }
     800                 : 
     801                 : /**
     802                 :  VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.
     803                 :  In case of overflow of the multiplication, or if memory allocation fails, a
     804                 :  NULL pointer is returned and a CE_Failure error is raised with CPLError().
     805                 :  If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.
     806                 :  CPLFree() or VSIFree() can be used to free memory allocated by this function.
     807                 : */
     808           15849 : void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 )
     809                 : {
     810           15849 :     int bOverflowFlag = FALSE;
     811                 : 
     812                 :     size_t nSizeToAllocate;
     813                 :     void* pReturn;
     814                 : 
     815           15849 :     nSizeToAllocate = VSICheckMul3( nSize1, nSize2, nSize3, &bOverflowFlag );
     816           15849 :     if (bOverflowFlag)
     817               2 :         return NULL;
     818                 : 
     819           15847 :     if (nSizeToAllocate == 0)
     820               0 :         return NULL;
     821                 : 
     822           15847 :     pReturn = VSIMalloc(nSizeToAllocate);
     823                 : 
     824           15847 :     if( pReturn == NULL )
     825                 :     {
     826                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     827                 :                   "VSIMalloc3(): Out of memory allocating %lu bytes.\n",
     828               0 :                   (unsigned long)nSizeToAllocate );
     829                 :     }
     830                 : 
     831           15847 :     return pReturn;
     832                 : }
     833                 : 
     834                 : 
     835                 : /************************************************************************/
     836                 : /*                              VSIStat()                               */
     837                 : /************************************************************************/
     838                 : 
     839            5820 : int VSIStat( const char * pszFilename, VSIStatBuf * pStatBuf )
     840                 : 
     841                 : {
     842                 : #if defined(WIN32) && !defined(WIN32CE)
     843                 :     if( CSLTestBoolean(
     844                 :             CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     845                 :     {
     846                 :         int nResult;
     847                 :         wchar_t *pwszFilename = 
     848                 :             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
     849                 : 
     850                 :         nResult = _wstat( pwszFilename, (struct _stat *) pStatBuf );
     851                 : 
     852                 :         CPLFree( pwszFilename );
     853                 : 
     854                 :         return nResult;
     855                 :     }
     856                 :     else
     857                 : #endif 
     858            5820 :         return( stat( pszFilename, pStatBuf ) );
     859                 : }
     860                 : 
     861                 : /************************************************************************/
     862                 : /*                              VSITime()                               */
     863                 : /************************************************************************/
     864                 : 
     865               0 : unsigned long VSITime( unsigned long * pnTimeToSet )
     866                 : 
     867                 : {
     868                 :     time_t tTime;
     869                 :         
     870               0 :     tTime = time( NULL );
     871                 : 
     872               0 :     if( pnTimeToSet != NULL )
     873               0 :         *pnTimeToSet = (unsigned long) tTime;
     874                 : 
     875               0 :     return (unsigned long) tTime;
     876                 : }
     877                 : 
     878                 : /************************************************************************/
     879                 : /*                              VSICTime()                              */
     880                 : /************************************************************************/
     881                 : 
     882               0 : const char *VSICTime( unsigned long nTime )
     883                 : 
     884                 : {
     885               0 :     time_t tTime = (time_t) nTime;
     886                 : 
     887               0 :     return (const char *) ctime( &tTime );
     888                 : }
     889                 : 
     890                 : /************************************************************************/
     891                 : /*                             VSIGMTime()                              */
     892                 : /************************************************************************/
     893                 : 
     894               0 : struct tm *VSIGMTime( const time_t *pnTime, struct tm *poBrokenTime )
     895                 : {
     896                 : 
     897                 : #if HAVE_GMTIME_R
     898                 :     gmtime_r( pnTime, poBrokenTime );
     899                 : #else
     900                 :     struct tm   *poTime;
     901               0 :     poTime = gmtime( pnTime );
     902               0 :     memcpy( poBrokenTime, poTime, sizeof(tm) );
     903                 : #endif
     904                 : 
     905               0 :     return poBrokenTime;
     906                 : }
     907                 : 
     908                 : /************************************************************************/
     909                 : /*                             VSILocalTime()                           */
     910                 : /************************************************************************/
     911                 : 
     912               0 : struct tm *VSILocalTime( const time_t *pnTime, struct tm *poBrokenTime )
     913                 : {
     914                 : 
     915                 : #if HAVE_LOCALTIME_R
     916                 :     localtime_r( pnTime, poBrokenTime );
     917                 : #else
     918                 :     struct tm   *poTime;
     919               0 :     poTime = localtime( pnTime );
     920               0 :     memcpy( poBrokenTime, poTime, sizeof(tm) );
     921                 : #endif
     922                 : 
     923               0 :     return poBrokenTime;
     924                 : }
     925                 : 
     926                 : /************************************************************************/
     927                 : /*                            VSIStrerror()                             */
     928                 : /************************************************************************/
     929                 : 
     930              68 : char *VSIStrerror( int nErrno )
     931                 : 
     932                 : {
     933              68 :     return strerror( nErrno );
     934                 : }

Generated by: LCOV version 1.7