1 : /******************************************************************************
2 : * $Id: cpl_vsisimple.cpp 23604 2011-12-19 22:49:08Z 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 : /* Uncomment to print every memory allocation or deallocation. */
52 : /* DEBUG_VSIMALLOC must also be defined */
53 : //#define DEBUG_VSIMALLOC_VERBOSE
54 :
55 : CPL_CVSID("$Id: cpl_vsisimple.cpp 23604 2011-12-19 22:49:08Z rouault $");
56 :
57 : /* for stat() */
58 :
59 : /* Unix or Windows NT/2000/XP */
60 : #if !defined(WIN32) && !defined(WIN32CE)
61 : # include <unistd.h>
62 : #elif !defined(WIN32CE) /* not Win32 platform */
63 : # include <io.h>
64 : # include <fcntl.h>
65 : # include <direct.h>
66 : #endif
67 :
68 : /* Windows CE or other platforms */
69 : #if defined(WIN32CE)
70 : # include <wce_io.h>
71 : # include <wce_stat.h>
72 : # include <wce_stdio.h>
73 : # include <wce_string.h>
74 : # include <wce_time.h>
75 : # define time wceex_time
76 : #else
77 : # include <sys/stat.h>
78 : # include <time.h>
79 : #endif
80 :
81 : /************************************************************************/
82 : /* VSIFOpen() */
83 : /************************************************************************/
84 :
85 24654 : FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
86 :
87 : {
88 24654 : FILE *fp = NULL;
89 : int nError;
90 :
91 : #if defined(WIN32) && !defined(WIN32CE)
92 : if( CSLTestBoolean(
93 : CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
94 : {
95 : wchar_t *pwszFilename =
96 : CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
97 : wchar_t *pwszAccess =
98 : CPLRecodeToWChar( pszAccess, CPL_ENC_UTF8, CPL_ENC_UCS2 );
99 :
100 : fp = _wfopen( pwszFilename, pwszAccess );
101 :
102 : CPLFree( pwszFilename );
103 : CPLFree( pwszAccess );
104 : }
105 : else
106 : #endif
107 24654 : fp = fopen( (char *) pszFilename, (char *) pszAccess );
108 :
109 24654 : nError = errno;
110 : VSIDebug3( "VSIFOpen(%s,%s) = %p", pszFilename, pszAccess, fp );
111 24654 : errno = nError;
112 :
113 24654 : return( fp );
114 : }
115 :
116 : /************************************************************************/
117 : /* VSIFClose() */
118 : /************************************************************************/
119 :
120 22170 : int VSIFClose( FILE * fp )
121 :
122 : {
123 : VSIDebug1( "VSIClose(%p)", fp );
124 :
125 22170 : return( fclose(fp) );
126 : }
127 :
128 : /************************************************************************/
129 : /* VSIFSeek() */
130 : /************************************************************************/
131 :
132 818421 : int VSIFSeek( FILE * fp, long nOffset, int nWhence )
133 :
134 : {
135 818421 : int nResult = fseek( fp, nOffset, nWhence );
136 818421 : int nError = errno;
137 :
138 : #ifdef VSI_DEBUG
139 : if( nWhence == SEEK_SET )
140 : {
141 : VSIDebug3( "VSIFSeek(%p,%ld,SEEK_SET) = %d", fp, nOffset, nResult );
142 : }
143 : else if( nWhence == SEEK_END )
144 : {
145 : VSIDebug3( "VSIFSeek(%p,%ld,SEEK_END) = %d", fp, nOffset, nResult );
146 : }
147 : else if( nWhence == SEEK_CUR )
148 : {
149 : VSIDebug3( "VSIFSeek(%p,%ld,SEEK_CUR) = %d", fp, nOffset, nResult );
150 : }
151 : else
152 : {
153 : VSIDebug4( "VSIFSeek(%p,%ld,%d-Unknown) = %d",
154 : fp, nOffset, nWhence, nResult );
155 : }
156 : #endif
157 :
158 818421 : errno = nError;
159 818421 : return nResult;
160 : }
161 :
162 : /************************************************************************/
163 : /* VSIFTell() */
164 : /************************************************************************/
165 :
166 4842031 : long VSIFTell( FILE * fp )
167 :
168 : {
169 4842031 : long nOffset = ftell(fp);
170 4842031 : int nError = errno;
171 :
172 : VSIDebug2( "VSIFTell(%p) = %ld", fp, nOffset );
173 :
174 4842031 : errno = nError;
175 4842031 : return nOffset;
176 : }
177 :
178 : /************************************************************************/
179 : /* VSIRewind() */
180 : /************************************************************************/
181 :
182 15004 : void VSIRewind( FILE * fp )
183 :
184 : {
185 : VSIDebug1("VSIRewind(%p)", fp );
186 15004 : rewind( fp );
187 15004 : }
188 :
189 : /************************************************************************/
190 : /* VSIFRead() */
191 : /************************************************************************/
192 :
193 834324 : size_t VSIFRead( void * pBuffer, size_t nSize, size_t nCount, FILE * fp )
194 :
195 : {
196 834324 : size_t nResult = fread( pBuffer, nSize, nCount, fp );
197 834324 : int nError = errno;
198 :
199 : VSIDebug4( "VSIFRead(%p,%ld,%ld) = %ld",
200 : fp, (long)nSize, (long)nCount, (long)nResult );
201 :
202 834324 : errno = nError;
203 834324 : return nResult;
204 : }
205 :
206 : /************************************************************************/
207 : /* VSIFWrite() */
208 : /************************************************************************/
209 :
210 3222 : size_t VSIFWrite( const void *pBuffer, size_t nSize, size_t nCount, FILE * fp )
211 :
212 : {
213 3222 : size_t nResult = fwrite( pBuffer, nSize, nCount, fp );
214 3222 : int nError = errno;
215 :
216 : VSIDebug4( "VSIFWrite(%p,%ld,%ld) = %ld",
217 : fp, (long)nSize, (long)nCount, (long)nResult );
218 :
219 3222 : errno = nError;
220 3222 : return nResult;
221 : }
222 :
223 : /************************************************************************/
224 : /* VSIFFlush() */
225 : /************************************************************************/
226 :
227 4 : void VSIFFlush( FILE * fp )
228 :
229 : {
230 : VSIDebug1( "VSIFFlush(%p)", fp );
231 4 : fflush( fp );
232 4 : }
233 :
234 : /************************************************************************/
235 : /* VSIFGets() */
236 : /************************************************************************/
237 :
238 2747101 : char *VSIFGets( char *pszBuffer, int nBufferSize, FILE * fp )
239 :
240 : {
241 2747101 : return( fgets( pszBuffer, nBufferSize, fp ) );
242 : }
243 :
244 : /************************************************************************/
245 : /* VSIFGetc() */
246 : /************************************************************************/
247 :
248 16742 : int VSIFGetc( FILE * fp )
249 :
250 : {
251 16742 : return( fgetc( fp ) );
252 : }
253 :
254 : /************************************************************************/
255 : /* VSIUngetc() */
256 : /************************************************************************/
257 :
258 234 : int VSIUngetc( int c, FILE * fp )
259 :
260 : {
261 234 : return( ungetc( c, fp ) );
262 : }
263 :
264 : /************************************************************************/
265 : /* VSIFPrintf() */
266 : /* */
267 : /* This is a little more complicated than just calling */
268 : /* fprintf() because of the variable arguments. Instead we */
269 : /* have to use vfprintf(). */
270 : /************************************************************************/
271 :
272 72 : int VSIFPrintf( FILE * fp, const char * pszFormat, ... )
273 :
274 : {
275 : va_list args;
276 : int nReturn;
277 :
278 72 : va_start( args, pszFormat );
279 72 : nReturn = vfprintf( fp, pszFormat, args );
280 72 : va_end( args );
281 :
282 72 : return( nReturn );
283 : }
284 :
285 : /************************************************************************/
286 : /* VSIFEof() */
287 : /************************************************************************/
288 :
289 482604 : int VSIFEof( FILE * fp )
290 :
291 : {
292 482604 : return( feof( fp ) );
293 : }
294 :
295 : /************************************************************************/
296 : /* VSIFPuts() */
297 : /************************************************************************/
298 :
299 0 : int VSIFPuts( const char * pszString, FILE * fp )
300 :
301 : {
302 0 : return fputs( pszString, fp );
303 : }
304 :
305 : /************************************************************************/
306 : /* VSIFPutc() */
307 : /************************************************************************/
308 :
309 0 : int VSIFPutc( int nChar, FILE * fp )
310 :
311 : {
312 0 : return( fputc( nChar, fp ) );
313 : }
314 :
315 :
316 : #ifdef DEBUG_VSIMALLOC_STATS
317 : #include "cpl_multiproc.h"
318 :
319 : static void* hMemStatMutex = 0;
320 : static size_t nCurrentTotalAllocs = 0;
321 : static size_t nMaxTotalAllocs = 0;
322 : static GUIntBig nVSIMallocs = 0;
323 : static GUIntBig nVSICallocs = 0;
324 : static GUIntBig nVSIReallocs = 0;
325 : static GUIntBig nVSIFrees = 0;
326 :
327 : /************************************************************************/
328 : /* VSIShowMemStats() */
329 : /************************************************************************/
330 :
331 : void VSIShowMemStats()
332 : {
333 : char* pszShowMemStats = getenv("CPL_SHOW_MEM_STATS");
334 : if (pszShowMemStats == NULL || pszShowMemStats[0] == '\0' )
335 : return;
336 : printf("Current VSI memory usage : " CPL_FRMT_GUIB " bytes\n",
337 : (GUIntBig)nCurrentTotalAllocs);
338 : printf("Maximum VSI memory usage : " CPL_FRMT_GUIB " bytes\n",
339 : (GUIntBig)nMaxTotalAllocs);
340 : printf("Number of calls to VSIMalloc() : " CPL_FRMT_GUIB "\n",
341 : nVSIMallocs);
342 : printf("Number of calls to VSICalloc() : " CPL_FRMT_GUIB "\n",
343 : nVSICallocs);
344 : printf("Number of calls to VSIRealloc() : " CPL_FRMT_GUIB "\n",
345 : nVSIReallocs);
346 : printf("Number of calls to VSIFree() : " CPL_FRMT_GUIB "\n",
347 : nVSIFrees);
348 : printf("VSIMalloc + VSICalloc - VSIFree : " CPL_FRMT_GUIB "\n",
349 : nVSIMallocs + nVSICallocs - nVSIFrees);
350 : }
351 : #endif
352 :
353 : #ifdef DEBUG_VSIMALLOC
354 : static GIntBig nMaxPeakAllocSize = -1;
355 : static GIntBig nMaxCumulAllocSize = -1;
356 : #endif
357 :
358 : /************************************************************************/
359 : /* VSICalloc() */
360 : /************************************************************************/
361 :
362 10926591 : void *VSICalloc( size_t nCount, size_t nSize )
363 :
364 : {
365 : #ifdef DEBUG_VSIMALLOC
366 : size_t nMul = nCount * nSize;
367 : if (nCount != 0 && nMul / nCount != nSize)
368 : {
369 : fprintf(stderr, "Overflow in VSICalloc(%d, %d)\n",
370 : (int)nCount, (int)nSize);
371 : return NULL;
372 : }
373 : if (nMaxPeakAllocSize < 0)
374 : {
375 : char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
376 : nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
377 : char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
378 : nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
379 : }
380 : if (nMaxPeakAllocSize > 0 && (GIntBig)nMul > nMaxPeakAllocSize)
381 : return NULL;
382 : #ifdef DEBUG_VSIMALLOC_STATS
383 : if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nMul > nMaxCumulAllocSize)
384 : return NULL;
385 : #endif
386 : char* ptr = (char*) calloc(1, 2 * sizeof(void*) + nMul);
387 : if (ptr == NULL)
388 : return NULL;
389 : ptr[0] = 'V';
390 : ptr[1] = 'S';
391 : ptr[2] = 'I';
392 : ptr[3] = 'M';
393 : memcpy(ptr + sizeof(void*), &nMul, sizeof(void*));
394 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
395 : {
396 : CPLMutexHolderD(&hMemStatMutex);
397 : #ifdef DEBUG_VSIMALLOC_VERBOSE
398 : fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p\n",
399 : (void*)CPLGetPID(), (int)nCount, (int)nSize, ptr + 2 * sizeof(void*));
400 : #endif
401 : #ifdef DEBUG_VSIMALLOC_STATS
402 : nVSICallocs ++;
403 : if (nMaxTotalAllocs == 0)
404 : atexit(VSIShowMemStats);
405 : nCurrentTotalAllocs += nMul;
406 : if (nCurrentTotalAllocs > nMaxTotalAllocs)
407 : nMaxTotalAllocs = nCurrentTotalAllocs;
408 : #endif
409 : }
410 : #endif
411 : return ptr + 2 * sizeof(void*);
412 : #else
413 10926591 : return( calloc( nCount, nSize ) );
414 : #endif
415 : }
416 :
417 : /************************************************************************/
418 : /* VSIMalloc() */
419 : /************************************************************************/
420 :
421 75697315 : void *VSIMalloc( size_t nSize )
422 :
423 : {
424 : #ifdef DEBUG_VSIMALLOC
425 : if (nMaxPeakAllocSize < 0)
426 : {
427 : char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
428 : nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
429 : char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
430 : nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
431 : }
432 : if (nMaxPeakAllocSize > 0 && (GIntBig)nSize > nMaxPeakAllocSize)
433 : return NULL;
434 : #ifdef DEBUG_VSIMALLOC_STATS
435 : if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nSize > nMaxCumulAllocSize)
436 : return NULL;
437 : #endif
438 : char* ptr = (char*) malloc(2 * sizeof(void*) + nSize);
439 : if (ptr == NULL)
440 : return NULL;
441 : ptr[0] = 'V';
442 : ptr[1] = 'S';
443 : ptr[2] = 'I';
444 : ptr[3] = 'M';
445 : memcpy(ptr + sizeof(void*), &nSize, sizeof(void*));
446 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
447 : {
448 : CPLMutexHolderD(&hMemStatMutex);
449 : #ifdef DEBUG_VSIMALLOC_VERBOSE
450 : fprintf(stderr, "Thread[%p] VSIMalloc(%d) = %p\n",
451 : (void*)CPLGetPID(), (int)nSize, ptr + 2 * sizeof(void*));
452 : #endif
453 : #ifdef DEBUG_VSIMALLOC_STATS
454 : nVSIMallocs ++;
455 : if (nMaxTotalAllocs == 0)
456 : atexit(VSIShowMemStats);
457 : nCurrentTotalAllocs += nSize;
458 : if (nCurrentTotalAllocs > nMaxTotalAllocs)
459 : nMaxTotalAllocs = nCurrentTotalAllocs;
460 : #endif
461 : }
462 : #endif
463 : return ptr + 2 * sizeof(void*);
464 : #else
465 75697315 : return( malloc( nSize ) );
466 : #endif
467 : }
468 :
469 : #ifdef DEBUG_VSIMALLOC
470 : void VSICheckMarker(char* ptr)
471 : {
472 : if (memcmp(ptr, "VSIM", 4) != 0)
473 : {
474 : CPLError(CE_Fatal, CPLE_AppDefined,
475 : "Inconsistant use of VSI memory allocation primitives for %p : %c%c%c%c",
476 : ptr, ptr[0], ptr[1], ptr[2], ptr[3]);
477 : }
478 : }
479 :
480 : #endif
481 :
482 : /************************************************************************/
483 : /* VSIRealloc() */
484 : /************************************************************************/
485 :
486 29036810 : void * VSIRealloc( void * pData, size_t nNewSize )
487 :
488 : {
489 : #ifdef DEBUG_VSIMALLOC
490 : if (pData == NULL)
491 : return VSIMalloc(nNewSize);
492 :
493 : char* ptr = ((char*)pData) - 2 * sizeof(void*);
494 : VSICheckMarker(ptr);
495 : #ifdef DEBUG_VSIMALLOC_STATS
496 : size_t nOldSize;
497 : memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
498 : #endif
499 :
500 : if (nMaxPeakAllocSize < 0)
501 : {
502 : char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
503 : nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
504 : }
505 : if (nMaxPeakAllocSize > 0 && (GIntBig)nNewSize > nMaxPeakAllocSize)
506 : return NULL;
507 : #ifdef DEBUG_VSIMALLOC_STATS
508 : if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nNewSize - (GIntBig)nOldSize > nMaxCumulAllocSize)
509 : return NULL;
510 : #endif
511 :
512 : void* newptr = realloc(ptr, nNewSize + 2 * sizeof(void*));
513 : if (newptr == NULL)
514 : return NULL;
515 : ptr = (char*) newptr;
516 : memcpy(ptr + sizeof(void*), &nNewSize, sizeof(void*));
517 :
518 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
519 : {
520 : CPLMutexHolderD(&hMemStatMutex);
521 : #ifdef DEBUG_VSIMALLOC_VERBOSE
522 : fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p\n",
523 : (void*)CPLGetPID(), pData, (int)nNewSize, ptr + 2 * sizeof(void*));
524 : #endif
525 : #ifdef DEBUG_VSIMALLOC_STATS
526 : nVSIReallocs ++;
527 : nCurrentTotalAllocs -= nOldSize;
528 : nCurrentTotalAllocs += nNewSize;
529 : if (nCurrentTotalAllocs > nMaxTotalAllocs)
530 : nMaxTotalAllocs = nCurrentTotalAllocs;
531 : #endif
532 : }
533 : #endif
534 : return ptr + 2 * sizeof(void*);
535 : #else
536 29036810 : return( realloc( pData, nNewSize ) );
537 : #endif
538 : }
539 :
540 : /************************************************************************/
541 : /* VSIFree() */
542 : /************************************************************************/
543 :
544 121518093 : void VSIFree( void * pData )
545 :
546 : {
547 : #ifdef DEBUG_VSIMALLOC
548 : if (pData == NULL)
549 : return;
550 :
551 : char* ptr = ((char*)pData) - 2 * sizeof(void*);
552 : VSICheckMarker(ptr);
553 : ptr[0] = 'M';
554 : ptr[1] = 'I';
555 : ptr[2] = 'S';
556 : ptr[3] = 'V';
557 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
558 : size_t nOldSize;
559 : memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
560 : {
561 : CPLMutexHolderD(&hMemStatMutex);
562 : #ifdef DEBUG_VSIMALLOC_VERBOSE
563 : fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n",
564 : (void*)CPLGetPID(), pData, (int)nOldSize);
565 : #endif
566 : #ifdef DEBUG_VSIMALLOC_STATS
567 : nVSIFrees ++;
568 : nCurrentTotalAllocs -= nOldSize;
569 : #endif
570 : }
571 : #endif
572 : free(ptr);
573 : #else
574 121518093 : if( pData != NULL )
575 98046879 : free( pData );
576 : #endif
577 121518093 : }
578 :
579 : /************************************************************************/
580 : /* VSIStrdup() */
581 : /************************************************************************/
582 :
583 9878577 : char *VSIStrdup( const char * pszString )
584 :
585 : {
586 : #ifdef DEBUG_VSIMALLOC
587 : int nSize = strlen(pszString) + 1;
588 : char* ptr = (char*) VSIMalloc(nSize);
589 : if (ptr == NULL)
590 : return NULL;
591 : memcpy(ptr, pszString, nSize);
592 : return ptr;
593 : #else
594 9878577 : return( strdup( pszString ) );
595 : #endif
596 : }
597 :
598 : /************************************************************************/
599 : /* VSICheckMul2() */
600 : /************************************************************************/
601 :
602 51209 : static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag)
603 : {
604 51209 : size_t res = mul1 * mul2;
605 51209 : if (mul1 != 0)
606 : {
607 51207 : if (res / mul1 == mul2)
608 : {
609 51207 : if (pbOverflowFlag)
610 51207 : *pbOverflowFlag = FALSE;
611 51207 : return res;
612 : }
613 : else
614 : {
615 0 : if (pbOverflowFlag)
616 0 : *pbOverflowFlag = TRUE;
617 : CPLError(CE_Failure, CPLE_OutOfMemory,
618 : "Multiplication overflow : %lu * %lu",
619 0 : (unsigned long)mul1, (unsigned long)mul2);
620 : }
621 : }
622 : else
623 : {
624 2 : if (pbOverflowFlag)
625 2 : *pbOverflowFlag = FALSE;
626 : }
627 2 : return 0;
628 : }
629 :
630 : /************************************************************************/
631 : /* VSICheckMul3() */
632 : /************************************************************************/
633 :
634 31264 : static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverflowFlag)
635 : {
636 31264 : if (mul1 != 0)
637 : {
638 31264 : size_t res = mul1 * mul2;
639 31264 : if (res / mul1 == mul2)
640 : {
641 31264 : size_t res2 = res * mul3;
642 31264 : if (mul3 != 0)
643 : {
644 31264 : if (res2 / mul3 == res)
645 : {
646 31264 : if (pbOverflowFlag)
647 31264 : *pbOverflowFlag = FALSE;
648 31264 : return res2;
649 : }
650 : else
651 : {
652 0 : if (pbOverflowFlag)
653 0 : *pbOverflowFlag = TRUE;
654 : CPLError(CE_Failure, CPLE_OutOfMemory,
655 : "Multiplication overflow : %lu * %lu * %lu",
656 0 : (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
657 : }
658 : }
659 : else
660 : {
661 0 : if (pbOverflowFlag)
662 0 : *pbOverflowFlag = FALSE;
663 : }
664 : }
665 : else
666 : {
667 0 : if (pbOverflowFlag)
668 0 : *pbOverflowFlag = TRUE;
669 : CPLError(CE_Failure, CPLE_OutOfMemory,
670 : "Multiplication overflow : %lu * %lu * %lu",
671 0 : (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
672 : }
673 : }
674 : else
675 : {
676 0 : if (pbOverflowFlag)
677 0 : *pbOverflowFlag = FALSE;
678 : }
679 0 : return 0;
680 : }
681 :
682 :
683 :
684 : /**
685 : VSIMalloc2 allocates (nSize1 * nSize2) bytes.
686 : In case of overflow of the multiplication, or if memory allocation fails, a
687 : NULL pointer is returned and a CE_Failure error is raised with CPLError().
688 : If nSize1 == 0 || nSize2 == 0, a NULL pointer will also be returned.
689 : CPLFree() or VSIFree() can be used to free memory allocated by this function.
690 : */
691 51209 : void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 )
692 : {
693 51209 : int bOverflowFlag = FALSE;
694 : size_t nSizeToAllocate;
695 : void* pReturn;
696 :
697 51209 : nSizeToAllocate = VSICheckMul2( nSize1, nSize2, &bOverflowFlag );
698 51209 : if (bOverflowFlag)
699 0 : return NULL;
700 :
701 51209 : if (nSizeToAllocate == 0)
702 130 : return NULL;
703 :
704 51079 : pReturn = VSIMalloc(nSizeToAllocate);
705 :
706 51079 : if( pReturn == NULL )
707 : {
708 : CPLError( CE_Failure, CPLE_OutOfMemory,
709 : "VSIMalloc2(): Out of memory allocating %lu bytes.\n",
710 0 : (unsigned long)nSizeToAllocate );
711 : }
712 :
713 51079 : return pReturn;
714 : }
715 :
716 : /**
717 : VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.
718 : In case of overflow of the multiplication, or if memory allocation fails, a
719 : NULL pointer is returned and a CE_Failure error is raised with CPLError().
720 : If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.
721 : CPLFree() or VSIFree() can be used to free memory allocated by this function.
722 : */
723 31264 : void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 )
724 : {
725 31264 : int bOverflowFlag = FALSE;
726 :
727 : size_t nSizeToAllocate;
728 : void* pReturn;
729 :
730 31264 : nSizeToAllocate = VSICheckMul3( nSize1, nSize2, nSize3, &bOverflowFlag );
731 31264 : if (bOverflowFlag)
732 0 : return NULL;
733 :
734 31264 : if (nSizeToAllocate == 0)
735 0 : return NULL;
736 :
737 31264 : pReturn = VSIMalloc(nSizeToAllocate);
738 :
739 31264 : if( pReturn == NULL )
740 : {
741 : CPLError( CE_Failure, CPLE_OutOfMemory,
742 : "VSIMalloc3(): Out of memory allocating %lu bytes.\n",
743 0 : (unsigned long)nSizeToAllocate );
744 : }
745 :
746 31264 : return pReturn;
747 : }
748 :
749 :
750 : /************************************************************************/
751 : /* VSIStat() */
752 : /************************************************************************/
753 :
754 10256 : int VSIStat( const char * pszFilename, VSIStatBuf * pStatBuf )
755 :
756 : {
757 : #if defined(WIN32) && !defined(WIN32CE)
758 : if( CSLTestBoolean(
759 : CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
760 : {
761 : int nResult;
762 : wchar_t *pwszFilename =
763 : CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
764 :
765 : nResult = _wstat( pwszFilename, (struct _stat *) pStatBuf );
766 :
767 : CPLFree( pwszFilename );
768 :
769 : return nResult;
770 : }
771 : else
772 : #endif
773 10256 : return( stat( pszFilename, pStatBuf ) );
774 : }
775 :
776 : /************************************************************************/
777 : /* VSITime() */
778 : /************************************************************************/
779 :
780 0 : unsigned long VSITime( unsigned long * pnTimeToSet )
781 :
782 : {
783 : time_t tTime;
784 :
785 0 : tTime = time( NULL );
786 :
787 0 : if( pnTimeToSet != NULL )
788 0 : *pnTimeToSet = (unsigned long) tTime;
789 :
790 0 : return (unsigned long) tTime;
791 : }
792 :
793 : /************************************************************************/
794 : /* VSICTime() */
795 : /************************************************************************/
796 :
797 0 : const char *VSICTime( unsigned long nTime )
798 :
799 : {
800 0 : time_t tTime = (time_t) nTime;
801 :
802 0 : return (const char *) ctime( &tTime );
803 : }
804 :
805 : /************************************************************************/
806 : /* VSIGMTime() */
807 : /************************************************************************/
808 :
809 0 : struct tm *VSIGMTime( const time_t *pnTime, struct tm *poBrokenTime )
810 : {
811 :
812 : #if HAVE_GMTIME_R
813 : gmtime_r( pnTime, poBrokenTime );
814 : #else
815 : struct tm *poTime;
816 0 : poTime = gmtime( pnTime );
817 0 : memcpy( poBrokenTime, poTime, sizeof(tm) );
818 : #endif
819 :
820 0 : return poBrokenTime;
821 : }
822 :
823 : /************************************************************************/
824 : /* VSILocalTime() */
825 : /************************************************************************/
826 :
827 0 : struct tm *VSILocalTime( const time_t *pnTime, struct tm *poBrokenTime )
828 : {
829 :
830 : #if HAVE_LOCALTIME_R
831 : localtime_r( pnTime, poBrokenTime );
832 : #else
833 : struct tm *poTime;
834 0 : poTime = localtime( pnTime );
835 0 : memcpy( poBrokenTime, poTime, sizeof(tm) );
836 : #endif
837 :
838 0 : return poBrokenTime;
839 : }
840 :
841 : /************************************************************************/
842 : /* VSIStrerror() */
843 : /************************************************************************/
844 :
845 32 : char *VSIStrerror( int nErrno )
846 :
847 : {
848 32 : return strerror( nErrno );
849 : }
|