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 : }
|