1 : /******************************************************************************
2 : * $Id: cpl_vsil.cpp 23506 2011-12-10 13:43:59Z rouault $
3 : *
4 : * Project: VSI Virtual File System
5 : * Purpose: Implementation VSI*L File API and other file system access
6 : * methods going through file virtualization.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_vsi_virtual.h"
32 : #include "cpl_string.h"
33 : #include <string>
34 :
35 : CPL_CVSID("$Id: cpl_vsil.cpp 23506 2011-12-10 13:43:59Z rouault $");
36 :
37 : /************************************************************************/
38 : /* VSIReadDir() */
39 : /************************************************************************/
40 :
41 : /**
42 : * \brief Read names in a directory.
43 : *
44 : * This function abstracts access to directory contains. It returns a
45 : * list of strings containing the names of files, and directories in this
46 : * directory. The resulting string list becomes the responsibility of the
47 : * application and should be freed with CSLDestroy() when no longer needed.
48 : *
49 : * Note that no error is issued via CPLError() if the directory path is
50 : * invalid, though NULL is returned.
51 : *
52 : * This function used to be known as CPLReadDir(), but the old name is now
53 : * deprecated.
54 : *
55 : * @param pszPath the relative, or absolute path of a directory to read.
56 : * UTF-8 encoded.
57 : * @return The list of entries in the directory, or NULL if the directory
58 : * doesn't exist. Filenames are returned in UTF-8 encoding.
59 : */
60 :
61 22506 : char **VSIReadDir(const char *pszPath)
62 : {
63 : VSIFilesystemHandler *poFSHandler =
64 22506 : VSIFileManager::GetHandler( pszPath );
65 :
66 22506 : return poFSHandler->ReadDir( pszPath );
67 : }
68 :
69 : /************************************************************************/
70 : /* CPLReadDir() */
71 : /* */
72 : /* This is present only to provide ABI compatability with older */
73 : /* versions. */
74 : /************************************************************************/
75 : #undef CPLReadDir
76 :
77 : CPL_C_START
78 : char CPL_DLL **CPLReadDir( const char *pszPath );
79 : CPL_C_END
80 :
81 0 : char **CPLReadDir( const char *pszPath )
82 : {
83 0 : return VSIReadDir(pszPath);
84 : }
85 :
86 : /************************************************************************/
87 : /* VSIMkdir() */
88 : /************************************************************************/
89 :
90 : /**
91 : * \brief Create a directory.
92 : *
93 : * Create a new directory with the indicated mode. The mode is ignored
94 : * on some platforms. A reasonable default mode value would be 0666.
95 : * This method goes through the VSIFileHandler virtualization and may
96 : * work on unusual filesystems such as in memory.
97 : *
98 : * Analog of the POSIX mkdir() function.
99 : *
100 : * @param pszPathname the path to the directory to create. UTF-8 encoded.
101 : * @param mode the permissions mode.
102 : *
103 : * @return 0 on success or -1 on an error.
104 : */
105 :
106 236 : int VSIMkdir( const char *pszPathname, long mode )
107 :
108 : {
109 : VSIFilesystemHandler *poFSHandler =
110 236 : VSIFileManager::GetHandler( pszPathname );
111 :
112 236 : return poFSHandler->Mkdir( pszPathname, mode );
113 : }
114 :
115 : /************************************************************************/
116 : /* VSIUnlink() */
117 : /*************************a***********************************************/
118 :
119 : /**
120 : * \brief Delete a file.
121 : *
122 : * Deletes a file object from the file system.
123 : *
124 : * This method goes through the VSIFileHandler virtualization and may
125 : * work on unusual filesystems such as in memory.
126 : *
127 : * Analog of the POSIX unlink() function.
128 : *
129 : * @param pszFilename the path of the file to be deleted. UTF-8 encoded.
130 : *
131 : * @return 0 on success or -1 on an error.
132 : */
133 :
134 17164 : int VSIUnlink( const char * pszFilename )
135 :
136 : {
137 : VSIFilesystemHandler *poFSHandler =
138 17164 : VSIFileManager::GetHandler( pszFilename );
139 :
140 17164 : return poFSHandler->Unlink( pszFilename );
141 : }
142 :
143 : /************************************************************************/
144 : /* VSIRename() */
145 : /************************************************************************/
146 :
147 : /**
148 : * \brief Rename a file.
149 : *
150 : * Renames a file object in the file system. It should be possible
151 : * to rename a file onto a new filesystem, but it is safest if this
152 : * function is only used to rename files that remain in the same directory.
153 : *
154 : * This method goes through the VSIFileHandler virtualization and may
155 : * work on unusual filesystems such as in memory.
156 : *
157 : * Analog of the POSIX rename() function.
158 : *
159 : * @param oldpath the name of the file to be renamed. UTF-8 encoded.
160 : * @param newpath the name the file should be given. UTF-8 encoded.
161 : *
162 : * @return 0 on success or -1 on an error.
163 : */
164 :
165 28 : int VSIRename( const char * oldpath, const char * newpath )
166 :
167 : {
168 : VSIFilesystemHandler *poFSHandler =
169 28 : VSIFileManager::GetHandler( oldpath );
170 :
171 28 : return poFSHandler->Rename( oldpath, newpath );
172 : }
173 :
174 : /************************************************************************/
175 : /* VSIRmdir() */
176 : /************************************************************************/
177 :
178 : /**
179 : * \brief Delete a directory.
180 : *
181 : * Deletes a directory object from the file system. On some systems
182 : * the directory must be empty before it can be deleted.
183 : *
184 : * This method goes through the VSIFileHandler virtualization and may
185 : * work on unusual filesystems such as in memory.
186 : *
187 : * Analog of the POSIX rmdir() function.
188 : *
189 : * @param pszDirname the path of the directory to be deleted. UTF-8 encoded.
190 : *
191 : * @return 0 on success or -1 on an error.
192 : */
193 :
194 634 : int VSIRmdir( const char * pszDirname )
195 :
196 : {
197 : VSIFilesystemHandler *poFSHandler =
198 634 : VSIFileManager::GetHandler( pszDirname );
199 :
200 634 : return poFSHandler->Rmdir( pszDirname );
201 : }
202 :
203 : /************************************************************************/
204 : /* VSIStatL() */
205 : /************************************************************************/
206 :
207 : /**
208 : * \brief Get filesystem object info.
209 : *
210 : * Fetches status information about a filesystem object (file, directory, etc).
211 : * The returned information is placed in the VSIStatBufL structure. For
212 : * portability only the st_size (size in bytes), and st_mode (file type).
213 : * This method is similar to VSIStat(), but will work on large files on
214 : * systems where this requires special calls.
215 : *
216 : * This method goes through the VSIFileHandler virtualization and may
217 : * work on unusual filesystems such as in memory.
218 : *
219 : * Analog of the POSIX stat() function.
220 : *
221 : * @param pszFilename the path of the filesystem object to be queried. UTF-8 encoded.
222 : * @param psStatBuf the structure to load with information.
223 : *
224 : * @return 0 on success or -1 on an error.
225 : */
226 :
227 19686 : int VSIStatL( const char * pszFilename, VSIStatBufL *psStatBuf )
228 :
229 : {
230 19686 : return VSIStatExL(pszFilename, psStatBuf, 0);
231 : }
232 :
233 :
234 : /************************************************************************/
235 : /* VSIStatExL() */
236 : /************************************************************************/
237 :
238 : /**
239 : * \brief Get filesystem object info.
240 : *
241 : * Fetches status information about a filesystem object (file, directory, etc).
242 : * The returned information is placed in the VSIStatBufL structure. For
243 : * portability only the st_size (size in bytes), and st_mode (file type).
244 : * This method is similar to VSIStat(), but will work on large files on
245 : * systems where this requires special calls.
246 : *
247 : * This method goes through the VSIFileHandler virtualization and may
248 : * work on unusual filesystems such as in memory.
249 : *
250 : * Analog of the POSIX stat() function, with an extra parameter to specify
251 : * which information is needed, which offers a potential for speed optimizations
252 : * on specialized and potentially slow virtual filesystem objects (/vsigzip/, /vsicurl/)
253 : *
254 : * @param pszFilename the path of the filesystem object to be queried. UTF-8 encoded.
255 : * @param psStatBuf the structure to load with information.
256 : * @param nFlags 0 to get all information, or VSI_STAT_EXISTS_FLAG, VSI_STAT_NATURE_FLAG or
257 : * VSI_STAT_SIZE_FLAG, or a combination of those to get partial info.
258 : *
259 : * @return 0 on success or -1 on an error.
260 : *
261 : * @since GDAL 1.8.0
262 : */
263 :
264 110936 : int VSIStatExL( const char * pszFilename, VSIStatBufL *psStatBuf, int nFlags )
265 :
266 : {
267 : char szAltPath[4];
268 : /* enable to work on "C:" as if it were "C:\" */
269 110936 : if( strlen(pszFilename) == 2 && pszFilename[1] == ':' )
270 : {
271 0 : szAltPath[0] = pszFilename[0];
272 0 : szAltPath[1] = pszFilename[1];
273 0 : szAltPath[2] = '\\';
274 0 : szAltPath[3] = '\0';
275 :
276 0 : pszFilename = szAltPath;
277 : }
278 :
279 : VSIFilesystemHandler *poFSHandler =
280 110936 : VSIFileManager::GetHandler( pszFilename );
281 :
282 110936 : if (nFlags == 0)
283 19686 : nFlags = VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG | VSI_STAT_SIZE_FLAG;
284 :
285 110936 : return poFSHandler->Stat( pszFilename, psStatBuf, nFlags );
286 : }
287 :
288 : /************************************************************************/
289 : /* VSIIsCaseSensitiveFS() */
290 : /************************************************************************/
291 :
292 : /**
293 : * \brief Returns if the filenames of the filesystem are case sensitive.
294 : *
295 : * This method retrieves to which filesystem belongs the passed filename
296 : * and return TRUE if the filenames of that filesystem are case sensitive.
297 : *
298 : * Currently, this will return FALSE only for Windows real filenames. Other
299 : * VSI virtual filesystems are case sensitive.
300 : *
301 : * This methods avoid ugly #ifndef WIN32 / #endif code, that is wrong when
302 : * dealing with virtual filenames.
303 : *
304 : * @param pszFilename the path of the filesystem object to be tested. UTF-8 encoded.
305 : *
306 : * @return TRUE if the filenames of the filesystem are case sensitive.
307 : *
308 : * @since GDAL 1.8.0
309 : */
310 21156 : int VSIIsCaseSensitiveFS( const char * pszFilename )
311 : {
312 : VSIFilesystemHandler *poFSHandler =
313 21156 : VSIFileManager::GetHandler( pszFilename );
314 :
315 21156 : return poFSHandler->IsCaseSensitive( pszFilename );
316 : }
317 :
318 : /************************************************************************/
319 : /* VSIFOpenL() */
320 : /************************************************************************/
321 :
322 : /**
323 : * \brief Open file.
324 : *
325 : * This function opens a file with the desired access. Large files (larger
326 : * than 2GB) should be supported. Binary access is always implied and
327 : * the "b" does not need to be included in the pszAccess string.
328 : *
329 : * Note that the "VSILFILE *" returned since GDAL 1.8.0 by this function is
330 : * *NOT* a standard C library FILE *, and cannot be used with any functions
331 : * other than the "VSI*L" family of functions. They aren't "real" FILE objects.
332 : *
333 : * On windows it is possible to define the configuration option
334 : * GDAL_FILE_IS_UTF8 to have pszFilename treated as being in the local
335 : * encoding instead of UTF-8, retoring the pre-1.8.0 behavior of VSIFOpenL().
336 : *
337 : * This method goes through the VSIFileHandler virtualization and may
338 : * work on unusual filesystems such as in memory.
339 : *
340 : * Analog of the POSIX fopen() function.
341 : *
342 : * @param pszFilename the file to open. UTF-8 encoded.
343 : * @param pszAccess access requested (ie. "r", "r+", "w".
344 : *
345 : * @return NULL on failure, or the file handle.
346 : */
347 :
348 174067 : VSILFILE *VSIFOpenL( const char * pszFilename, const char * pszAccess )
349 :
350 : {
351 : VSIFilesystemHandler *poFSHandler =
352 174067 : VSIFileManager::GetHandler( pszFilename );
353 :
354 174067 : VSILFILE* fp = (VSILFILE *) poFSHandler->Open( pszFilename, pszAccess );
355 :
356 : VSIDebug3( "VSIFOpenL(%s,%s) = %p", pszFilename, pszAccess, fp );
357 :
358 174067 : return fp;
359 : }
360 :
361 : /************************************************************************/
362 : /* VSIFCloseL() */
363 : /************************************************************************/
364 :
365 : /**
366 : * \brief Close file.
367 : *
368 : * This function closes the indicated file.
369 : *
370 : * This method goes through the VSIFileHandler virtualization and may
371 : * work on unusual filesystems such as in memory.
372 : *
373 : * Analog of the POSIX fclose() function.
374 : *
375 : * @param fp file handle opened with VSIFOpenL().
376 : *
377 : * @return 0 on success or -1 on failure.
378 : */
379 :
380 122585 : int VSIFCloseL( VSILFILE * fp )
381 :
382 : {
383 122585 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
384 :
385 : VSIDebug1( "VSICloseL(%p)", fp );
386 :
387 122585 : int nResult = poFileHandle->Close();
388 :
389 122585 : delete poFileHandle;
390 :
391 122585 : return nResult;
392 : }
393 :
394 : /************************************************************************/
395 : /* VSIFSeekL() */
396 : /************************************************************************/
397 :
398 : /**
399 : * \brief Seek to requested offset.
400 : *
401 : * Seek to the desired offset (nOffset) in the indicated file.
402 : *
403 : * This method goes through the VSIFileHandler virtualization and may
404 : * work on unusual filesystems such as in memory.
405 : *
406 : * Analog of the POSIX fseek() call.
407 : *
408 : * @param fp file handle opened with VSIFOpenL().
409 : * @param nOffset offset in bytes.
410 : * @param nWhence one of SEEK_SET, SEEK_CUR or SEEK_END.
411 : *
412 : * @return 0 on success or -1 one failure.
413 : */
414 :
415 6345037 : int VSIFSeekL( VSILFILE * fp, vsi_l_offset nOffset, int nWhence )
416 :
417 : {
418 6345037 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
419 :
420 6345037 : return poFileHandle->Seek( nOffset, nWhence );
421 : }
422 :
423 : /************************************************************************/
424 : /* VSIFTellL() */
425 : /************************************************************************/
426 :
427 : /**
428 : * \brief Tell current file offset.
429 : *
430 : * Returns the current file read/write offset in bytes from the beginning of
431 : * the file.
432 : *
433 : * This method goes through the VSIFileHandler virtualization and may
434 : * work on unusual filesystems such as in memory.
435 : *
436 : * Analog of the POSIX ftell() call.
437 : *
438 : * @param fp file handle opened with VSIFOpenL().
439 : *
440 : * @return file offset in bytes.
441 : */
442 :
443 2029761 : vsi_l_offset VSIFTellL( VSILFILE * fp )
444 :
445 : {
446 2029761 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
447 :
448 2029761 : return poFileHandle->Tell();
449 : }
450 :
451 : /************************************************************************/
452 : /* VSIRewindL() */
453 : /************************************************************************/
454 :
455 966 : void VSIRewindL( VSILFILE * fp )
456 :
457 : {
458 966 : VSIFSeekL( fp, 0, SEEK_SET );
459 966 : }
460 :
461 : /************************************************************************/
462 : /* VSIFFlushL() */
463 : /************************************************************************/
464 :
465 : /**
466 : * \brief Flush pending writes to disk.
467 : *
468 : * For files in write or update mode and on filesystem types where it is
469 : * applicable, all pending output on the file is flushed to the physical disk.
470 : *
471 : * This method goes through the VSIFileHandler virtualization and may
472 : * work on unusual filesystems such as in memory.
473 : *
474 : * Analog of the POSIX fflush() call.
475 : *
476 : * @param fp file handle opened with VSIFOpenL().
477 : *
478 : * @return 0 on success or -1 on error.
479 : */
480 :
481 8418 : int VSIFFlushL( VSILFILE * fp )
482 :
483 : {
484 8418 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
485 :
486 8418 : return poFileHandle->Flush();
487 : }
488 :
489 : /************************************************************************/
490 : /* VSIFReadL() */
491 : /************************************************************************/
492 :
493 : /**
494 : * \brief Read bytes from file.
495 : *
496 : * Reads nCount objects of nSize bytes from the indicated file at the
497 : * current offset into the indicated buffer.
498 : *
499 : * This method goes through the VSIFileHandler virtualization and may
500 : * work on unusual filesystems such as in memory.
501 : *
502 : * Analog of the POSIX fread() call.
503 : *
504 : * @param pBuffer the buffer into which the data should be read (at least
505 : * nCount * nSize bytes in size.
506 : * @param nSize size of objects to read in bytes.
507 : * @param nCount number of objects to read.
508 : * @param fp file handle opened with VSIFOpenL().
509 : *
510 : * @return number of objects successfully read.
511 : */
512 :
513 13423306 : size_t VSIFReadL( void * pBuffer, size_t nSize, size_t nCount, VSILFILE * fp )
514 :
515 : {
516 13423306 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
517 :
518 13423306 : return poFileHandle->Read( pBuffer, nSize, nCount );
519 : }
520 :
521 :
522 : /************************************************************************/
523 : /* VSIFReadMultiRangeL() */
524 : /************************************************************************/
525 :
526 : /**
527 : * \brief Read several ranges of bytes from file.
528 : *
529 : * Reads nRanges objects of panSizes[i] bytes from the indicated file at the
530 : * offset panOffsets[i] into the buffer ppData[i].
531 : *
532 : * Ranges must be sorted in ascending start offset, and must not overlap each
533 : * other.
534 : *
535 : * This method goes through the VSIFileHandler virtualization and may
536 : * work on unusual filesystems such as in memory or /vsicurl/.
537 : *
538 : * @param nRanges number of ranges to read.
539 : * @param ppData array of nRanges buffer into which the data should be read
540 : * (ppData[i] must be at list panSizes[i] bytes).
541 : * @param panOffsets array of nRanges offsets at which the data should be read.
542 : * @param panSizes array of nRanges sizes of objects to read (in bytes).
543 : * @param fp file handle opened with VSIFOpenL().
544 : *
545 : * @return 0 in case of success, -1 otherwise.
546 : * @since GDAL 1.9.0
547 : */
548 :
549 2 : int VSIFReadMultiRangeL( int nRanges, void ** ppData,
550 : const vsi_l_offset* panOffsets,
551 : const size_t* panSizes, VSILFILE * fp )
552 : {
553 2 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
554 :
555 2 : return poFileHandle->ReadMultiRange( nRanges, ppData, panOffsets, panSizes );
556 : }
557 :
558 : /************************************************************************/
559 : /* VSIFWriteL() */
560 : /************************************************************************/
561 :
562 : /**
563 : * \brief Write bytes to file.
564 : *
565 : * Writess nCount objects of nSize bytes to the indicated file at the
566 : * current offset into the indicated buffer.
567 : *
568 : * This method goes through the VSIFileHandler virtualization and may
569 : * work on unusual filesystems such as in memory.
570 : *
571 : * Analog of the POSIX fwrite() call.
572 : *
573 : * @param pBuffer the buffer from which the data should be written (at least
574 : * nCount * nSize bytes in size.
575 : * @param nSize size of objects to read in bytes.
576 : * @param nCount number of objects to read.
577 : * @param fp file handle opened with VSIFOpenL().
578 : *
579 : * @return number of objects successfully written.
580 : */
581 :
582 4793550 : size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp )
583 :
584 : {
585 4793550 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
586 :
587 4793550 : return poFileHandle->Write( pBuffer, nSize, nCount );
588 : }
589 :
590 : /************************************************************************/
591 : /* VSIFEofL() */
592 : /************************************************************************/
593 :
594 : /**
595 : * \brief Test for end of file.
596 : *
597 : * Returns TRUE (non-zero) if an end-of-file condition occured during the
598 : * previous read operation. The end-of-file flag is cleared by a successfull
599 : * VSIFSeekL() call.
600 : *
601 : * This method goes through the VSIFileHandler virtualization and may
602 : * work on unusual filesystems such as in memory.
603 : *
604 : * Analog of the POSIX feof() call.
605 : *
606 : * @param fp file handle opened with VSIFOpenL().
607 : *
608 : * @return TRUE if at EOF else FALSE.
609 : */
610 :
611 183932 : int VSIFEofL( VSILFILE * fp )
612 :
613 : {
614 183932 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
615 :
616 183932 : return poFileHandle->Eof();
617 : }
618 :
619 : /************************************************************************/
620 : /* VSIFTruncateL() */
621 : /************************************************************************/
622 :
623 : /**
624 : * \brief Truncate/expand the file to the specified size
625 :
626 : * This method goes through the VSIFileHandler virtualization and may
627 : * work on unusual filesystems such as in memory.
628 : *
629 : * Analog of the POSIX ftruncate() call.
630 : *
631 : * @param fp file handle opened with VSIFOpenL().
632 : * @param nNewSize new size in bytes.
633 : *
634 : * @return 0 on success
635 : * @since GDAL 1.9.0
636 : */
637 :
638 120 : int VSIFTruncateL( VSILFILE * fp, vsi_l_offset nNewSize )
639 :
640 : {
641 120 : VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
642 :
643 120 : return poFileHandle->Truncate(nNewSize);
644 : }
645 :
646 : /************************************************************************/
647 : /* VSIFPrintfL() */
648 : /************************************************************************/
649 :
650 : /**
651 : * \brief Formatted write to file.
652 : *
653 : * Provides fprintf() style formatted output to a VSI*L file. This formats
654 : * an internal buffer which is written using VSIFWriteL().
655 : *
656 : * Analog of the POSIX fprintf() call.
657 : *
658 : * @param fp file handle opened with VSIFOpenL().
659 : * @param pszFormat the printf style format string.
660 : *
661 : * @return the number of bytes written or -1 on an error.
662 : */
663 :
664 39906 : int VSIFPrintfL( VSILFILE *fp, const char *pszFormat, ... )
665 :
666 : {
667 : va_list args;
668 39906 : CPLString osResult;
669 :
670 39906 : va_start( args, pszFormat );
671 39906 : osResult.vPrintf( pszFormat, args );
672 39906 : va_end( args );
673 :
674 39906 : return VSIFWriteL( osResult.c_str(), 1, osResult.length(), fp );
675 : }
676 :
677 : /************************************************************************/
678 : /* VSIFPutcL() */
679 : /************************************************************************/
680 :
681 340 : int VSIFPutcL( int nChar, VSILFILE * fp )
682 :
683 : {
684 340 : unsigned char cChar = (unsigned char)nChar;
685 340 : return VSIFWriteL(&cChar, 1, 1, fp);
686 : }
687 :
688 : /************************************************************************/
689 : /* ==================================================================== */
690 : /* VSIFileManager() */
691 : /* ==================================================================== */
692 : /************************************************************************/
693 :
694 : /*
695 : ** Notes on Multithreading:
696 : **
697 : ** The VSIFileManager maintains a list of file type handlers (mem, large
698 : ** file, etc). It should be thread safe as long as all the handlers are
699 : ** instantiated before multiple threads begin to operate.
700 : **/
701 :
702 : /************************************************************************/
703 : /* VSIFileManager() */
704 : /************************************************************************/
705 :
706 1341 : VSIFileManager::VSIFileManager()
707 :
708 : {
709 1341 : poDefaultHandler = NULL;
710 1341 : }
711 :
712 : /************************************************************************/
713 : /* ~VSIFileManager() */
714 : /************************************************************************/
715 :
716 1297 : VSIFileManager::~VSIFileManager()
717 : {
718 1297 : std::map<std::string,VSIFilesystemHandler*>::const_iterator iter;
719 :
720 14267 : for( iter = oHandlers.begin();
721 : iter != oHandlers.end();
722 : ++iter )
723 : {
724 12970 : delete iter->second;
725 : }
726 :
727 1297 : delete poDefaultHandler;
728 1297 : }
729 :
730 :
731 : /************************************************************************/
732 : /* Get() */
733 : /************************************************************************/
734 :
735 : static VSIFileManager *poManager = NULL;
736 :
737 364068 : VSIFileManager *VSIFileManager::Get()
738 :
739 : {
740 :
741 364068 : if( poManager == NULL )
742 : {
743 1341 : poManager = new VSIFileManager;
744 1341 : VSIInstallLargeFileHandler();
745 1341 : VSIInstallSubFileHandler();
746 1341 : VSIInstallMemFileHandler();
747 : #ifdef HAVE_LIBZ
748 1341 : VSIInstallGZipFileHandler();
749 1341 : VSIInstallZipFileHandler();
750 : #endif
751 : #ifdef HAVE_CURL
752 1341 : VSIInstallCurlFileHandler();
753 : #endif
754 1341 : VSIInstallStdinHandler();
755 1341 : VSIInstallStdoutHandler();
756 1341 : VSIInstallSparseFileHandler();
757 1341 : VSIInstallTarFileHandler();
758 : }
759 :
760 364068 : return poManager;
761 : }
762 :
763 : /************************************************************************/
764 : /* GetHandler() */
765 : /************************************************************************/
766 :
767 349317 : VSIFilesystemHandler *VSIFileManager::GetHandler( const char *pszPath )
768 :
769 : {
770 349317 : VSIFileManager *poThis = Get();
771 349317 : std::map<std::string,VSIFilesystemHandler*>::const_iterator iter;
772 349317 : int nPathLen = strlen(pszPath);
773 :
774 3278943 : for( iter = poThis->oHandlers.begin();
775 : iter != poThis->oHandlers.end();
776 : ++iter )
777 : {
778 3001594 : const char* pszIterKey = iter->first.c_str();
779 3001594 : int nIterKeyLen = iter->first.size();
780 3001594 : if( strncmp(pszPath,pszIterKey,nIterKeyLen) == 0 )
781 70906 : return iter->second;
782 :
783 : /* "/vsimem\foo" should be handled as "/vsimem/foo" */
784 8075242 : if (nIterKeyLen && nPathLen > nIterKeyLen &&
785 2572277 : pszIterKey[nIterKeyLen-1] == '/' &&
786 2572277 : pszPath[nIterKeyLen-1] == '\\' &&
787 : strncmp(pszPath,pszIterKey,nIterKeyLen-1) == 0 )
788 6 : return iter->second;
789 :
790 : /* /vsimem should be treated as a match for /vsimem/ */
791 2930682 : if( nPathLen == nIterKeyLen - 1
792 : && strncmp(pszPath,pszIterKey,nIterKeyLen-1) == 0 )
793 1056 : return iter->second;
794 : }
795 :
796 277349 : return poThis->poDefaultHandler;
797 : }
798 :
799 : /************************************************************************/
800 : /* InstallHandler() */
801 : /************************************************************************/
802 :
803 14751 : void VSIFileManager::InstallHandler( const std::string& osPrefix,
804 : VSIFilesystemHandler *poHandler )
805 :
806 : {
807 14751 : if( osPrefix == "" )
808 1341 : Get()->poDefaultHandler = poHandler;
809 : else
810 13410 : Get()->oHandlers[osPrefix] = poHandler;
811 14751 : }
812 :
813 : /************************************************************************/
814 : /* VSICleanupFileManager() */
815 : /************************************************************************/
816 :
817 1974 : void VSICleanupFileManager()
818 :
819 : {
820 1974 : if( poManager )
821 : {
822 1297 : delete poManager;
823 1297 : poManager = NULL;
824 : }
825 1974 : }
826 :
827 : /************************************************************************/
828 : /* ReadMultiRange() */
829 : /************************************************************************/
830 :
831 0 : int VSIVirtualHandle::ReadMultiRange( int nRanges, void ** ppData,
832 : const vsi_l_offset* panOffsets,
833 : const size_t* panSizes )
834 : {
835 0 : int nRet = 0;
836 0 : vsi_l_offset nCurOffset = Tell();
837 0 : for(int i=0;i<nRanges;i++)
838 : {
839 0 : if (Seek(panOffsets[i], SEEK_SET) < 0)
840 : {
841 0 : nRet = -1;
842 0 : break;
843 : }
844 :
845 0 : size_t nRead = Read(ppData[i], 1, panSizes[i]);
846 0 : if (panSizes[i] != nRead)
847 : {
848 0 : nRet = -1;
849 0 : break;
850 : }
851 : }
852 :
853 0 : Seek(nCurOffset, SEEK_SET);
854 :
855 0 : return nRet;
856 : }
|