1 /******************************************************************************
2 *
3 * Project: CPL - Common Portability Library
4 * Purpose: Standalone shared library that can be LD_PRELOAD'ed as an overload of
5 * libc to enable VSI Virtual FILE API to be used with binaries using
6 * regular libc for I/O.
7 * Author: Even Rouault <even dot rouault at spatialys.com>
8 *
9 ******************************************************************************
10 * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.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 // WARNING: Linux glibc ONLY
32 // Might work with some adaptations (mainly around 64bit symbols) on other Unix systems
33
34 // Compile:
35 // g++ -Wall -fPIC port/vsipreload.cpp -shared -o vsipreload.so -Iport -L. -L.libs -lgdal
36
37 // Run:
38 // LD_PRELOAD=./vsipreload.so ....
39 // e.g:
40 // LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
41 // LD_PRELOAD=./vsipreload.so gdalinfo 'HDF4_EOS:EOS_GRID:"/vsicurl/http://download.osgeo.org/gdal/data/hdf4/MOD09Q1G_EVI.A2006233.h07v03.005.2008338190308.hdf":MODIS_NACP_EVI:MODIS_EVI'
42 // LD_PRELOAD=./vsipreload.so ogrinfo /vsicurl/http://svn.osgeo.org/gdal/trunk/autotest/ogr/data/testavc -ro
43 // even non GDAL binaries :
44 // LD_PRELOAD=./vsipreload.so h5dump -d /x /vsicurl/http://download.osgeo.org/gdal/data/netcdf/utm-big-chunks.nc
45 // LD_PRELOAD=./vsipreload.so sqlite3 /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
46 // LD_PRELOAD=./vsipreload.so ls -al /vsicurl/http://download.osgeo.org/gdal/data/sqlite3
47 // LD_PRELOAD=./vsipreload.so find /vsicurl/http://download.osgeo.org/gdal/data/sqlite3
48
49 #define _GNU_SOURCE 1
50 #define _LARGEFILE64_SOURCE 1
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <assert.h>
54 #include <dlfcn.h>
55 #include <string.h>
56 #include <fcntl.h>
57 #include <unistd.h>
58 #include <dirent.h>
59 #include <sys/types.h>
60 #include <sys/stat.h>
61
62 #include <set>
63 #include <map>
64 #include <string>
65 #include "cpl_vsi.h"
66 #include "cpl_multiproc.h"
67 #include "cpl_string.h"
68 #include "cpl_hash_set.h"
69
70 CPL_CVSID("$Id: vsipreload.cpp 355b41831cd2685c85d1aabe5b95665a2c6e99b7 2019-06-19 17:07:04 +0200 Even Rouault $")
71
72 static int DEBUG_VSIPRELOAD = 0;
73 static int DEBUG_VSIPRELOAD_ONLY_VSIL = 1;
74 #define DEBUG_OUTPUT_READ 0
75
76 #ifndef NO_FSTATAT
77 #define HAVE_FSTATAT
78 #endif
79
80 #define DECLARE_SYMBOL(x, retType, args) \
81 typedef retType (*fn ## x ## Type)args;\
82 static fn ## x ## Type pfn ## x = nullptr
83
84 DECLARE_SYMBOL(fopen, FILE*, (const char *path, const char *mode));
85 DECLARE_SYMBOL(fopen64, FILE*, (const char *path, const char *mode));
86 DECLARE_SYMBOL(fread, size_t, (void *ptr, size_t size, size_t nmemb,
87 FILE *stream));
88 DECLARE_SYMBOL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb,
89 FILE *stream));
90 DECLARE_SYMBOL(fclose, int, (FILE *stream));
91 DECLARE_SYMBOL(__xstat, int, (int ver, const char *path, struct stat *buf));
92 DECLARE_SYMBOL(__lxstat, int, (int ver, const char *path, struct stat *buf));
93 DECLARE_SYMBOL(__xstat64, int, (int ver, const char *path, struct stat64 *buf));
94 DECLARE_SYMBOL(fseeko64, int, (FILE *stream, off64_t off, int whence));
95 DECLARE_SYMBOL(fseek, int, (FILE *stream, off_t off, int whence));
96 DECLARE_SYMBOL(ftello64, off64_t, (FILE *stream));
97 DECLARE_SYMBOL(ftell, off_t, (FILE *stream));
98 DECLARE_SYMBOL(feof, int, (FILE *stream));
99 DECLARE_SYMBOL(fflush, int, (FILE *stream));
100 DECLARE_SYMBOL(fgetpos, int, (FILE *stream, fpos_t *pos));
101 DECLARE_SYMBOL(fsetpos, int, (FILE *stream, fpos_t *pos));
102 DECLARE_SYMBOL(fileno, int, (FILE *stream));
103 DECLARE_SYMBOL(ferror, int, (FILE *stream));
104 DECLARE_SYMBOL(clearerr, void, (FILE *stream));
105
106 DECLARE_SYMBOL(fdopen, FILE*, (int fd, const char *mode));
107 DECLARE_SYMBOL(freopen, FILE*, (const char *path, const char *mode,
108 FILE *stream));
109
110 DECLARE_SYMBOL(open, int, (const char *path, int flags, mode_t mode));
111 DECLARE_SYMBOL(open64, int, (const char *path, int flags, mode_t mode));
112 // DECLARE_SYMBOL(creat, int, (const char *path, mode_t mode));
113 DECLARE_SYMBOL(close, int, (int fd));
114 DECLARE_SYMBOL(read, ssize_t, (int fd, void *buf, size_t count));
115 DECLARE_SYMBOL(write, ssize_t, (int fd, const void *buf, size_t count));
116 DECLARE_SYMBOL(fsync, int, (int fd));
117 DECLARE_SYMBOL(fdatasync, int, (int fd));
118 DECLARE_SYMBOL(__fxstat, int, (int ver, int fd, struct stat *__stat_buf));
119 DECLARE_SYMBOL(__fxstat64, int, (int ver, int fd, struct stat64 *__stat_buf));
120 #ifdef HAVE_FSTATAT
121 DECLARE_SYMBOL(__fxstatat, int, (int ver, int dirfd, const char *pathname,
122 struct stat *buf, int flags));
123 #endif
124
125 DECLARE_SYMBOL(lseek, off_t, (int fd, off_t off, int whence));
126 DECLARE_SYMBOL(lseek64, off64_t , (int fd, off64_t off, int whence));
127
128 DECLARE_SYMBOL(truncate, int, (const char *path, off_t length));
129 DECLARE_SYMBOL(ftruncate, int, (int fd, off_t length));
130
131 DECLARE_SYMBOL(opendir, DIR* , (const char *name));
132 DECLARE_SYMBOL(readdir, struct dirent*, (DIR *dirp));
133 DECLARE_SYMBOL(readdir64, struct dirent64*, (DIR *dirp));
134 DECLARE_SYMBOL(closedir, int, (DIR *dirp));
135 DECLARE_SYMBOL(dirfd, int, (DIR *dirp));
136 DECLARE_SYMBOL(fchdir, int, (int fd));
137
138 static CPLLock* hLock = nullptr;
139
140 typedef struct
141 {
142 char* pszDirname;
143 char** papszDir;
144 int nIter;
145 struct dirent ent;
146 struct dirent64 ent64;
147 int fd;
148 } VSIDIRPreload;
149
150 std::set<VSILFILE*> oSetFiles;
151 std::map<int, VSILFILE*> oMapfdToVSI;
152 std::map<VSILFILE*, int> oMapVSITofd;
153 std::map<VSILFILE*, std::string> oMapVSIToString;
154 std::set<VSIDIRPreload*> oSetVSIDIRPreload;
155 std::map<int, VSIDIRPreload*> oMapfdToVSIDIRPreload;
156 std::map<int, std::string> oMapDirFdToName;
157 std::string osCurDir;
158
159 /************************************************************************/
160 /* myinit() */
161 /************************************************************************/
162
163 #define LOAD_SYMBOL(x) \
164 pfn ## x = (fn ## x ## Type) dlsym(RTLD_NEXT, #x); \
165 assert(pfn ## x)
166
myinit()167 static void myinit()
168 {
169 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
170
171 if( pfnfopen64 != nullptr ) return;
172 DEBUG_VSIPRELOAD = getenv("DEBUG_VSIPRELOAD") != nullptr;
173 LOAD_SYMBOL(fopen);
174 LOAD_SYMBOL(fopen64);
175 LOAD_SYMBOL(fread);
176 LOAD_SYMBOL(fwrite);
177 LOAD_SYMBOL(fclose);
178 LOAD_SYMBOL(fseeko64);
179 LOAD_SYMBOL(fseek);
180 LOAD_SYMBOL(__xstat);
181 LOAD_SYMBOL(__lxstat);
182 LOAD_SYMBOL(__xstat64);
183 LOAD_SYMBOL(ftello64);
184 LOAD_SYMBOL(ftell);
185 LOAD_SYMBOL(feof);
186 LOAD_SYMBOL(fflush);
187 LOAD_SYMBOL(fgetpos);
188 LOAD_SYMBOL(fsetpos);
189 LOAD_SYMBOL(fileno);
190 LOAD_SYMBOL(ferror);
191 LOAD_SYMBOL(clearerr);
192
193 LOAD_SYMBOL(fdopen);
194 LOAD_SYMBOL(freopen);
195
196 LOAD_SYMBOL(open);
197 LOAD_SYMBOL(open64);
198 // LOAD_SYMBOL(creat);
199 LOAD_SYMBOL(close);
200 LOAD_SYMBOL(read);
201 LOAD_SYMBOL(write);
202 LOAD_SYMBOL(fsync);
203 LOAD_SYMBOL(fdatasync);
204 LOAD_SYMBOL(__fxstat);
205 LOAD_SYMBOL(__fxstat64);
206 #ifdef HAVE_FSTATAT
207 LOAD_SYMBOL(__fxstatat);
208 #endif
209 LOAD_SYMBOL(lseek);
210 LOAD_SYMBOL(lseek64);
211
212 LOAD_SYMBOL(truncate);
213 LOAD_SYMBOL(ftruncate);
214
215 LOAD_SYMBOL(opendir);
216 LOAD_SYMBOL(readdir);
217 LOAD_SYMBOL(readdir64);
218 LOAD_SYMBOL(closedir);
219 LOAD_SYMBOL(dirfd);
220 LOAD_SYMBOL(fchdir);
221 }
222
223 /************************************************************************/
224 /* getVSILFILE() */
225 /************************************************************************/
226
getVSILFILE(FILE * stream)227 static VSILFILE* getVSILFILE( FILE* stream )
228 {
229 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
230 std::set<VSILFILE*>::iterator oIter = oSetFiles.find((VSILFILE*)stream);
231 VSILFILE* ret = nullptr;
232 if( oIter != oSetFiles.end() )
233 ret = *oIter;
234 else
235 ret = nullptr;
236 return ret;
237 }
238
239 /************************************************************************/
240 /* getVSILFILE() */
241 /************************************************************************/
242
getVSILFILE(int fd)243 static VSILFILE* getVSILFILE( int fd )
244 {
245 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
246 std::map<int, VSILFILE*>::iterator oIter = oMapfdToVSI.find(fd);
247 VSILFILE* ret = nullptr;
248 if( oIter != oMapfdToVSI.end() )
249 ret = oIter->second;
250 else
251 ret = nullptr;
252 return ret;
253 }
254
255 /************************************************************************/
256 /* VSIFSeekLHelper() */
257 /************************************************************************/
258
VSIFSeekLHelper(VSILFILE * fpVSIL,off64_t off,int whence)259 static int VSIFSeekLHelper( VSILFILE* fpVSIL, off64_t off, int whence )
260 {
261 if( off < 0 && whence == SEEK_CUR )
262 {
263 return VSIFSeekL(fpVSIL, VSIFTellL(fpVSIL) + off, SEEK_SET);
264 }
265 else if( off < 0 && whence == SEEK_END )
266 {
267 VSIFSeekL(fpVSIL, 0, SEEK_END);
268 return VSIFSeekL(fpVSIL, VSIFTellL(fpVSIL) + off, SEEK_SET);
269 }
270
271 return VSIFSeekL(fpVSIL, off, whence);
272 }
273
274 /************************************************************************/
275 /* VSIFopenHelper() */
276 /************************************************************************/
277
VSIFfopenHelper(const char * path,const char * mode)278 static VSILFILE* VSIFfopenHelper( const char *path, const char *mode )
279 {
280 VSILFILE* fpVSIL = VSIFOpenL(path, mode);
281 if( fpVSIL != nullptr )
282 {
283 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
284 oSetFiles.insert(fpVSIL);
285 oMapVSIToString[fpVSIL] = path;
286 }
287 return fpVSIL;
288 }
289
290 /************************************************************************/
291 /* getfdFromVSILFILE() */
292 /************************************************************************/
293
getfdFromVSILFILE(VSILFILE * fpVSIL)294 static int getfdFromVSILFILE( VSILFILE* fpVSIL )
295 {
296 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
297
298 int fd = 0;
299 std::map<VSILFILE*, int>::iterator oIter = oMapVSITofd.find(fpVSIL);
300 if( oIter != oMapVSITofd.end() )
301 fd = oIter->second;
302 else
303 {
304 fd = open("/dev/zero", O_RDONLY);
305 assert(fd >= 0);
306 oMapVSITofd[fpVSIL] = fd;
307 oMapfdToVSI[fd] = fpVSIL;
308 }
309 return fd;
310 }
311
312 /************************************************************************/
313 /* VSIFopenHelper() */
314 /************************************************************************/
315
VSIFopenHelper(const char * path,int flags)316 static int VSIFopenHelper( const char *path, int flags )
317 {
318 const char* pszMode = "rb";
319 if( (flags & 3) == O_RDONLY )
320 pszMode = "rb";
321 else if( (flags & 3) == O_WRONLY )
322 {
323 if( flags & O_APPEND )
324 pszMode = "ab";
325 else
326 pszMode = "wb";
327 }
328 else
329 {
330 if( flags & O_APPEND )
331 pszMode = "ab+";
332 else
333 pszMode = "rb+";
334 }
335 VSILFILE* fpVSIL = VSIFfopenHelper(path, pszMode );
336 int fd = 0;
337 if( fpVSIL != nullptr )
338 {
339 if( flags & O_TRUNC )
340 {
341 VSIFTruncateL(fpVSIL, 0);
342 VSIFSeekL(fpVSIL, 0, SEEK_SET);
343 }
344 fd = getfdFromVSILFILE(fpVSIL);
345 }
346 else
347 fd = -1;
348 return fd;
349 }
350
351 /************************************************************************/
352 /* GET_DEBUG_VSIPRELOAD_COND() */
353 /************************************************************************/
354
GET_DEBUG_VSIPRELOAD_COND(const char * path)355 static bool GET_DEBUG_VSIPRELOAD_COND( const char* path )
356 {
357 return
358 DEBUG_VSIPRELOAD &&
359 // cppcheck-suppress knownConditionTrueFalse
360 (!DEBUG_VSIPRELOAD_ONLY_VSIL || STARTS_WITH(path, "/vsi"));
361 }
362
GET_DEBUG_VSIPRELOAD_COND(VSILFILE * fpVSIL)363 static bool GET_DEBUG_VSIPRELOAD_COND(VSILFILE* fpVSIL)
364 {
365 // cppcheck-suppress knownConditionTrueFalse
366 return DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || fpVSIL != nullptr);
367 }
368
GET_DEBUG_VSIPRELOAD_COND(VSIDIRPreload * dirP)369 static bool GET_DEBUG_VSIPRELOAD_COND(VSIDIRPreload* dirP)
370 {
371 return
372 DEBUG_VSIPRELOAD &&
373 // cppcheck-suppress knownConditionTrueFalse
374 (!DEBUG_VSIPRELOAD_ONLY_VSIL ||
375 oSetVSIDIRPreload.find(dirP) != oSetVSIDIRPreload.end());
376 }
377
378 /************************************************************************/
379 /* copyVSIStatBufLToBuf() */
380 /************************************************************************/
381
copyVSIStatBufLToBuf(VSIStatBufL * bufSrc,struct stat * buf)382 static void copyVSIStatBufLToBuf( VSIStatBufL* bufSrc, struct stat *buf )
383 {
384 buf->st_dev = bufSrc->st_dev;
385 buf->st_ino = bufSrc->st_ino;
386 // S_IXUSR | S_IXGRP | S_IXOTH;
387 buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH;
388 buf->st_nlink = 1; // bufSrc->st_nlink;
389 buf->st_uid = bufSrc->st_uid;
390 buf->st_gid = bufSrc->st_gid;
391 buf->st_rdev = bufSrc->st_rdev;
392 buf->st_size = bufSrc->st_size;
393 buf->st_blksize = bufSrc->st_blksize;
394 buf->st_blocks = bufSrc->st_blocks;
395 buf->st_atime = bufSrc->st_atime;
396 buf->st_mtime = bufSrc->st_mtime;
397 buf->st_ctime = bufSrc->st_ctime;
398 }
399
400 /************************************************************************/
401 /* copyVSIStatBufLToBuf64() */
402 /************************************************************************/
403
copyVSIStatBufLToBuf64(VSIStatBufL * bufSrc,struct stat64 * buf)404 static void copyVSIStatBufLToBuf64( VSIStatBufL *bufSrc, struct stat64 *buf )
405 {
406 buf->st_dev = bufSrc->st_dev;
407 buf->st_ino = bufSrc->st_ino;
408 // S_IXUSR | S_IXGRP | S_IXOTH;
409 buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH;
410 buf->st_nlink = 1; // bufSrc->st_nlink;
411 buf->st_uid = bufSrc->st_uid;
412 buf->st_gid = bufSrc->st_gid;
413 buf->st_rdev = bufSrc->st_rdev;
414 buf->st_size = bufSrc->st_size;
415 buf->st_blksize = bufSrc->st_blksize;
416 buf->st_blocks = bufSrc->st_blocks;
417 buf->st_atime = bufSrc->st_atime;
418 buf->st_mtime = bufSrc->st_mtime;
419 buf->st_ctime = bufSrc->st_ctime;
420 }
421
422 /************************************************************************/
423 /* fopen() */
424 /************************************************************************/
425
fopen(const char * path,const char * mode)426 FILE CPL_DLL *fopen( const char *path, const char *mode )
427 {
428 myinit();
429 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
430 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fopen(%s, %s)\n", path, mode);
431 FILE* ret;
432 if( STARTS_WITH(path, "/vsi") )
433 ret = (FILE*) VSIFfopenHelper(path, mode);
434 else
435 ret = pfnfopen(path, mode);
436 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fopen() = %p\n", ret);
437 return ret;
438 }
439
440 /************************************************************************/
441 /* fopen64() */
442 /************************************************************************/
443
fopen64(const char * path,const char * mode)444 FILE CPL_DLL *fopen64( const char *path, const char *mode )
445 {
446 myinit();
447 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
448 if( DEBUG_VSIPRELOAD_COND )
449 fprintf(stderr, "fopen64(%s, %s)\n", path, mode);
450 FILE* ret;
451 if( STARTS_WITH(path, "/vsi") )
452 ret = (FILE*) VSIFfopenHelper(path, mode);
453 else
454 ret = pfnfopen64(path, mode);
455 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fopen64() = %p\n", ret);
456 return ret;
457 }
458
459 /************************************************************************/
460 /* fread() */
461 /************************************************************************/
462
fread(void * ptr,size_t size,size_t nmemb,FILE * stream)463 size_t CPL_DLL fread( void *ptr, size_t size, size_t nmemb, FILE *stream )
464 {
465 myinit();
466 VSILFILE* fpVSIL = getVSILFILE(stream);
467 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
468 if( DEBUG_VSIPRELOAD_COND )
469 fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d)\n",
470 stream, static_cast<int>(size), static_cast<int>(nmemb));
471 size_t ret = 0;
472 if( fpVSIL )
473 ret = VSIFReadL(ptr, size, nmemb, fpVSIL);
474 else
475 ret = pfnfread(ptr, size, nmemb, stream);
476 if( DEBUG_VSIPRELOAD_COND )
477 fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d) -> %d\n",
478 stream, static_cast<int>(size), static_cast<int>(nmemb),
479 static_cast<int>(ret));
480 return ret;
481 }
482
483 /************************************************************************/
484 /* fwrite() */
485 /************************************************************************/
486
fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream)487 size_t CPL_DLL fwrite( const void *ptr, size_t size, size_t nmemb, FILE *stream )
488 {
489 myinit();
490 VSILFILE* fpVSIL = getVSILFILE(stream);
491 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
492 if( DEBUG_VSIPRELOAD_COND )
493 fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d)\n",
494 stream, static_cast<int>(size), static_cast<int>(nmemb));
495 size_t ret = 0;
496 if( fpVSIL != nullptr )
497 ret = VSIFWriteL(ptr, size, nmemb, fpVSIL);
498 else
499 ret = pfnfwrite(ptr, size, nmemb, stream);
500 if( DEBUG_VSIPRELOAD_COND )
501 fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d) -> %d\n",
502 stream, static_cast<int>(size), static_cast<int>(nmemb),
503 static_cast<int>(ret));
504 return ret;
505 }
506
507 /************************************************************************/
508 /* fclose() */
509 /************************************************************************/
510
fclose(FILE * stream)511 int CPL_DLL fclose( FILE *stream )
512 {
513 myinit();
514 VSILFILE* fpVSIL = getVSILFILE(stream);
515 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
516 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fclose(stream=%p)\n", stream);
517 if( fpVSIL != nullptr )
518 {
519 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
520
521 int ret = VSIFCloseL(fpVSIL);
522 oMapVSIToString.erase(fpVSIL);
523 oSetFiles.erase(fpVSIL);
524
525 std::map<VSILFILE*, int>::iterator oIter = oMapVSITofd.find(fpVSIL);
526 if( oIter != oMapVSITofd.end() )
527 {
528 int fd = oIter->second;
529 pfnclose(fd);
530 oMapVSITofd.erase(oIter);
531 oMapfdToVSI.erase(fd);
532 }
533
534 return ret;
535 }
536 else
537 return pfnfclose(stream);
538 }
539
540 /************************************************************************/
541 /* __xstat() */
542 /************************************************************************/
543
__xstat(int ver,const char * path,struct stat * buf)544 int CPL_DLL __xstat( int ver, const char *path, struct stat *buf )
545 {
546 myinit();
547 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
548 if( DEBUG_VSIPRELOAD && (!osCurDir.empty() && path[0] != '/') )
549 DEBUG_VSIPRELOAD_COND = 1;
550 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__xstat(%s)\n", path);
551 if( (!osCurDir.empty() && path[0] != '/') || STARTS_WITH(path, "/vsi") )
552 {
553 VSIStatBufL sStatBufL;
554 std::string newpath;
555 if( (!osCurDir.empty() && path[0] != '/') )
556 {
557 newpath = CPLFormFilename(osCurDir.c_str(), path, nullptr);
558 path = newpath.c_str();
559 }
560 const int ret = VSIStatL(path, &sStatBufL);
561 sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(path));
562 if( ret == 0 )
563 {
564 copyVSIStatBufLToBuf(&sStatBufL, buf);
565 if( DEBUG_VSIPRELOAD_COND )
566 fprintf(stderr,
567 "__xstat(%s) ret = 0, mode = %d, size=%d\n",
568 path, sStatBufL.st_mode,
569 static_cast<int>(sStatBufL.st_size));
570 }
571 return ret;
572 }
573 else
574 {
575 int ret = pfn__xstat(ver, path, buf);
576 if( ret == 0 )
577 {
578 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr,
579 "__xstat ret = 0, mode = %d\n", buf->st_mode);
580 }
581 return ret;
582 }
583 }
584
585 /************************************************************************/
586 /* __lxstat() */
587 /************************************************************************/
588
__lxstat(int ver,const char * path,struct stat * buf)589 int CPL_DLL __lxstat( int ver, const char *path, struct stat *buf )
590 {
591 myinit();
592 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
593 if( DEBUG_VSIPRELOAD && (!osCurDir.empty() && path[0] != '/') )
594 DEBUG_VSIPRELOAD_COND = 1;
595 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__lxstat(%s)\n", path);
596 if( (!osCurDir.empty() && path[0] != '/') || STARTS_WITH(path, "/vsi") )
597 {
598 VSIStatBufL sStatBufL;
599 std::string newpath;
600 if( (!osCurDir.empty() && path[0] != '/') )
601 {
602 newpath = CPLFormFilename(osCurDir.c_str(), path, nullptr);
603 path = newpath.c_str();
604 }
605 const int ret = VSIStatL(path, &sStatBufL);
606 sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(path));
607 if( ret == 0 )
608 {
609 copyVSIStatBufLToBuf(&sStatBufL, buf);
610 if( DEBUG_VSIPRELOAD_COND )
611 fprintf(stderr,
612 "__lxstat(%s) ret = 0, mode = %d, size=%d\n",
613 path, sStatBufL.st_mode,
614 static_cast<int>(sStatBufL.st_size));
615 }
616 return ret;
617 }
618 else
619 {
620 int ret = pfn__lxstat(ver, path, buf);
621 if( ret == 0 )
622 {
623 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr,
624 "__lxstat ret = 0, mode = %d\n", buf->st_mode);
625 }
626 return ret;
627 }
628 }
629
630 /************************************************************************/
631 /* __xstat64() */
632 /************************************************************************/
633
__xstat64(int ver,const char * path,struct stat64 * buf)634 int CPL_DLL __xstat64( int ver, const char *path, struct stat64 *buf )
635 {
636 myinit();
637 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
638 if( DEBUG_VSIPRELOAD && (!osCurDir.empty() && path[0] != '/') )
639 DEBUG_VSIPRELOAD_COND = 1;
640 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__xstat64(%s)\n", path);
641 if( (!osCurDir.empty() && path[0] != '/') || STARTS_WITH(path, "/vsi") )
642 {
643 VSIStatBufL sStatBufL;
644 std::string newpath;
645 if( (!osCurDir.empty() && path[0] != '/') )
646 {
647 newpath = CPLFormFilename(osCurDir.c_str(), path, nullptr);
648 path = newpath.c_str();
649 }
650 const int ret = VSIStatL(path, &sStatBufL);
651 sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(path));
652 if( ret == 0 )
653 {
654 copyVSIStatBufLToBuf64(&sStatBufL, buf);
655 if( DEBUG_VSIPRELOAD_COND )
656 fprintf(stderr,
657 "__xstat64(%s) ret = 0, mode = %d, size = %d\n",
658 path, buf->st_mode, static_cast<int>(buf->st_size));
659 }
660 return ret;
661 }
662 else
663 return pfn__xstat64(ver, path, buf);
664 }
665
666 /************************************************************************/
667 /* fseeko64() */
668 /************************************************************************/
669
fseeko64(FILE * stream,off64_t off,int whence)670 int CPL_DLL fseeko64( FILE *stream, off64_t off, int whence )
671 {
672 myinit();
673 VSILFILE* fpVSIL = getVSILFILE(stream);
674 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
675 if( DEBUG_VSIPRELOAD_COND )
676 fprintf(stderr, "fseeko64(stream=%p, off=%d, whence=%d)\n",
677 stream, static_cast<int>(off), whence);
678 if( fpVSIL != nullptr )
679 return VSIFSeekLHelper(fpVSIL, off, whence);
680 else
681 return pfnfseeko64(stream, off, whence);
682 }
683
684 /************************************************************************/
685 /* fseeko() */
686 /************************************************************************/
687
fseeko(FILE * stream,off_t off,int whence)688 int CPL_DLL fseeko( FILE *stream, off_t off, int whence )
689 {
690 myinit();
691 VSILFILE* fpVSIL = getVSILFILE(stream);
692 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
693 if( DEBUG_VSIPRELOAD_COND )
694 fprintf(stderr, "fseeko(stream=%p, off=%d, whence=%d)\n",
695 stream, static_cast<int>(off), whence);
696 if( fpVSIL != nullptr )
697 return VSIFSeekLHelper(fpVSIL, off, whence);
698 else
699 return pfnfseeko64(stream, off, whence);
700 }
701
702 /************************************************************************/
703 /* fseek() */
704 /************************************************************************/
705
fseek(FILE * stream,off_t off,int whence)706 int CPL_DLL fseek( FILE *stream, off_t off, int whence )
707 {
708 myinit();
709 VSILFILE* fpVSIL = getVSILFILE(stream);
710 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
711 if( DEBUG_VSIPRELOAD_COND )
712 fprintf(stderr, "fseek(stream=%p, off=%d, whence=%d)\n",
713 stream, static_cast<int>(off), whence);
714 if( fpVSIL != nullptr )
715 return VSIFSeekLHelper(fpVSIL, off, whence);
716 else
717 return pfnfseek(stream, off, whence);
718 }
719
720 /************************************************************************/
721 /* ftello64() */
722 /************************************************************************/
723
ftello64(FILE * stream)724 off64_t CPL_DLL ftello64( FILE *stream )
725 {
726 myinit();
727 VSILFILE* fpVSIL = getVSILFILE(stream);
728 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
729 if( DEBUG_VSIPRELOAD_COND )
730 fprintf(stderr, "ftello64(stream=%p)\n", stream);
731 if( fpVSIL != nullptr )
732 return VSIFTellL(fpVSIL);
733 else
734 return pfnftello64(stream);
735 }
736
737 /************************************************************************/
738 /* ftello() */
739 /************************************************************************/
740
ftello(FILE * stream)741 off_t CPL_DLL ftello( FILE *stream )
742 {
743 myinit();
744 VSILFILE* fpVSIL = getVSILFILE(stream);
745 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
746 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ftello(stream=%p)\n", stream);
747 if( fpVSIL != nullptr )
748 return VSIFTellL(fpVSIL);
749 else
750 return pfnftello64(stream);
751 }
752
753 /************************************************************************/
754 /* ftell() */
755 /************************************************************************/
756
ftell(FILE * stream)757 off_t CPL_DLL ftell( FILE *stream )
758 {
759 myinit();
760 VSILFILE* fpVSIL = getVSILFILE(stream);
761 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
762 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ftell(stream=%p)\n", stream);
763 if( fpVSIL != nullptr )
764 return VSIFTellL(fpVSIL);
765 else
766 return pfnftell(stream);
767 }
768
769 /************************************************************************/
770 /* feof() */
771 /************************************************************************/
772
feof(FILE * stream)773 int CPL_DLL feof( FILE *stream )
774 {
775 myinit();
776 VSILFILE* fpVSIL = getVSILFILE(stream);
777 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
778 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "feof(stream=%p)\n", stream);
779 if( fpVSIL != nullptr )
780 return VSIFEofL(fpVSIL);
781 else
782 return pfnfeof(stream);
783 }
784
785 /************************************************************************/
786 /* rewind() */
787 /************************************************************************/
788
rewind(FILE * stream)789 void CPL_DLL rewind( FILE *stream )
790 {
791 fseek(stream, 0, SEEK_SET);
792 }
793
794 /************************************************************************/
795 /* fflush() */
796 /************************************************************************/
797
fflush(FILE * stream)798 int CPL_DLL fflush( FILE *stream )
799 {
800 myinit();
801 VSILFILE* fpVSIL = getVSILFILE(stream);
802 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
803 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fflush(stream=%p)\n", stream);
804 if( fpVSIL != nullptr )
805 return 0;
806 else
807 return pfnfflush(stream);
808 }
809
810 /************************************************************************/
811 /* fgetpos() */
812 /************************************************************************/
813
fgetpos(FILE * stream,fpos_t * pos)814 int CPL_DLL fgetpos( FILE *stream, fpos_t *pos )
815 {
816 myinit();
817 VSILFILE* fpVSIL = getVSILFILE(stream);
818 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
819 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fgetpos(stream=%p)\n", stream);
820 if( fpVSIL != nullptr )
821 {
822 fprintf(stderr, "fgetpos() unimplemented for VSILFILE\n");
823 return -1; // FIXME
824 }
825 else
826 return pfnfgetpos(stream, pos);
827 }
828
829 /************************************************************************/
830 /* fsetpos() */
831 /************************************************************************/
832
fsetpos(FILE * stream,fpos_t * pos)833 int CPL_DLL fsetpos( FILE *stream, fpos_t *pos )
834 {
835 myinit();
836 VSILFILE* fpVSIL = getVSILFILE(stream);
837 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
838 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fsetpos(stream=%p)\n", stream);
839 if( fpVSIL != nullptr )
840 {
841 fprintf(stderr, "fsetpos() unimplemented for VSILFILE\n");
842 return -1; // FIXME
843 }
844 else
845 return pfnfsetpos(stream, pos);
846 }
847
848 /************************************************************************/
849 /* fileno() */
850 /************************************************************************/
851
fileno(FILE * stream)852 int CPL_DLL fileno( FILE *stream )
853 {
854 myinit();
855 VSILFILE* fpVSIL = getVSILFILE(stream);
856 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
857 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fileno(stream=%p)\n", stream);
858 int fd = 0;
859 if( fpVSIL != nullptr )
860 fd = getfdFromVSILFILE(fpVSIL);
861 else
862 fd = pfnfileno(stream);
863 if( DEBUG_VSIPRELOAD_COND )
864 fprintf(stderr, "fileno(stream=%p) = %d\n", stream, fd);
865 return fd;
866 }
867
868 /************************************************************************/
869 /* ferror() */
870 /************************************************************************/
871
ferror(FILE * stream)872 int CPL_DLL ferror( FILE *stream )
873 {
874 myinit();
875 VSILFILE* fpVSIL = getVSILFILE(stream);
876 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
877 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ferror(stream=%p)\n", stream);
878 if( fpVSIL != nullptr )
879 {
880 fprintf(stderr, "ferror() unimplemented for VSILFILE\n");
881 return 0; // FIXME ?
882 }
883 else
884 return pfnferror(stream);
885 }
886
887 /************************************************************************/
888 /* clearerr() */
889 /************************************************************************/
890
clearerr(FILE * stream)891 void CPL_DLL clearerr( FILE *stream )
892 {
893 myinit();
894 VSILFILE* fpVSIL = getVSILFILE(stream);
895 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
896 if( DEBUG_VSIPRELOAD_COND )
897 fprintf(stderr, "clearerr(stream=%p)\n", stream);
898 if( fpVSIL != nullptr )
899 {
900 fprintf(stderr, "clearerr() unimplemented for VSILFILE\n");
901 }
902 else
903 pfnclearerr(stream);
904 }
905
906 /************************************************************************/
907 /* fdopen() */
908 /************************************************************************/
909
fdopen(int fd,const char * mode)910 FILE CPL_DLL * fdopen( int fd, const char *mode )
911 {
912 myinit();
913 VSILFILE* fpVSIL = getVSILFILE(fd);
914 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
915 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fdopen(fd=%d)\n", fd);
916 if( fpVSIL != nullptr )
917 {
918 fprintf(stderr, "fdopen() unimplemented for VSILFILE\n");
919 return nullptr; // FIXME ?
920 }
921 else
922 return pfnfdopen(fd, mode);
923 }
924
925 /************************************************************************/
926 /* freopen() */
927 /************************************************************************/
928
freopen(const char * path,const char * mode,FILE * stream)929 FILE CPL_DLL *freopen( const char *path, const char *mode, FILE *stream )
930 {
931 myinit();
932 VSILFILE* fpVSIL = getVSILFILE(stream);
933 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
934 if( DEBUG_VSIPRELOAD_COND )
935 fprintf(stderr, "freopen(path=%s,mode=%s,stream=%p)\n",
936 path, mode, stream);
937 if( fpVSIL != nullptr )
938 {
939 fprintf(stderr, "freopen() unimplemented for VSILFILE\n");
940 return nullptr; // FIXME ?
941 }
942 else
943 return pfnfreopen(path, mode, stream);
944 }
945
946 /************************************************************************/
947 /* open() */
948 /************************************************************************/
949
open(const char * path,int flags,...)950 int CPL_DLL open( const char *path, int flags, ... )
951 {
952 myinit();
953 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
954 if( DEBUG_VSIPRELOAD && !osCurDir.empty() && path[0] != '/' )
955 DEBUG_VSIPRELOAD_COND = 1;
956 if( DEBUG_VSIPRELOAD_COND )
957 {
958 if( !osCurDir.empty() && path[0] != '/' )
959 fprintf(stderr, "open(%s)\n",
960 CPLFormFilename(osCurDir.c_str(), path, nullptr));
961 else
962 fprintf(stderr, "open(%s)\n", path);
963 }
964
965 va_list args;
966 va_start(args, flags);
967 mode_t mode = va_arg(args, mode_t);
968 int fd = 0;
969 if( !osCurDir.empty() && path[0] != '/' &&
970 (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
971 {
972 VSIStatBufL sStatBufL;
973 char* newname =
974 const_cast<char *>(CPLFormFilename(osCurDir.c_str(), path, nullptr));
975 if( strchr(osCurDir.c_str(), '/') != nullptr && strcmp(path, "..") == 0 )
976 {
977 char* lastslash = strrchr(newname, '/');
978 if( lastslash != nullptr )
979 {
980 *lastslash = 0;
981 lastslash = strrchr(newname, '/');
982 if( lastslash != nullptr )
983 *lastslash = 0;
984 }
985 }
986 if( VSIStatL(newname, &sStatBufL) == 0 &&
987 S_ISDIR(sStatBufL.st_mode) )
988 {
989 fd = open("/dev/zero", O_RDONLY);
990 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
991 oMapDirFdToName[fd] = newname;
992 }
993 else
994 fd = -1;
995 }
996 else if( STARTS_WITH(path, "/vsi") )
997 fd = VSIFopenHelper(path, flags);
998 else
999 fd = pfnopen(path, flags, mode);
1000 va_end(args);
1001 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "open(%s) = %d\n", path, fd);
1002 return fd;
1003 }
1004
1005 /************************************************************************/
1006 /* open64() */
1007 /************************************************************************/
1008
open64(const char * path,int flags,...)1009 int CPL_DLL open64( const char *path, int flags, ... )
1010 {
1011 myinit();
1012 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
1013 if( DEBUG_VSIPRELOAD && !osCurDir.empty() && path[0] != '/' )
1014 DEBUG_VSIPRELOAD_COND = 1;
1015 if( DEBUG_VSIPRELOAD_COND )
1016 {
1017 if( !osCurDir.empty() && path[0] != '/' )
1018 fprintf(stderr, "open64(%s)\n",
1019 CPLFormFilename(osCurDir.c_str(), path, nullptr));
1020 else
1021 fprintf(stderr, "open64(%s)\n", path);
1022 }
1023
1024 va_list args;
1025 va_start(args, flags);
1026 mode_t mode = va_arg(args, mode_t);
1027 int fd = 0;
1028 if( !osCurDir.empty() && path[0] != '/' &&
1029 (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
1030 {
1031 VSIStatBufL sStatBufL;
1032 char* newname =
1033 const_cast<char *>(CPLFormFilename(osCurDir.c_str(), path, nullptr));
1034 if( strchr(osCurDir.c_str(), '/') != nullptr && strcmp(path, "..") == 0 )
1035 {
1036 char* lastslash = strrchr(newname, '/');
1037 if( lastslash != nullptr )
1038 {
1039 *lastslash = 0;
1040 lastslash = strrchr(newname, '/');
1041 if( lastslash != nullptr )
1042 *lastslash = 0;
1043 }
1044 }
1045 if( VSIStatL(newname, &sStatBufL) == 0 &&
1046 S_ISDIR(sStatBufL.st_mode) )
1047 {
1048 fd = open("/dev/zero", O_RDONLY);
1049 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
1050 oMapDirFdToName[fd] = newname;
1051 }
1052 else
1053 fd = -1;
1054 }
1055 else if( STARTS_WITH(path, "/vsi") )
1056 fd = VSIFopenHelper(path, flags);
1057 else
1058 fd = pfnopen64(path, flags, mode);
1059 va_end(args);
1060 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "open64(%s) = %d\n", path, fd);
1061 return fd;
1062 }
1063
1064 /************************************************************************/
1065 /* creat() */
1066 /************************************************************************/
1067
creat(const char * path,mode_t mode)1068 int CPL_DLL creat( const char *path, mode_t mode )
1069 {
1070 return open64(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
1071 }
1072
1073 /************************************************************************/
1074 /* close() */
1075 /************************************************************************/
1076
close(int fd)1077 int CPL_DLL close( int fd )
1078 {
1079 myinit();
1080 VSILFILE* fpVSIL = getVSILFILE(fd);
1081 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1082 {
1083 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1084 assert( oMapfdToVSIDIRPreload.find(fd) == oMapfdToVSIDIRPreload.end() );
1085
1086 // cppcheck-suppress redundantIfRemove
1087 if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
1088 {
1089 oMapDirFdToName.erase(fd);
1090 if( DEBUG_VSIPRELOAD )
1091 DEBUG_VSIPRELOAD_COND = 1;
1092 }
1093 }
1094 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "close(fd=%d)\n", fd);
1095 if( fpVSIL != nullptr )
1096 {
1097 VSIFCloseL(fpVSIL);
1098 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1099 oSetFiles.erase(fpVSIL);
1100 pfnclose(oMapVSITofd[fpVSIL]);
1101 oMapVSITofd.erase(fpVSIL);
1102 oMapfdToVSI.erase(fd);
1103 oMapVSIToString.erase(fpVSIL);
1104 return 0;
1105 }
1106 else
1107 return pfnclose(fd);
1108 }
1109
1110 /************************************************************************/
1111 /* read() */
1112 /************************************************************************/
1113
read(int fd,void * buf,size_t count)1114 ssize_t CPL_DLL read( int fd, void *buf, size_t count )
1115 {
1116 myinit();
1117 VSILFILE* fpVSIL = getVSILFILE(fd);
1118 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1119 if( DEBUG_VSIPRELOAD_COND )
1120 fprintf(stderr, "read(fd=%d, count=%d)\n",
1121 fd, static_cast<int>(count));
1122 ssize_t ret = 0;
1123 if( fpVSIL != nullptr )
1124 ret = VSIFReadL(buf, 1, count, fpVSIL);
1125 else
1126 ret = pfnread(fd, buf, count);
1127 if( DEBUG_VSIPRELOAD_COND && DEBUG_OUTPUT_READ && ret < 40 )
1128 {
1129 fprintf(stderr, "read() : ");
1130 for( int i = 0; i < ret; i++ )
1131 {
1132 if( ((unsigned char*)buf)[i] >= 'A' &&
1133 ((unsigned char*)buf)[i] <= 'Z' )
1134 fprintf(stderr, "%c ", ((unsigned char*)buf)[i]);
1135 else
1136 fprintf(stderr, "\\%02X ", ((unsigned char*)buf)[i]);
1137 }
1138 fprintf(stderr, "\n");
1139 }
1140 if( DEBUG_VSIPRELOAD_COND )
1141 fprintf(stderr, "read() -> %d\n", static_cast<int>(ret));
1142 return ret;
1143 }
1144
1145 /************************************************************************/
1146 /* write() */
1147 /************************************************************************/
1148
write(int fd,const void * buf,size_t count)1149 ssize_t CPL_DLL write( int fd, const void *buf, size_t count )
1150 {
1151 myinit();
1152 VSILFILE* fpVSIL = getVSILFILE(fd);
1153 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1154 if( DEBUG_VSIPRELOAD_COND )
1155 fprintf(stderr, "write(fd=%d, count=%d)\n",
1156 fd, static_cast<int>(count));
1157 if( fpVSIL != nullptr )
1158 return VSIFWriteL(buf, 1, count, fpVSIL);
1159 else
1160 return pfnwrite(fd, buf, count);
1161 }
1162
1163 /************************************************************************/
1164 /* fsync() */
1165 /************************************************************************/
1166
fsync(int fd)1167 int CPL_DLL fsync( int fd )
1168 {
1169 myinit();
1170 VSILFILE* fpVSIL = getVSILFILE(fd);
1171 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1172 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fsync(fd=%d)\n", fd);
1173 if( fpVSIL != nullptr )
1174 return 0;
1175 else
1176 return pfnfsync(fd);
1177 }
1178
1179 /************************************************************************/
1180 /* fdatasync() */
1181 /************************************************************************/
1182
fdatasync(int fd)1183 int CPL_DLL fdatasync( int fd )
1184 {
1185 myinit();
1186 VSILFILE* fpVSIL = getVSILFILE(fd);
1187 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1188 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fdatasync(fd=%d)\n", fd);
1189 if( fpVSIL != nullptr )
1190 return 0;
1191 else
1192 return pfnfdatasync(fd);
1193 }
1194
1195 /************************************************************************/
1196 /* __fxstat() */
1197 /************************************************************************/
1198
__fxstat(int ver,int fd,struct stat * buf)1199 int CPL_DLL __fxstat( int ver, int fd, struct stat *buf )
1200 {
1201 myinit();
1202 VSILFILE* fpVSIL = getVSILFILE(fd);
1203 std::string name;
1204 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1205 {
1206 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
1207 if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
1208 {
1209 name = oMapDirFdToName[fd];
1210 if( DEBUG_VSIPRELOAD )
1211 DEBUG_VSIPRELOAD_COND = 1;
1212 }
1213 }
1214 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__fxstat(fd=%d)\n", fd);
1215 if( !name.empty() )
1216 {
1217 VSIStatBufL sStatBufL;
1218 if( DEBUG_VSIPRELOAD_COND )
1219 fprintf(stderr, "__fxstat(%s)\n", name.c_str());
1220 int ret = VSIStatL(name.c_str(), &sStatBufL);
1221 sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(name.c_str()));
1222 if( ret == 0 )
1223 {
1224 copyVSIStatBufLToBuf(&sStatBufL, buf);
1225 if( DEBUG_VSIPRELOAD_COND )
1226 fprintf(stderr,
1227 "__fxstat ret = 0, mode = %d, size = %d\n",
1228 sStatBufL.st_mode, static_cast<int>(sStatBufL.st_size));
1229 }
1230 return ret;
1231 }
1232 else if( fpVSIL != nullptr )
1233 {
1234 VSIStatBufL sStatBufL;
1235 {
1236 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1237 name = oMapVSIToString[fpVSIL];
1238 }
1239 int ret = VSIStatL(name.c_str(), &sStatBufL);
1240 sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(name.c_str()));
1241 if( ret == 0 )
1242 {
1243 copyVSIStatBufLToBuf(&sStatBufL, buf);
1244 if( DEBUG_VSIPRELOAD_COND )
1245 fprintf(stderr,
1246 "__fxstat ret = 0, mode = %d, size = %d\n",
1247 sStatBufL.st_mode, static_cast<int>(sStatBufL.st_size));
1248 }
1249 return ret;
1250 }
1251 else
1252 return pfn__fxstat(ver, fd, buf);
1253 }
1254
1255 /************************************************************************/
1256 /* __fxstat64() */
1257 /************************************************************************/
1258
__fxstat64(int ver,int fd,struct stat64 * buf)1259 int CPL_DLL __fxstat64( int ver, int fd, struct stat64 *buf )
1260 {
1261 myinit();
1262 VSILFILE* fpVSIL = getVSILFILE(fd);
1263 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1264 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__fxstat64(fd=%d)\n", fd);
1265 if( fpVSIL != nullptr )
1266 {
1267 VSIStatBufL sStatBufL;
1268 std::string name;
1269 {
1270 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1271 name = oMapVSIToString[fpVSIL];
1272 }
1273 int ret = VSIStatL(name.c_str(), &sStatBufL);
1274 sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(name.c_str()));
1275 if( ret == 0 )
1276 {
1277 copyVSIStatBufLToBuf64(&sStatBufL, buf);
1278 if( DEBUG_VSIPRELOAD_COND )
1279 fprintf(stderr,
1280 "__fxstat64 ret = 0, mode = %d, size = %d\n",
1281 buf->st_mode, static_cast<int>(buf->st_size));
1282 }
1283 return ret;
1284 }
1285 else
1286 return pfn__fxstat64(ver, fd, buf);
1287 }
1288
1289 /************************************************************************/
1290 /* __fxstatat() */
1291 /************************************************************************/
1292
1293 #ifdef HAVE_FSTATAT
__fxstatat(int ver,int dirfd,const char * pathname,struct stat * buf,int flags)1294 int CPL_DLL __fxstatat( int ver, int dirfd, const char *pathname, struct stat *buf,
1295 int flags )
1296 {
1297 myinit();
1298 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(pathname);
1299 if( DEBUG_VSIPRELOAD && !osCurDir.empty() )
1300 DEBUG_VSIPRELOAD_COND = 1;
1301 if( DEBUG_VSIPRELOAD_COND )
1302 fprintf(stderr, "__fxstatat(dirfd=%d,pathname=%s,flags=%d)\n",
1303 dirfd, pathname, flags);
1304
1305 if( !osCurDir.empty() || STARTS_WITH(pathname, "/vsi") )
1306 {
1307 VSIStatBufL sStatBufL;
1308 if( !osCurDir.empty() && dirfd == AT_FDCWD && pathname[0] != '/' )
1309 pathname = CPLFormFilename(osCurDir.c_str(), pathname, nullptr);
1310 const int ret = VSIStatL(pathname, &sStatBufL);
1311 sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(pathname));
1312 if( ret == 0 )
1313 {
1314 copyVSIStatBufLToBuf(&sStatBufL, buf);
1315 if( DEBUG_VSIPRELOAD_COND )
1316 fprintf(stderr,
1317 "__fxstatat(%s) ret = 0, mode = %d, size = %d\n",
1318 pathname, buf->st_mode, static_cast<int>(buf->st_size));
1319 }
1320 return ret;
1321 }
1322 else
1323 return pfn__fxstatat(ver, dirfd, pathname, buf, flags);
1324 }
1325 #endif
1326
1327 /************************************************************************/
1328 /* lseek() */
1329 /************************************************************************/
1330
lseek(int fd,off_t off,int whence)1331 off_t CPL_DLL lseek( int fd, off_t off, int whence )
1332 {
1333 myinit();
1334 off_t ret;
1335 VSILFILE* fpVSIL = getVSILFILE(fd);
1336 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1337 if( DEBUG_VSIPRELOAD_COND )
1338 fprintf(stderr,
1339 "lseek(fd=%d, off=%d, whence=%d)\n",
1340 fd, static_cast<int>(off), whence);
1341 if( fpVSIL != nullptr )
1342 {
1343 VSIFSeekLHelper(fpVSIL, off, whence);
1344 ret = VSIFTellL(fpVSIL);
1345 }
1346 else
1347 ret = pfnlseek(fd, off, whence);
1348 if( DEBUG_VSIPRELOAD_COND )
1349 fprintf(stderr, "lseek() -> ret = %d\n", static_cast<int>(ret));
1350 return ret;
1351 }
1352
1353 /************************************************************************/
1354 /* lseek64() */
1355 /************************************************************************/
1356
lseek64(int fd,off64_t off,int whence)1357 off64_t CPL_DLL lseek64( int fd, off64_t off, int whence )
1358 {
1359 myinit();
1360 off_t ret;
1361 VSILFILE* fpVSIL = getVSILFILE(fd);
1362 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1363 if( DEBUG_VSIPRELOAD_COND )
1364 fprintf(stderr,
1365 "lseek64(fd=%d, off=%d, whence=%d)\n",
1366 fd, static_cast<int>(off), whence);
1367 if( fpVSIL != nullptr )
1368 {
1369 VSIFSeekLHelper(fpVSIL, off, whence);
1370 ret = VSIFTellL(fpVSIL);
1371 }
1372 else
1373 ret = pfnlseek64(fd, off, whence);
1374 if( DEBUG_VSIPRELOAD_COND )
1375 fprintf(stderr,
1376 "lseek64() -> ret = %d\n", static_cast<int>(ret));
1377 return ret;
1378 }
1379
1380 /************************************************************************/
1381 /* truncate() */
1382 /************************************************************************/
1383
truncate(const char * path,off_t length)1384 int CPL_DLL truncate( const char *path, off_t length )
1385 {
1386 myinit();
1387 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
1388 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "truncate(%s)\n", path);
1389
1390 int ret = 0;
1391 if( STARTS_WITH(path, "/vsi") )
1392 {
1393 VSILFILE* fpVSIL = VSIFOpenL(path, "wb+");
1394 if( fpVSIL )
1395 {
1396 ret = VSIFTruncateL(fpVSIL, length);
1397 VSIFCloseL(fpVSIL);
1398 }
1399 else
1400 ret = -1;
1401 }
1402 else
1403 ret = pfntruncate(path, length);
1404 return ret;
1405 }
1406
1407 /************************************************************************/
1408 /* ftruncate() */
1409 /************************************************************************/
1410
ftruncate(int fd,off_t length)1411 int CPL_DLL ftruncate( int fd, off_t length )
1412 {
1413 myinit();
1414 VSILFILE* fpVSIL = getVSILFILE(fd);
1415 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
1416 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ftruncate(fd=%d)\n", fd);
1417 int ret = 0;
1418 if( fpVSIL != nullptr )
1419 {
1420 ret = VSIFTruncateL(fpVSIL, length);
1421 }
1422 else
1423 ret = pfnftruncate(fd, length);
1424 return ret;
1425 }
1426
1427 /************************************************************************/
1428 /* opendir() */
1429 /************************************************************************/
1430
opendir(const char * name)1431 DIR CPL_DLL *opendir( const char *name )
1432 {
1433 myinit();
1434 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(name);
1435 if( DEBUG_VSIPRELOAD && !osCurDir.empty() )
1436 DEBUG_VSIPRELOAD_COND = 1;
1437 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "opendir(%s)\n", name);
1438
1439 DIR * ret;
1440 if( !osCurDir.empty() || STARTS_WITH(name, "/vsi") )
1441 {
1442 char** papszDir;
1443 if( !osCurDir.empty() && name[0] != '/' )
1444 name = CPLFormFilename(osCurDir.c_str(), name, nullptr);
1445 papszDir = VSIReadDir(name);
1446 if( papszDir == nullptr )
1447 {
1448 VSIStatBufL sStatBufL;
1449 if( VSIStatL(name, &sStatBufL) == 0 && S_ISDIR(sStatBufL.st_mode) )
1450 {
1451 papszDir = static_cast<char **>(CPLMalloc(sizeof(char*)));
1452 papszDir[0] = nullptr;
1453 }
1454 }
1455 if( papszDir == nullptr )
1456 ret = nullptr;
1457 else
1458 {
1459 VSIDIRPreload* mydir = static_cast<VSIDIRPreload *>(malloc(sizeof(VSIDIRPreload)));
1460 mydir->pszDirname = CPLStrdup(name);
1461 mydir->papszDir = papszDir;
1462 mydir->nIter = 0;
1463 mydir->fd = -1;
1464 ret = (DIR*)mydir;
1465 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1466 oSetVSIDIRPreload.insert(mydir);
1467 }
1468 }
1469 else
1470 {
1471 ret = pfnopendir(name);
1472 }
1473 if( DEBUG_VSIPRELOAD_COND )
1474 fprintf(stderr, "opendir(%s) -> %p\n", name, ret);
1475 return ret;
1476 }
1477
1478 /************************************************************************/
1479 /* filldir() */
1480 /************************************************************************/
1481
filldir(VSIDIRPreload * mydir)1482 static bool filldir( VSIDIRPreload* mydir )
1483 {
1484 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(mydir);
1485 char* pszName = mydir->papszDir[mydir->nIter++];
1486 if( pszName == nullptr )
1487 return false;
1488 mydir->ent.d_ino = 0;
1489 mydir->ent.d_off = 0;
1490 mydir->ent.d_reclen = sizeof(mydir->ent);
1491 VSIStatBufL sStatBufL;
1492 CPL_IGNORE_RET_VAL(VSIStatL(CPLFormFilename(mydir->pszDirname, pszName, nullptr), &sStatBufL));
1493 if( DEBUG_VSIPRELOAD_COND && S_ISDIR(sStatBufL.st_mode) )
1494 fprintf(stderr, "%s is dir\n", pszName);
1495 mydir->ent.d_type = S_ISDIR(sStatBufL.st_mode) ? DT_DIR :
1496 S_ISREG(sStatBufL.st_mode) ? DT_REG :
1497 S_ISLNK(sStatBufL.st_mode) ? DT_LNK :
1498 DT_UNKNOWN;
1499 strncpy(mydir->ent.d_name, pszName, 256);
1500 mydir->ent.d_name[255] = '\0';
1501
1502 mydir->ent64.d_ino = 0;
1503 mydir->ent64.d_off = 0;
1504 mydir->ent64.d_reclen = sizeof(mydir->ent64);
1505 mydir->ent64.d_type = mydir->ent.d_type;
1506 strcpy(mydir->ent64.d_name, mydir->ent.d_name);
1507
1508 return true;
1509 }
1510
1511 /************************************************************************/
1512 /* readdir() */
1513 /************************************************************************/
1514
readdir(DIR * dirp)1515 struct dirent CPL_DLL *readdir( DIR *dirp )
1516 {
1517 myinit();
1518 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIRPreload*)dirp);
1519 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "readdir(%p)\n", dirp);
1520 if( oSetVSIDIRPreload.find((VSIDIRPreload*)dirp) != oSetVSIDIRPreload.end() )
1521 {
1522 VSIDIRPreload* mydir = (VSIDIRPreload*)dirp;
1523 if( !filldir(mydir) )
1524 return nullptr;
1525
1526 return &(mydir->ent);
1527 }
1528 else
1529 return pfnreaddir(dirp);
1530 }
1531
1532 /************************************************************************/
1533 /* readdir64() */
1534 /************************************************************************/
1535
readdir64(DIR * dirp)1536 struct dirent64 CPL_DLL *readdir64( DIR *dirp )
1537 {
1538 myinit();
1539 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIRPreload*)dirp);
1540 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "readdir64(%p)\n", dirp);
1541 if( oSetVSIDIRPreload.find((VSIDIRPreload*)dirp) != oSetVSIDIRPreload.end() )
1542 {
1543 VSIDIRPreload* mydir = (VSIDIRPreload*)dirp;
1544 if( !filldir(mydir) )
1545 return nullptr;
1546
1547 return &(mydir->ent64);
1548 }
1549 else
1550 return pfnreaddir64(dirp);
1551 }
1552
1553 /************************************************************************/
1554 /* closedir() */
1555 /************************************************************************/
1556
closedir(DIR * dirp)1557 int CPL_DLL closedir( DIR *dirp )
1558 {
1559 myinit();
1560 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIRPreload*)dirp);
1561 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "closedir(%p)\n", dirp);
1562 if( oSetVSIDIRPreload.find((VSIDIRPreload*)dirp) != oSetVSIDIRPreload.end() )
1563 {
1564 VSIDIRPreload* mydir = (VSIDIRPreload*)dirp;
1565 CPLFree(mydir->pszDirname);
1566 CSLDestroy(mydir->papszDir);
1567 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1568 if( mydir->fd >= 0 )
1569 {
1570 oMapfdToVSIDIRPreload.erase(mydir->fd);
1571 close(mydir->fd);
1572 }
1573 oSetVSIDIRPreload.erase(mydir);
1574 free(mydir);
1575 return 0;
1576 }
1577 else
1578 return pfnclosedir(dirp);
1579 }
1580
1581 /************************************************************************/
1582 /* dirfd() */
1583 /************************************************************************/
1584
dirfd(DIR * dirp)1585 int CPL_DLL dirfd( DIR *dirp )
1586 {
1587 myinit();
1588 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIRPreload*)dirp);
1589 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "dirfd(%p)\n", dirp);
1590 int ret = 0;
1591 if( oSetVSIDIRPreload.find((VSIDIRPreload*)dirp) != oSetVSIDIRPreload.end() )
1592 {
1593 VSIDIRPreload* mydir = (VSIDIRPreload*)dirp;
1594 if( mydir->fd < 0 )
1595 {
1596 mydir->fd = open("/dev/zero", O_RDONLY);
1597 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1598 oMapfdToVSIDIRPreload[mydir->fd] = mydir;
1599 }
1600 ret = mydir->fd;
1601 }
1602 else
1603 ret = pfndirfd(dirp);
1604 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "dirfd(%p) -> %d\n", dirp, ret);
1605 return ret;
1606 }
1607
1608 /************************************************************************/
1609 /* fchdir() */
1610 /************************************************************************/
1611
fchdir(int fd)1612 int CPL_DLL fchdir( int fd )
1613 {
1614 VSIDIRPreload* mydir = nullptr;
1615 {
1616 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
1617 if( oMapfdToVSIDIRPreload.find(fd) != oMapfdToVSIDIRPreload.end() )
1618 mydir = oMapfdToVSIDIRPreload[fd];
1619 }
1620 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(mydir);
1621 std::string name;
1622 {
1623 CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
1624 if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
1625 {
1626 name = oMapDirFdToName[fd];
1627 if( DEBUG_VSIPRELOAD )
1628 DEBUG_VSIPRELOAD_COND = 1;
1629 }
1630 }
1631 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fchdir(%d)\n", fd);
1632 if( !name.empty() )
1633 {
1634 osCurDir = name;
1635 if( DEBUG_VSIPRELOAD_COND )
1636 fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
1637 return 0;
1638 }
1639 else if( mydir != nullptr )
1640 {
1641 osCurDir = mydir->pszDirname;
1642 if( DEBUG_VSIPRELOAD_COND )
1643 fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
1644 return 0;
1645 }
1646 else
1647 {
1648 osCurDir = "";
1649 if( DEBUG_VSIPRELOAD_COND )
1650 fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
1651 return pfnfchdir(fd);
1652 }
1653 }
1654
1655 /************************************************************************/
1656 /* acl_extended_file() */
1657 /************************************************************************/
1658
1659 // #include <acl/acl.h>
1660 extern "C" int CPL_DLL acl_extended_file(const char *name);
1661 DECLARE_SYMBOL(acl_extended_file, int, (const char *name));
1662
acl_extended_file(const char * path)1663 int acl_extended_file( const char *path )
1664 {
1665 myinit();
1666 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
1667 if( DEBUG_VSIPRELOAD_COND )
1668 fprintf(stderr, "acl_extended_file(%s)\n", path);
1669 int ret = 0;
1670 if( STARTS_WITH(path, "/vsi") )
1671 ret = -1;
1672 else
1673 {
1674 if( pfnacl_extended_file == nullptr )
1675 pfnacl_extended_file =
1676 (fnacl_extended_fileType) dlsym(RTLD_NEXT, "acl_extended_file");
1677 if( pfnacl_extended_file == nullptr )
1678 ret = -1;
1679 else
1680 ret = pfnacl_extended_file(path);
1681 }
1682 return ret;
1683 }
1684
1685 /************************************************************************/
1686 /* getfilecon() */
1687 /************************************************************************/
1688
1689 // #include <selinux/selinux.h>
1690 extern "C" int CPL_DLL getfilecon(const char *name, void* con);
1691 DECLARE_SYMBOL(getfilecon, int, (const char *name, void* con));
1692
getfilecon(const char * path,void * con)1693 int getfilecon( const char *path, /*security_context_t **/ void* con )
1694 {
1695 myinit();
1696 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
1697 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "getfilecon(%s)\n", path);
1698 int ret = 0;
1699 if( STARTS_WITH(path, "/vsi") )
1700 {
1701 errno = ENOTSUP;
1702 ret = -1;
1703 }
1704 else
1705 {
1706 if( pfngetfilecon == nullptr )
1707 pfngetfilecon = (fngetfileconType) dlsym(RTLD_NEXT, "getfilecon");
1708 if( pfngetfilecon == nullptr )
1709 ret = -1;
1710 else
1711 ret = pfngetfilecon(path, con);
1712 }
1713 return ret;
1714 }
1715
1716 /************************************************************************/
1717 /* lgetfilecon() */
1718 /************************************************************************/
1719
1720 // #include <selinux/selinux.h>
1721 extern "C" int CPL_DLL lgetfilecon(const char *name, void* con);
1722 DECLARE_SYMBOL(lgetfilecon, int, (const char *name, void* con));
1723
lgetfilecon(const char * path,void * con)1724 int lgetfilecon(const char *path, /*security_context_t **/ void* con)
1725 {
1726 myinit();
1727 int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
1728 if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "lgetfilecon(%s)\n", path);
1729 int ret = 0;
1730 if( STARTS_WITH(path, "/vsi") )
1731 {
1732 errno = ENOTSUP;
1733 ret = -1;
1734 }
1735 else
1736 {
1737 if( pfnlgetfilecon == nullptr )
1738 pfnlgetfilecon =
1739 (fnlgetfileconType) dlsym(RTLD_NEXT, "lgetfilecon");
1740 if( pfnlgetfilecon == nullptr )
1741 ret = -1;
1742 else
1743 ret = pfnlgetfilecon(path, con);
1744 }
1745 return ret;
1746 }
1747