1 : /******************************************************************************
2 : * $Id: cpl_vsisimple.cpp 25359 2012-12-27 15:19:28Z 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 25359 2012-12-27 15:19:28Z 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 13800 : FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
94 :
95 : {
96 13800 : 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 13800 : fp = fopen( (char *) pszFilename, (char *) pszAccess );
116 :
117 13800 : nError = errno;
118 : VSIDebug3( "VSIFOpen(%s,%s) = %p", pszFilename, pszAccess, fp );
119 13800 : errno = nError;
120 :
121 13800 : return( fp );
122 : }
123 :
124 : /************************************************************************/
125 : /* VSIFClose() */
126 : /************************************************************************/
127 :
128 12186 : int VSIFClose( FILE * fp )
129 :
130 : {
131 : VSIDebug1( "VSIClose(%p)", fp );
132 :
133 12186 : return( fclose(fp) );
134 : }
135 :
136 : /************************************************************************/
137 : /* VSIFSeek() */
138 : /************************************************************************/
139 :
140 407868 : int VSIFSeek( FILE * fp, long nOffset, int nWhence )
141 :
142 : {
143 407868 : int nResult = fseek( fp, nOffset, nWhence );
144 407868 : 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 407868 : errno = nError;
167 407868 : return nResult;
168 : }
169 :
170 : /************************************************************************/
171 : /* VSIFTell() */
172 : /************************************************************************/
173 :
174 2518216 : long VSIFTell( FILE * fp )
175 :
176 : {
177 2518216 : long nOffset = ftell(fp);
178 2518216 : int nError = errno;
179 :
180 : VSIDebug2( "VSIFTell(%p) = %ld", fp, nOffset );
181 :
182 2518216 : errno = nError;
183 2518216 : return nOffset;
184 : }
185 :
186 : /************************************************************************/
187 : /* VSIRewind() */
188 : /************************************************************************/
189 :
190 7809 : void VSIRewind( FILE * fp )
191 :
192 : {
193 : VSIDebug1("VSIRewind(%p)", fp );
194 7809 : rewind( fp );
195 7809 : }
196 :
197 : /************************************************************************/
198 : /* VSIFRead() */
199 : /************************************************************************/
200 :
201 416646 : size_t VSIFRead( void * pBuffer, size_t nSize, size_t nCount, FILE * fp )
202 :
203 : {
204 416646 : size_t nResult = fread( pBuffer, nSize, nCount, fp );
205 416646 : int nError = errno;
206 :
207 : VSIDebug4( "VSIFRead(%p,%ld,%ld) = %ld",
208 : fp, (long)nSize, (long)nCount, (long)nResult );
209 :
210 416646 : errno = nError;
211 416646 : 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 1470621 : char *VSIFGets( char *pszBuffer, int nBufferSize, FILE * fp )
247 :
248 : {
249 1470621 : 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 5706415 : 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 5706415 : return( calloc( nCount, nSize ) );
442 : #endif
443 : }
444 :
445 : /************************************************************************/
446 : /* VSIMalloc() */
447 : /************************************************************************/
448 :
449 45026945 : 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 45026945 : 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 17059012 : 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 : {
570 : ptr[2 * sizeof(void*) + nOldSize + 0] = 'E';
571 : ptr[2 * sizeof(void*) + nOldSize + 1] = 'V';
572 : ptr[2 * sizeof(void*) + nOldSize + 2] = 'S';
573 : ptr[2 * sizeof(void*) + nOldSize + 3] = 'I';
574 : return NULL;
575 : }
576 : memcpy(newptr + 2 * sizeof(void*), pData, nOldSize);
577 : ptr[0] = 'M';
578 : ptr[1] = 'I';
579 : ptr[2] = 'S';
580 : ptr[3] = 'V';
581 : free(ptr);
582 : newptr[0] = 'V';
583 : newptr[1] = 'S';
584 : newptr[2] = 'I';
585 : newptr[3] = 'M';
586 : #else
587 : void* newptr = realloc(ptr, nNewSize + 3 * sizeof(void*));
588 : if (newptr == NULL)
589 : {
590 : ptr[2 * sizeof(void*) + nOldSize + 0] = 'E';
591 : ptr[2 * sizeof(void*) + nOldSize + 1] = 'V';
592 : ptr[2 * sizeof(void*) + nOldSize + 2] = 'S';
593 : ptr[2 * sizeof(void*) + nOldSize + 3] = 'I';
594 : return NULL;
595 : }
596 : #endif
597 : ptr = (char*) newptr;
598 : memcpy(ptr + sizeof(void*), &nNewSize, sizeof(void*));
599 : ptr[2 * sizeof(void*) + nNewSize + 0] = 'E';
600 : ptr[2 * sizeof(void*) + nNewSize + 1] = 'V';
601 : ptr[2 * sizeof(void*) + nNewSize + 2] = 'S';
602 : ptr[2 * sizeof(void*) + nNewSize + 3] = 'I';
603 :
604 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
605 : {
606 : CPLMutexHolderD(&hMemStatMutex);
607 : #ifdef DEBUG_VSIMALLOC_VERBOSE
608 : fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p\n",
609 : (void*)CPLGetPID(), pData, (int)nNewSize, ptr + 2 * sizeof(void*));
610 : #endif
611 : #ifdef DEBUG_VSIMALLOC_STATS
612 : nVSIReallocs ++;
613 : nCurrentTotalAllocs -= nOldSize;
614 : nCurrentTotalAllocs += nNewSize;
615 : if (nCurrentTotalAllocs > nMaxTotalAllocs)
616 : nMaxTotalAllocs = nCurrentTotalAllocs;
617 : #endif
618 : }
619 : #endif
620 : return ptr + 2 * sizeof(void*);
621 : #else
622 17059012 : return( realloc( pData, nNewSize ) );
623 : #endif
624 : }
625 :
626 : /************************************************************************/
627 : /* VSIFree() */
628 : /************************************************************************/
629 :
630 70612806 : void VSIFree( void * pData )
631 :
632 : {
633 : #ifdef DEBUG_VSIMALLOC
634 : if (pData == NULL)
635 : return;
636 :
637 : char* ptr = ((char*)pData) - 2 * sizeof(void*);
638 : VSICheckMarkerBegin(ptr);
639 : size_t nOldSize;
640 : memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
641 : VSICheckMarkerEnd(ptr, 2 * sizeof(void*) + nOldSize);
642 : ptr[0] = 'M';
643 : ptr[1] = 'I';
644 : ptr[2] = 'S';
645 : ptr[3] = 'V';
646 : ptr[2 * sizeof(void*) + nOldSize + 0] = 'I';
647 : ptr[2 * sizeof(void*) + nOldSize + 1] = 'S';
648 : ptr[2 * sizeof(void*) + nOldSize + 2] = 'V';
649 : ptr[2 * sizeof(void*) + nOldSize + 3] = 'E';
650 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
651 : {
652 : CPLMutexHolderD(&hMemStatMutex);
653 : #ifdef DEBUG_VSIMALLOC_VERBOSE
654 : fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n",
655 : (void*)CPLGetPID(), pData, (int)nOldSize);
656 : #endif
657 : #ifdef DEBUG_VSIMALLOC_STATS
658 : nVSIFrees ++;
659 : nCurrentTotalAllocs -= nOldSize;
660 : #endif
661 : }
662 : #endif
663 :
664 : #ifdef DEBUG_VSIMALLOC_MPROTECT
665 : mprotect(ptr, nOldSize + 2 * sizeof(void*), PROT_NONE);
666 : #else
667 : free(ptr);
668 : #endif
669 :
670 : #else
671 70612806 : if( pData != NULL )
672 56732325 : free( pData );
673 : #endif
674 70612806 : }
675 :
676 : /************************************************************************/
677 : /* VSIStrdup() */
678 : /************************************************************************/
679 :
680 5046433 : char *VSIStrdup( const char * pszString )
681 :
682 : {
683 : #ifdef DEBUG_VSIMALLOC
684 : int nSize = strlen(pszString) + 1;
685 : char* ptr = (char*) VSIMalloc(nSize);
686 : if (ptr == NULL)
687 : return NULL;
688 : memcpy(ptr, pszString, nSize);
689 : return ptr;
690 : #else
691 5046433 : return( strdup( pszString ) );
692 : #endif
693 : }
694 :
695 : /************************************************************************/
696 : /* VSICheckMul2() */
697 : /************************************************************************/
698 :
699 32784 : static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag)
700 : {
701 32784 : size_t res = mul1 * mul2;
702 32784 : if (mul1 != 0)
703 : {
704 32783 : if (res / mul1 == mul2)
705 : {
706 32783 : if (pbOverflowFlag)
707 32783 : *pbOverflowFlag = FALSE;
708 32783 : return res;
709 : }
710 : else
711 : {
712 0 : if (pbOverflowFlag)
713 0 : *pbOverflowFlag = TRUE;
714 : CPLError(CE_Failure, CPLE_OutOfMemory,
715 : "Multiplication overflow : %lu * %lu",
716 0 : (unsigned long)mul1, (unsigned long)mul2);
717 : }
718 : }
719 : else
720 : {
721 1 : if (pbOverflowFlag)
722 1 : *pbOverflowFlag = FALSE;
723 : }
724 1 : return 0;
725 : }
726 :
727 : /************************************************************************/
728 : /* VSICheckMul3() */
729 : /************************************************************************/
730 :
731 15862 : static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverflowFlag)
732 : {
733 15862 : if (mul1 != 0)
734 : {
735 15862 : size_t res = mul1 * mul2;
736 15862 : if (res / mul1 == mul2)
737 : {
738 15862 : size_t res2 = res * mul3;
739 15862 : if (mul3 != 0)
740 : {
741 15862 : if (res2 / mul3 == res)
742 : {
743 15860 : if (pbOverflowFlag)
744 15860 : *pbOverflowFlag = FALSE;
745 15860 : return res2;
746 : }
747 : else
748 : {
749 2 : if (pbOverflowFlag)
750 2 : *pbOverflowFlag = TRUE;
751 : CPLError(CE_Failure, CPLE_OutOfMemory,
752 : "Multiplication overflow : %lu * %lu * %lu",
753 2 : (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
754 : }
755 : }
756 : else
757 : {
758 0 : if (pbOverflowFlag)
759 0 : *pbOverflowFlag = FALSE;
760 : }
761 : }
762 : else
763 : {
764 0 : if (pbOverflowFlag)
765 0 : *pbOverflowFlag = TRUE;
766 : CPLError(CE_Failure, CPLE_OutOfMemory,
767 : "Multiplication overflow : %lu * %lu * %lu",
768 0 : (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
769 : }
770 : }
771 : else
772 : {
773 0 : if (pbOverflowFlag)
774 0 : *pbOverflowFlag = FALSE;
775 : }
776 2 : return 0;
777 : }
778 :
779 :
780 :
781 : /**
782 : VSIMalloc2 allocates (nSize1 * nSize2) bytes.
783 : In case of overflow of the multiplication, or if memory allocation fails, a
784 : NULL pointer is returned and a CE_Failure error is raised with CPLError().
785 : If nSize1 == 0 || nSize2 == 0, a NULL pointer will also be returned.
786 : CPLFree() or VSIFree() can be used to free memory allocated by this function.
787 : */
788 32785 : void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 )
789 : {
790 32785 : int bOverflowFlag = FALSE;
791 : size_t nSizeToAllocate;
792 : void* pReturn;
793 :
794 32785 : nSizeToAllocate = VSICheckMul2( nSize1, nSize2, &bOverflowFlag );
795 32784 : if (bOverflowFlag)
796 0 : return NULL;
797 :
798 32784 : if (nSizeToAllocate == 0)
799 86 : return NULL;
800 :
801 32698 : pReturn = VSIMalloc(nSizeToAllocate);
802 :
803 32699 : if( pReturn == NULL )
804 : {
805 : CPLError( CE_Failure, CPLE_OutOfMemory,
806 : "VSIMalloc2(): Out of memory allocating %lu bytes.\n",
807 0 : (unsigned long)nSizeToAllocate );
808 : }
809 :
810 32699 : return pReturn;
811 : }
812 :
813 : /**
814 : VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.
815 : In case of overflow of the multiplication, or if memory allocation fails, a
816 : NULL pointer is returned and a CE_Failure error is raised with CPLError().
817 : If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.
818 : CPLFree() or VSIFree() can be used to free memory allocated by this function.
819 : */
820 15862 : void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 )
821 : {
822 15862 : int bOverflowFlag = FALSE;
823 :
824 : size_t nSizeToAllocate;
825 : void* pReturn;
826 :
827 15862 : nSizeToAllocate = VSICheckMul3( nSize1, nSize2, nSize3, &bOverflowFlag );
828 15862 : if (bOverflowFlag)
829 2 : return NULL;
830 :
831 15860 : if (nSizeToAllocate == 0)
832 0 : return NULL;
833 :
834 15860 : pReturn = VSIMalloc(nSizeToAllocate);
835 :
836 15860 : if( pReturn == NULL )
837 : {
838 : CPLError( CE_Failure, CPLE_OutOfMemory,
839 : "VSIMalloc3(): Out of memory allocating %lu bytes.\n",
840 0 : (unsigned long)nSizeToAllocate );
841 : }
842 :
843 15860 : return pReturn;
844 : }
845 :
846 :
847 : /************************************************************************/
848 : /* VSIStat() */
849 : /************************************************************************/
850 :
851 6028 : int VSIStat( const char * pszFilename, VSIStatBuf * pStatBuf )
852 :
853 : {
854 : #if defined(WIN32) && !defined(WIN32CE)
855 : if( CSLTestBoolean(
856 : CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
857 : {
858 : int nResult;
859 : wchar_t *pwszFilename =
860 : CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
861 :
862 : nResult = _wstat( pwszFilename, (struct _stat *) pStatBuf );
863 :
864 : CPLFree( pwszFilename );
865 :
866 : return nResult;
867 : }
868 : else
869 : #endif
870 6028 : return( stat( pszFilename, pStatBuf ) );
871 : }
872 :
873 : /************************************************************************/
874 : /* VSITime() */
875 : /************************************************************************/
876 :
877 0 : unsigned long VSITime( unsigned long * pnTimeToSet )
878 :
879 : {
880 : time_t tTime;
881 :
882 0 : tTime = time( NULL );
883 :
884 0 : if( pnTimeToSet != NULL )
885 0 : *pnTimeToSet = (unsigned long) tTime;
886 :
887 0 : return (unsigned long) tTime;
888 : }
889 :
890 : /************************************************************************/
891 : /* VSICTime() */
892 : /************************************************************************/
893 :
894 0 : const char *VSICTime( unsigned long nTime )
895 :
896 : {
897 0 : time_t tTime = (time_t) nTime;
898 :
899 0 : return (const char *) ctime( &tTime );
900 : }
901 :
902 : /************************************************************************/
903 : /* VSIGMTime() */
904 : /************************************************************************/
905 :
906 0 : struct tm *VSIGMTime( const time_t *pnTime, struct tm *poBrokenTime )
907 : {
908 :
909 : #if HAVE_GMTIME_R
910 : gmtime_r( pnTime, poBrokenTime );
911 : #else
912 : struct tm *poTime;
913 0 : poTime = gmtime( pnTime );
914 0 : memcpy( poBrokenTime, poTime, sizeof(tm) );
915 : #endif
916 :
917 0 : return poBrokenTime;
918 : }
919 :
920 : /************************************************************************/
921 : /* VSILocalTime() */
922 : /************************************************************************/
923 :
924 0 : struct tm *VSILocalTime( const time_t *pnTime, struct tm *poBrokenTime )
925 : {
926 :
927 : #if HAVE_LOCALTIME_R
928 : localtime_r( pnTime, poBrokenTime );
929 : #else
930 : struct tm *poTime;
931 0 : poTime = localtime( pnTime );
932 0 : memcpy( poBrokenTime, poTime, sizeof(tm) );
933 : #endif
934 :
935 0 : return poBrokenTime;
936 : }
937 :
938 : /************************************************************************/
939 : /* VSIStrerror() */
940 : /************************************************************************/
941 :
942 70 : char *VSIStrerror( int nErrno )
943 :
944 : {
945 70 : return strerror( nErrno );
946 : }
|