1 : /******************************************************************************
2 : * $Id: cpl_vsisimple.cpp 23430 2011-11-27 12:55:17Z 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 23430 2011-11-27 12:55:17Z 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 36079 : FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
86 :
87 : {
88 36079 : 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 36079 : fp = fopen( (char *) pszFilename, (char *) pszAccess );
108 :
109 36079 : nError = errno;
110 : VSIDebug3( "VSIFOpen(%s,%s) = %p", pszFilename, pszAccess, fp );
111 36079 : errno = nError;
112 :
113 36079 : return( fp );
114 : }
115 :
116 : /************************************************************************/
117 : /* VSIFClose() */
118 : /************************************************************************/
119 :
120 34520 : int VSIFClose( FILE * fp )
121 :
122 : {
123 : VSIDebug1( "VSIClose(%p)", fp );
124 :
125 34520 : return( fclose(fp) );
126 : }
127 :
128 : /************************************************************************/
129 : /* VSIFSeek() */
130 : /************************************************************************/
131 :
132 2049890 : int VSIFSeek( FILE * fp, long nOffset, int nWhence )
133 :
134 : {
135 2049890 : int nResult = fseek( fp, nOffset, nWhence );
136 2049890 : 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 2049890 : errno = nError;
159 2049890 : return nResult;
160 : }
161 :
162 : /************************************************************************/
163 : /* VSIFTell() */
164 : /************************************************************************/
165 :
166 2425669 : long VSIFTell( FILE * fp )
167 :
168 : {
169 2425669 : long nOffset = ftell(fp);
170 2425669 : int nError = errno;
171 :
172 : VSIDebug2( "VSIFTell(%p) = %ld", fp, nOffset );
173 :
174 2425669 : errno = nError;
175 2425669 : return nOffset;
176 : }
177 :
178 : /************************************************************************/
179 : /* VSIRewind() */
180 : /************************************************************************/
181 :
182 7188 : void VSIRewind( FILE * fp )
183 :
184 : {
185 : VSIDebug1("VSIRewind(%p)", fp );
186 7188 : rewind( fp );
187 7188 : }
188 :
189 : /************************************************************************/
190 : /* VSIFRead() */
191 : /************************************************************************/
192 :
193 2085012 : size_t VSIFRead( void * pBuffer, size_t nSize, size_t nCount, FILE * fp )
194 :
195 : {
196 2085012 : size_t nResult = fread( pBuffer, nSize, nCount, fp );
197 2085012 : int nError = errno;
198 :
199 : VSIDebug4( "VSIFRead(%p,%ld,%ld) = %ld",
200 : fp, (long)nSize, (long)nCount, (long)nResult );
201 :
202 2085012 : errno = nError;
203 2085012 : return nResult;
204 : }
205 :
206 : /************************************************************************/
207 : /* VSIFWrite() */
208 : /************************************************************************/
209 :
210 321782 : size_t VSIFWrite( const void *pBuffer, size_t nSize, size_t nCount, FILE * fp )
211 :
212 : {
213 321782 : size_t nResult = fwrite( pBuffer, nSize, nCount, fp );
214 321782 : int nError = errno;
215 :
216 : VSIDebug4( "VSIFWrite(%p,%ld,%ld) = %ld",
217 : fp, (long)nSize, (long)nCount, (long)nResult );
218 :
219 321782 : errno = nError;
220 321782 : return nResult;
221 : }
222 :
223 : /************************************************************************/
224 : /* VSIFFlush() */
225 : /************************************************************************/
226 :
227 2 : void VSIFFlush( FILE * fp )
228 :
229 : {
230 : VSIDebug1( "VSIFFlush(%p)", fp );
231 2 : fflush( fp );
232 2 : }
233 :
234 : /************************************************************************/
235 : /* VSIFGets() */
236 : /************************************************************************/
237 :
238 1377891 : char *VSIFGets( char *pszBuffer, int nBufferSize, FILE * fp )
239 :
240 : {
241 1377891 : return( fgets( pszBuffer, nBufferSize, fp ) );
242 : }
243 :
244 : /************************************************************************/
245 : /* VSIFGetc() */
246 : /************************************************************************/
247 :
248 8371 : int VSIFGetc( FILE * fp )
249 :
250 : {
251 8371 : return( fgetc( fp ) );
252 : }
253 :
254 : /************************************************************************/
255 : /* VSIUngetc() */
256 : /************************************************************************/
257 :
258 117 : int VSIUngetc( int c, FILE * fp )
259 :
260 : {
261 117 : 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 36 : int VSIFPrintf( FILE * fp, const char * pszFormat, ... )
273 :
274 : {
275 : va_list args;
276 : int nReturn;
277 :
278 36 : va_start( args, pszFormat );
279 36 : nReturn = vfprintf( fp, pszFormat, args );
280 36 : va_end( args );
281 :
282 36 : return( nReturn );
283 : }
284 :
285 : /************************************************************************/
286 : /* VSIFEof() */
287 : /************************************************************************/
288 :
289 241284 : int VSIFEof( FILE * fp )
290 :
291 : {
292 241284 : 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 : if (getenv("CPL_SHOW_MEM_STATS") == NULL)
334 : return;
335 : printf("Current VSI memory usage : " CPL_FRMT_GUIB " bytes\n",
336 : (GUIntBig)nCurrentTotalAllocs);
337 : printf("Maximum VSI memory usage : " CPL_FRMT_GUIB " bytes\n",
338 : (GUIntBig)nMaxTotalAllocs);
339 : printf("Number of calls to VSIMalloc() : " CPL_FRMT_GUIB "\n",
340 : nVSIMallocs);
341 : printf("Number of calls to VSICalloc() : " CPL_FRMT_GUIB "\n",
342 : nVSICallocs);
343 : printf("Number of calls to VSIRealloc() : " CPL_FRMT_GUIB "\n",
344 : nVSIReallocs);
345 : printf("Number of calls to VSIFree() : " CPL_FRMT_GUIB "\n",
346 : nVSIFrees);
347 : printf("VSIMalloc + VSICalloc - VSIFree : " CPL_FRMT_GUIB "\n",
348 : nVSIMallocs + nVSICallocs - nVSIFrees);
349 : }
350 : #endif
351 :
352 : #ifdef DEBUG_VSIMALLOC
353 : static GIntBig nMaxPeakAllocSize = -1;
354 : static GIntBig nMaxCumulAllocSize = -1;
355 : #endif
356 :
357 : /************************************************************************/
358 : /* VSICalloc() */
359 : /************************************************************************/
360 :
361 5231987 : void *VSICalloc( size_t nCount, size_t nSize )
362 :
363 : {
364 : #ifdef DEBUG_VSIMALLOC
365 : size_t nMul = nCount * nSize;
366 : if (nCount != 0 && nMul / nCount != nSize)
367 : {
368 : fprintf(stderr, "Overflow in VSICalloc(%d, %d)\n",
369 : (int)nCount, (int)nSize);
370 : return NULL;
371 : }
372 : if (nMaxPeakAllocSize < 0)
373 : {
374 : char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
375 : nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
376 : char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
377 : nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
378 : }
379 : if (nMaxPeakAllocSize > 0 && (GIntBig)nMul > nMaxPeakAllocSize)
380 : return NULL;
381 : #ifdef DEBUG_VSIMALLOC_STATS
382 : if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nMul > nMaxCumulAllocSize)
383 : return NULL;
384 : #endif
385 : char* ptr = (char*) calloc(1, 2 * sizeof(void*) + nMul);
386 : if (ptr == NULL)
387 : return NULL;
388 : ptr[0] = 'V';
389 : ptr[1] = 'S';
390 : ptr[2] = 'I';
391 : ptr[3] = 'M';
392 : memcpy(ptr + sizeof(void*), &nMul, sizeof(void*));
393 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
394 : {
395 : CPLMutexHolderD(&hMemStatMutex);
396 : #ifdef DEBUG_VSIMALLOC_VERBOSE
397 : fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p\n",
398 : (void*)CPLGetPID(), (int)nCount, (int)nSize, ptr + 2 * sizeof(void*));
399 : #endif
400 : #ifdef DEBUG_VSIMALLOC_STATS
401 : nVSICallocs ++;
402 : if (nMaxTotalAllocs == 0)
403 : atexit(VSIShowMemStats);
404 : nCurrentTotalAllocs += nMul;
405 : if (nCurrentTotalAllocs > nMaxTotalAllocs)
406 : nMaxTotalAllocs = nCurrentTotalAllocs;
407 : #endif
408 : }
409 : #endif
410 : return ptr + 2 * sizeof(void*);
411 : #else
412 5231987 : return( calloc( nCount, nSize ) );
413 : #endif
414 : }
415 :
416 : /************************************************************************/
417 : /* VSIMalloc() */
418 : /************************************************************************/
419 :
420 36822041 : void *VSIMalloc( size_t nSize )
421 :
422 : {
423 : #ifdef DEBUG_VSIMALLOC
424 : if (nMaxPeakAllocSize < 0)
425 : {
426 : char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
427 : nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
428 : char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
429 : nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
430 : }
431 : if (nMaxPeakAllocSize > 0 && (GIntBig)nSize > nMaxPeakAllocSize)
432 : return NULL;
433 : #ifdef DEBUG_VSIMALLOC_STATS
434 : if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nSize > nMaxCumulAllocSize)
435 : return NULL;
436 : #endif
437 : char* ptr = (char*) malloc(2 * sizeof(void*) + nSize);
438 : if (ptr == NULL)
439 : return NULL;
440 : ptr[0] = 'V';
441 : ptr[1] = 'S';
442 : ptr[2] = 'I';
443 : ptr[3] = 'M';
444 : memcpy(ptr + sizeof(void*), &nSize, sizeof(void*));
445 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
446 : {
447 : CPLMutexHolderD(&hMemStatMutex);
448 : #ifdef DEBUG_VSIMALLOC_VERBOSE
449 : fprintf(stderr, "Thread[%p] VSIMalloc(%d) = %p\n",
450 : (void*)CPLGetPID(), (int)nSize, ptr + 2 * sizeof(void*));
451 : #endif
452 : #ifdef DEBUG_VSIMALLOC_STATS
453 : nVSIMallocs ++;
454 : if (nMaxTotalAllocs == 0)
455 : atexit(VSIShowMemStats);
456 : nCurrentTotalAllocs += nSize;
457 : if (nCurrentTotalAllocs > nMaxTotalAllocs)
458 : nMaxTotalAllocs = nCurrentTotalAllocs;
459 : #endif
460 : }
461 : #endif
462 : return ptr + 2 * sizeof(void*);
463 : #else
464 36822041 : return( malloc( nSize ) );
465 : #endif
466 : }
467 :
468 : #ifdef DEBUG_VSIMALLOC
469 : void VSICheckMarker(char* ptr)
470 : {
471 : if (memcmp(ptr, "VSIM", 4) != 0)
472 : {
473 : CPLError(CE_Fatal, CPLE_AppDefined,
474 : "Inconsistant use of VSI memory allocation primitives for %p : %c%c%c%c",
475 : ptr, ptr[0], ptr[1], ptr[2], ptr[3]);
476 : }
477 : }
478 :
479 : #endif
480 :
481 : /************************************************************************/
482 : /* VSIRealloc() */
483 : /************************************************************************/
484 :
485 14159732 : void * VSIRealloc( void * pData, size_t nNewSize )
486 :
487 : {
488 : #ifdef DEBUG_VSIMALLOC
489 : if (pData == NULL)
490 : return VSIMalloc(nNewSize);
491 :
492 : char* ptr = ((char*)pData) - 2 * sizeof(void*);
493 : VSICheckMarker(ptr);
494 : #ifdef DEBUG_VSIMALLOC_STATS
495 : size_t nOldSize;
496 : memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
497 : #endif
498 :
499 : if (nMaxPeakAllocSize < 0)
500 : {
501 : char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
502 : nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
503 : }
504 : if (nMaxPeakAllocSize > 0 && (GIntBig)nNewSize > nMaxPeakAllocSize)
505 : return NULL;
506 : #ifdef DEBUG_VSIMALLOC_STATS
507 : if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nNewSize - (GIntBig)nOldSize > nMaxCumulAllocSize)
508 : return NULL;
509 : #endif
510 :
511 : void* newptr = realloc(ptr, nNewSize + 2 * sizeof(void*));
512 : if (newptr == NULL)
513 : return NULL;
514 : ptr = (char*) newptr;
515 : memcpy(ptr + sizeof(void*), &nNewSize, sizeof(void*));
516 :
517 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
518 : {
519 : CPLMutexHolderD(&hMemStatMutex);
520 : #ifdef DEBUG_VSIMALLOC_VERBOSE
521 : fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p\n",
522 : (void*)CPLGetPID(), pData, (int)nNewSize, ptr + 2 * sizeof(void*));
523 : #endif
524 : #ifdef DEBUG_VSIMALLOC_STATS
525 : nVSIReallocs ++;
526 : nCurrentTotalAllocs -= nOldSize;
527 : nCurrentTotalAllocs += nNewSize;
528 : if (nCurrentTotalAllocs > nMaxTotalAllocs)
529 : nMaxTotalAllocs = nCurrentTotalAllocs;
530 : #endif
531 : }
532 : #endif
533 : return ptr + 2 * sizeof(void*);
534 : #else
535 14159732 : return( realloc( pData, nNewSize ) );
536 : #endif
537 : }
538 :
539 : /************************************************************************/
540 : /* VSIFree() */
541 : /************************************************************************/
542 :
543 58890898 : void VSIFree( void * pData )
544 :
545 : {
546 : #ifdef DEBUG_VSIMALLOC
547 : if (pData == NULL)
548 : return;
549 :
550 : char* ptr = ((char*)pData) - 2 * sizeof(void*);
551 : VSICheckMarker(ptr);
552 : ptr[0] = 'M';
553 : ptr[1] = 'I';
554 : ptr[2] = 'S';
555 : ptr[3] = 'V';
556 : #if defined(DEBUG_VSIMALLOC_STATS) || defined(DEBUG_VSIMALLOC_VERBOSE)
557 : size_t nOldSize;
558 : memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
559 : {
560 : CPLMutexHolderD(&hMemStatMutex);
561 : #ifdef DEBUG_VSIMALLOC_VERBOSE
562 : fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n",
563 : (void*)CPLGetPID(), pData, (int)nOldSize);
564 : #endif
565 : #ifdef DEBUG_VSIMALLOC_STATS
566 : nVSIFrees ++;
567 : nCurrentTotalAllocs -= nOldSize;
568 : #endif
569 : }
570 : #endif
571 : free(ptr);
572 : #else
573 58890898 : if( pData != NULL )
574 47418189 : free( pData );
575 : #endif
576 58890898 : }
577 :
578 : /************************************************************************/
579 : /* VSIStrdup() */
580 : /************************************************************************/
581 :
582 4709524 : char *VSIStrdup( const char * pszString )
583 :
584 : {
585 : #ifdef DEBUG_VSIMALLOC
586 : int nSize = strlen(pszString) + 1;
587 : char* ptr = (char*) VSIMalloc(nSize);
588 : if (ptr == NULL)
589 : return NULL;
590 : memcpy(ptr, pszString, nSize);
591 : return ptr;
592 : #else
593 4709524 : return( strdup( pszString ) );
594 : #endif
595 : }
596 :
597 : /************************************************************************/
598 : /* VSICheckMul2() */
599 : /************************************************************************/
600 :
601 17374 : static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag)
602 : {
603 17374 : size_t res = mul1 * mul2;
604 17374 : if (mul1 != 0)
605 : {
606 17373 : if (res / mul1 == mul2)
607 : {
608 17373 : if (pbOverflowFlag)
609 17373 : *pbOverflowFlag = FALSE;
610 17373 : return res;
611 : }
612 : else
613 : {
614 0 : if (pbOverflowFlag)
615 0 : *pbOverflowFlag = TRUE;
616 : CPLError(CE_Failure, CPLE_OutOfMemory,
617 : "Multiplication overflow : %lu * %lu",
618 0 : (unsigned long)mul1, (unsigned long)mul2);
619 : }
620 : }
621 : else
622 : {
623 1 : if (pbOverflowFlag)
624 1 : *pbOverflowFlag = FALSE;
625 : }
626 1 : return 0;
627 : }
628 :
629 : /************************************************************************/
630 : /* VSICheckMul3() */
631 : /************************************************************************/
632 :
633 15551 : static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverflowFlag)
634 : {
635 15551 : if (mul1 != 0)
636 : {
637 15551 : size_t res = mul1 * mul2;
638 15551 : if (res / mul1 == mul2)
639 : {
640 15551 : size_t res2 = res * mul3;
641 15551 : if (mul3 != 0)
642 : {
643 15551 : if (res2 / mul3 == res)
644 : {
645 15551 : if (pbOverflowFlag)
646 15551 : *pbOverflowFlag = FALSE;
647 15551 : return res2;
648 : }
649 : else
650 : {
651 0 : if (pbOverflowFlag)
652 0 : *pbOverflowFlag = TRUE;
653 : CPLError(CE_Failure, CPLE_OutOfMemory,
654 : "Multiplication overflow : %lu * %lu * %lu",
655 0 : (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
656 : }
657 : }
658 : else
659 : {
660 0 : if (pbOverflowFlag)
661 0 : *pbOverflowFlag = FALSE;
662 : }
663 : }
664 : else
665 : {
666 0 : if (pbOverflowFlag)
667 0 : *pbOverflowFlag = TRUE;
668 : CPLError(CE_Failure, CPLE_OutOfMemory,
669 : "Multiplication overflow : %lu * %lu * %lu",
670 0 : (unsigned long)mul1, (unsigned long)mul2, (unsigned long)mul3);
671 : }
672 : }
673 : else
674 : {
675 0 : if (pbOverflowFlag)
676 0 : *pbOverflowFlag = FALSE;
677 : }
678 0 : return 0;
679 : }
680 :
681 :
682 :
683 : /**
684 : VSIMalloc2 allocates (nSize1 * nSize2) bytes.
685 : In case of overflow of the multiplication, or if memory allocation fails, a
686 : NULL pointer is returned and a CE_Failure error is raised with CPLError().
687 : If nSize1 == 0 || nSize2 == 0, a NULL pointer will also be returned.
688 : CPLFree() or VSIFree() can be used to free memory allocated by this function.
689 : */
690 17374 : void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 )
691 : {
692 17374 : int bOverflowFlag = FALSE;
693 : size_t nSizeToAllocate;
694 : void* pReturn;
695 :
696 17374 : nSizeToAllocate = VSICheckMul2( nSize1, nSize2, &bOverflowFlag );
697 17374 : if (bOverflowFlag)
698 0 : return NULL;
699 :
700 17374 : if (nSizeToAllocate == 0)
701 65 : return NULL;
702 :
703 17309 : pReturn = VSIMalloc(nSizeToAllocate);
704 :
705 17309 : if( pReturn == NULL )
706 : {
707 : CPLError( CE_Failure, CPLE_OutOfMemory,
708 : "VSIMalloc2(): Out of memory allocating %lu bytes.\n",
709 0 : (unsigned long)nSizeToAllocate );
710 : }
711 :
712 17309 : return pReturn;
713 : }
714 :
715 : /**
716 : VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.
717 : In case of overflow of the multiplication, or if memory allocation fails, a
718 : NULL pointer is returned and a CE_Failure error is raised with CPLError().
719 : If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.
720 : CPLFree() or VSIFree() can be used to free memory allocated by this function.
721 : */
722 15551 : void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 )
723 : {
724 15551 : int bOverflowFlag = FALSE;
725 :
726 : size_t nSizeToAllocate;
727 : void* pReturn;
728 :
729 15551 : nSizeToAllocate = VSICheckMul3( nSize1, nSize2, nSize3, &bOverflowFlag );
730 15551 : if (bOverflowFlag)
731 0 : return NULL;
732 :
733 15551 : if (nSizeToAllocate == 0)
734 0 : return NULL;
735 :
736 15551 : pReturn = VSIMalloc(nSizeToAllocate);
737 :
738 15551 : if( pReturn == NULL )
739 : {
740 : CPLError( CE_Failure, CPLE_OutOfMemory,
741 : "VSIMalloc3(): Out of memory allocating %lu bytes.\n",
742 0 : (unsigned long)nSizeToAllocate );
743 : }
744 :
745 15551 : return pReturn;
746 : }
747 :
748 :
749 : /************************************************************************/
750 : /* VSIStat() */
751 : /************************************************************************/
752 :
753 5482 : int VSIStat( const char * pszFilename, VSIStatBuf * pStatBuf )
754 :
755 : {
756 : #if defined(WIN32) && !defined(WIN32CE)
757 : if( CSLTestBoolean(
758 : CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
759 : {
760 : int nResult;
761 : wchar_t *pwszFilename =
762 : CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
763 :
764 : nResult = _wstat( pwszFilename, (struct _stat *) pStatBuf );
765 :
766 : CPLFree( pwszFilename );
767 :
768 : return nResult;
769 : }
770 : else
771 : #endif
772 5482 : return( stat( pszFilename, pStatBuf ) );
773 : }
774 :
775 : /************************************************************************/
776 : /* VSITime() */
777 : /************************************************************************/
778 :
779 0 : unsigned long VSITime( unsigned long * pnTimeToSet )
780 :
781 : {
782 : time_t tTime;
783 :
784 0 : tTime = time( NULL );
785 :
786 0 : if( pnTimeToSet != NULL )
787 0 : *pnTimeToSet = (unsigned long) tTime;
788 :
789 0 : return (unsigned long) tTime;
790 : }
791 :
792 : /************************************************************************/
793 : /* VSICTime() */
794 : /************************************************************************/
795 :
796 0 : const char *VSICTime( unsigned long nTime )
797 :
798 : {
799 0 : time_t tTime = (time_t) nTime;
800 :
801 0 : return (const char *) ctime( &tTime );
802 : }
803 :
804 : /************************************************************************/
805 : /* VSIGMTime() */
806 : /************************************************************************/
807 :
808 0 : struct tm *VSIGMTime( const time_t *pnTime, struct tm *poBrokenTime )
809 : {
810 :
811 : #if HAVE_GMTIME_R
812 : gmtime_r( pnTime, poBrokenTime );
813 : #else
814 : struct tm *poTime;
815 0 : poTime = gmtime( pnTime );
816 0 : memcpy( poBrokenTime, poTime, sizeof(tm) );
817 : #endif
818 :
819 0 : return poBrokenTime;
820 : }
821 :
822 : /************************************************************************/
823 : /* VSILocalTime() */
824 : /************************************************************************/
825 :
826 0 : struct tm *VSILocalTime( const time_t *pnTime, struct tm *poBrokenTime )
827 : {
828 :
829 : #if HAVE_LOCALTIME_R
830 : localtime_r( pnTime, poBrokenTime );
831 : #else
832 : struct tm *poTime;
833 0 : poTime = localtime( pnTime );
834 0 : memcpy( poBrokenTime, poTime, sizeof(tm) );
835 : #endif
836 :
837 0 : return poBrokenTime;
838 : }
839 :
840 : /************************************************************************/
841 : /* VSIStrerror() */
842 : /************************************************************************/
843 :
844 16 : char *VSIStrerror( int nErrno )
845 :
846 : {
847 16 : return strerror( nErrno );
848 : }
|