ultimatepp/bazaar/plugin/gdal/port/vsipreload.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

1682 lines
57 KiB
C++

/******************************************************************************
* $Id: vsipreload.cpp 28464 2015-02-12 14:40:34Z rouault $
*
* Project: CPL - Common Portability Library
* Purpose: Standalone shared library that can be LD_PRELOAD'ed as an overload of
* libc to enable VSI Virtual FILE API to be used with binaries using
* regular libc for I/O.
* Author: Even Rouault <even dot rouault at mines dash paris.org>
*
******************************************************************************
* Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
// WARNING: Linux glibc ONLY
// Might work with some adaptations (mainly around 64bit symbols) on other Unix systems
// Compile:
// g++ -Wall -fPIC port/vsipreload.cpp -shared -o vsipreload.so -Iport -L. -L.libs -lgdal
// Run:
// LD_PRELOAD=./vsipreload.so ....
// e.g:
// LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
// 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'
// LD_PRELOAD=./vsipreload.so ogrinfo /vsicurl/http://svn.osgeo.org/gdal/trunk/autotest/ogr/data/testavc -ro
// even non GDAL binaries :
// LD_PRELOAD=./vsipreload.so h5dump -d /x /vsicurl/http://download.osgeo.org/gdal/data/netcdf/utm-big-chunks.nc
// LD_PRELOAD=./vsipreload.so sqlite3 /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
// LD_PRELOAD=./vsipreload.so ls -al /vsicurl/http://download.osgeo.org/gdal/data/sqlite3
// LD_PRELOAD=./vsipreload.so find /vsicurl/http://download.osgeo.org/gdal/data/sqlite3
#define _GNU_SOURCE 1
#define _LARGEFILE64_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <dlfcn.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <set>
#include <map>
#include <string>
#include "cpl_vsi.h"
#include "cpl_multiproc.h"
#include "cpl_string.h"
#include "cpl_hash_set.h"
CPL_CVSID("$Id: vsipreload.cpp 28464 2015-02-12 14:40:34Z rouault $");
static int DEBUG_VSIPRELOAD = 0;
static int DEBUG_VSIPRELOAD_ONLY_VSIL = 1;
#define DEBUG_OUTPUT_READ 0
#ifndef NO_FSTATAT
#define HAVE_FSTATAT
#endif
#define DECLARE_SYMBOL(x, retType, args) \
typedef retType (*fn ## x ## Type)args;\
static fn ## x ## Type pfn ## x = NULL
DECLARE_SYMBOL(fopen, FILE*, (const char *path, const char *mode));
DECLARE_SYMBOL(fopen64, FILE*, (const char *path, const char *mode));
DECLARE_SYMBOL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
DECLARE_SYMBOL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
DECLARE_SYMBOL(fclose, int, (FILE *stream));
DECLARE_SYMBOL(__xstat, int, (int ver, const char *path, struct stat *buf));
DECLARE_SYMBOL(__lxstat, int, (int ver, const char *path, struct stat *buf));
DECLARE_SYMBOL(__xstat64, int, (int ver, const char *path, struct stat64 *buf));
DECLARE_SYMBOL(fseeko64, int, (FILE *stream, off64_t off, int whence));
DECLARE_SYMBOL(fseek, int, (FILE *stream, off_t off, int whence));
DECLARE_SYMBOL(ftello64, off64_t, (FILE *stream));
DECLARE_SYMBOL(ftell, off_t, (FILE *stream));
DECLARE_SYMBOL(feof, int, (FILE *stream));
DECLARE_SYMBOL(fflush, int, (FILE *stream));
DECLARE_SYMBOL(fgetpos, int, (FILE *stream, fpos_t *pos));
DECLARE_SYMBOL(fsetpos, int, (FILE *stream, fpos_t *pos));
DECLARE_SYMBOL(fileno, int, (FILE *stream));
DECLARE_SYMBOL(ferror, int, (FILE *stream));
DECLARE_SYMBOL(clearerr, void, (FILE *stream));
DECLARE_SYMBOL(fdopen, FILE*, (int fd, const char *mode));
DECLARE_SYMBOL(freopen, FILE*, (const char *path, const char *mode, FILE *stream));
DECLARE_SYMBOL(open, int, (const char *path, int flags, mode_t mode));
DECLARE_SYMBOL(open64, int, (const char *path, int flags, mode_t mode));
//DECLARE_SYMBOL(creat, int, (const char *path, mode_t mode));
DECLARE_SYMBOL(close, int, (int fd));
DECLARE_SYMBOL(read, ssize_t, (int fd, void *buf, size_t count));
DECLARE_SYMBOL(write, ssize_t, (int fd, const void *buf, size_t count));
DECLARE_SYMBOL(fsync, int, (int fd));
DECLARE_SYMBOL(fdatasync, int, (int fd));
DECLARE_SYMBOL(__fxstat, int, (int ver, int fd, struct stat *__stat_buf));
DECLARE_SYMBOL(__fxstat64, int, (int ver, int fd, struct stat64 *__stat_buf));
#ifdef HAVE_FSTATAT
DECLARE_SYMBOL(__fxstatat, int, (int ver, int dirfd, const char *pathname, struct stat *buf, int flags));
#endif
DECLARE_SYMBOL(lseek, off_t, (int fd, off_t off, int whence));
DECLARE_SYMBOL(lseek64, off64_t , (int fd, off64_t off, int whence));
DECLARE_SYMBOL(truncate, int, (const char *path, off_t length));
DECLARE_SYMBOL(ftruncate, int, (int fd, off_t length));
DECLARE_SYMBOL(opendir, DIR* , (const char *name));
DECLARE_SYMBOL(readdir, struct dirent*, (DIR *dirp));
DECLARE_SYMBOL(readdir64, struct dirent64*, (DIR *dirp));
DECLARE_SYMBOL(closedir, int, (DIR *dirp));
DECLARE_SYMBOL(dirfd, int, (DIR *dirp));
DECLARE_SYMBOL(fchdir, int, (int fd));
static CPLLock* hLock = NULL;
typedef struct
{
char* pszDirname;
char** papszDir;
int nIter;
struct dirent ent;
struct dirent64 ent64;
int fd;
} VSIDIR;
std::set<VSILFILE*> oSetFiles;
std::map<int, VSILFILE*> oMapfdToVSI;
std::map<VSILFILE*, int> oMapVSITofd;
std::map<VSILFILE*, std::string> oMapVSIToString;
std::set<VSIDIR*> oSetVSIDIR;
std::map<int, VSIDIR*> oMapfdToVSIDIR;
std::map<int, std::string> oMapDirFdToName;
std::string osCurDir;
/************************************************************************/
/* myinit() */
/************************************************************************/
#define LOAD_SYMBOL(x) \
pfn ## x = (fn ## x ## Type) dlsym(RTLD_NEXT, #x); \
assert(pfn ## x)
static void myinit(void)
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
if( pfnfopen64 != NULL ) return;
DEBUG_VSIPRELOAD = getenv("DEBUG_VSIPRELOAD") != NULL;
LOAD_SYMBOL(fopen);
LOAD_SYMBOL(fopen64);
LOAD_SYMBOL(fread);
LOAD_SYMBOL(fwrite);
LOAD_SYMBOL(fclose);
LOAD_SYMBOL(fseeko64);
LOAD_SYMBOL(fseek);
LOAD_SYMBOL(__xstat);
LOAD_SYMBOL(__lxstat);
LOAD_SYMBOL(__xstat64);
LOAD_SYMBOL(ftello64);
LOAD_SYMBOL(ftell);
LOAD_SYMBOL(feof);
LOAD_SYMBOL(fflush);
LOAD_SYMBOL(fgetpos);
LOAD_SYMBOL(fsetpos);
LOAD_SYMBOL(fileno);
LOAD_SYMBOL(ferror);
LOAD_SYMBOL(clearerr);
LOAD_SYMBOL(fdopen);
LOAD_SYMBOL(freopen);
LOAD_SYMBOL(open);
LOAD_SYMBOL(open64);
//LOAD_SYMBOL(creat);
LOAD_SYMBOL(close);
LOAD_SYMBOL(read);
LOAD_SYMBOL(write);
LOAD_SYMBOL(fsync);
LOAD_SYMBOL(fdatasync);
LOAD_SYMBOL(__fxstat);
LOAD_SYMBOL(__fxstat64);
#ifdef HAVE_FSTATAT
LOAD_SYMBOL(__fxstatat);
#endif
LOAD_SYMBOL(lseek);
LOAD_SYMBOL(lseek64);
LOAD_SYMBOL(truncate);
LOAD_SYMBOL(ftruncate);
LOAD_SYMBOL(opendir);
LOAD_SYMBOL(readdir);
LOAD_SYMBOL(readdir64);
LOAD_SYMBOL(closedir);
LOAD_SYMBOL(dirfd);
LOAD_SYMBOL(fchdir);
}
/************************************************************************/
/* getVSILFILE() */
/************************************************************************/
static VSILFILE* getVSILFILE(FILE* stream)
{
VSILFILE* ret;
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
std::set<VSILFILE*>::iterator oIter = oSetFiles.find((VSILFILE*)stream);
if( oIter != oSetFiles.end() )
ret = *oIter;
else
ret = NULL;
return ret;
}
/************************************************************************/
/* getVSILFILE() */
/************************************************************************/
static VSILFILE* getVSILFILE(int fd)
{
VSILFILE* ret;
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
std::map<int, VSILFILE*>::iterator oIter = oMapfdToVSI.find(fd);
if( oIter != oMapfdToVSI.end() )
ret = oIter->second;
else
ret = NULL;
return ret;
}
/************************************************************************/
/* VSIFSeekLHelper() */
/************************************************************************/
static int VSIFSeekLHelper(VSILFILE* fpVSIL, off64_t off, int whence)
{
if( off < 0 && whence == SEEK_CUR )
{
return VSIFSeekL(fpVSIL, VSIFTellL(fpVSIL) + off, SEEK_SET);
}
else if( off < 0 && whence == SEEK_END )
{
VSIFSeekL(fpVSIL, 0, SEEK_END);
return VSIFSeekL(fpVSIL, VSIFTellL(fpVSIL) + off, SEEK_SET);
}
else
return VSIFSeekL(fpVSIL, off, whence);
}
/************************************************************************/
/* VSIFopenHelper() */
/************************************************************************/
static VSILFILE* VSIFfopenHelper(const char *path, const char *mode)
{
VSILFILE* fpVSIL = VSIFOpenL(path, mode);
if( fpVSIL != NULL )
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
oSetFiles.insert(fpVSIL);
oMapVSIToString[fpVSIL] = path;
}
return fpVSIL;
}
/************************************************************************/
/* getfdFromVSILFILE() */
/************************************************************************/
static int getfdFromVSILFILE(VSILFILE* fpVSIL)
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
int fd;
std::map<VSILFILE*, int>::iterator oIter = oMapVSITofd.find(fpVSIL);
if( oIter != oMapVSITofd.end() )
fd = oIter->second;
else
{
fd = open("/dev/zero", O_RDONLY);
assert(fd >= 0);
oMapVSITofd[fpVSIL] = fd;
oMapfdToVSI[fd] = fpVSIL;
}
return fd;
}
/************************************************************************/
/* VSIFopenHelper() */
/************************************************************************/
static int VSIFopenHelper(const char *path, int flags)
{
const char* pszMode = "rb";
if ((flags & 3) == O_RDONLY)
pszMode = "rb";
else if ((flags & 3) == O_WRONLY)
{
if( flags & O_APPEND )
pszMode = "ab";
else
pszMode = "wb";
}
else
{
if( flags & O_APPEND )
pszMode = "ab+";
else
pszMode = "rb+";
}
VSILFILE* fpVSIL = VSIFfopenHelper(path, pszMode );
int fd;
if( fpVSIL != NULL )
{
if( flags & O_TRUNC )
{
VSIFTruncateL(fpVSIL, 0);
VSIFSeekL(fpVSIL, 0, SEEK_SET);
}
fd = getfdFromVSILFILE(fpVSIL);
}
else
fd = -1;
return fd;
}
/************************************************************************/
/* GET_DEBUG_VSIPRELOAD_COND() */
/************************************************************************/
static int GET_DEBUG_VSIPRELOAD_COND(const char* path)
{
return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || strncmp(path, "/vsi", 4) == 0) );
}
static int GET_DEBUG_VSIPRELOAD_COND(VSILFILE* fpVSIL)
{
return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || fpVSIL != NULL));
}
static int GET_DEBUG_VSIPRELOAD_COND(VSIDIR* dirP)
{
return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || oSetVSIDIR.find(dirP) != oSetVSIDIR.end()));
}
/************************************************************************/
/* copyVSIStatBufLToBuf() */
/************************************************************************/
static void copyVSIStatBufLToBuf(VSIStatBufL* bufSrc, struct stat *buf)
{
buf->st_dev = bufSrc->st_dev;
buf->st_ino = bufSrc->st_ino;
buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH; // S_IXUSR | S_IXGRP | S_IXOTH;
buf->st_nlink = 1; //bufSrc->st_nlink;
buf->st_uid = bufSrc->st_uid;
buf->st_gid = bufSrc->st_gid;
buf->st_rdev = bufSrc->st_rdev;
buf->st_size = bufSrc->st_size;
buf->st_blksize = bufSrc->st_blksize;
buf->st_blocks = bufSrc->st_blocks;
buf->st_atime = bufSrc->st_atime;
buf->st_mtime = bufSrc->st_mtime;
buf->st_ctime = bufSrc->st_ctime;
}
/************************************************************************/
/* copyVSIStatBufLToBuf64() */
/************************************************************************/
static void copyVSIStatBufLToBuf64(VSIStatBufL *bufSrc, struct stat64 *buf)
{
buf->st_dev = bufSrc->st_dev;
buf->st_ino = bufSrc->st_ino;
buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH; // S_IXUSR | S_IXGRP | S_IXOTH;
buf->st_nlink = 1; //bufSrc->st_nlink;
buf->st_uid = bufSrc->st_uid;
buf->st_gid = bufSrc->st_gid;
buf->st_rdev = bufSrc->st_rdev;
buf->st_size = bufSrc->st_size;
buf->st_blksize = bufSrc->st_blksize;
buf->st_blocks = bufSrc->st_blocks;
buf->st_atime = bufSrc->st_atime;
buf->st_mtime = bufSrc->st_mtime;
buf->st_ctime = bufSrc->st_ctime;
}
/************************************************************************/
/* fopen() */
/************************************************************************/
FILE *fopen(const char *path, const char *mode)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen(%s, %s)\n", path, mode);
FILE* ret;
if( strncmp(path, "/vsi", 4) == 0 )
ret = (FILE*) VSIFfopenHelper(path, mode);
else
ret = pfnfopen(path, mode);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen() = %p\n", ret);
return ret;
}
/************************************************************************/
/* fopen64() */
/************************************************************************/
FILE *fopen64(const char *path, const char *mode)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen64(%s, %s)\n", path, mode);
FILE* ret;
if( strncmp(path, "/vsi", 4) == 0 )
ret = (FILE*) VSIFfopenHelper(path, mode);
else
ret = pfnfopen64(path, mode);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen64() = %p\n", ret);
return ret;
}
/************************************************************************/
/* fread() */
/************************************************************************/
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d)\n",
stream, (int)size, (int)nmemb);
size_t ret;
if( fpVSIL )
ret = VSIFReadL(ptr, size, nmemb, fpVSIL);
else
ret = pfnfread(ptr, size, nmemb, stream);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d) -> %d\n",
stream, (int)size, (int)nmemb, (int)ret);
return ret;
}
/************************************************************************/
/* fwrite() */
/************************************************************************/
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d)\n",
stream, (int)size, (int)nmemb);
size_t ret;
if( fpVSIL != NULL )
ret = VSIFWriteL(ptr, size, nmemb, fpVSIL);
else
ret = pfnfwrite(ptr, size, nmemb, stream);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d) -> %d\n",
stream, (int)size, (int)nmemb, (int)ret);
return ret;
}
/************************************************************************/
/* fclose() */
/************************************************************************/
int fclose(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fclose(stream=%p)\n", stream);
if( fpVSIL != NULL )
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
int ret = VSIFCloseL(fpVSIL);
oMapVSIToString.erase(fpVSIL);
oSetFiles.erase(fpVSIL);
std::map<VSILFILE*, int>::iterator oIter = oMapVSITofd.find(fpVSIL);
if( oIter != oMapVSITofd.end() )
{
int fd = oIter->second;
pfnclose(fd);
oMapVSITofd.erase(oIter);
oMapfdToVSI.erase(fd);
}
return ret;
}
else
return pfnfclose(stream);
}
/************************************************************************/
/* __xstat() */
/************************************************************************/
int __xstat(int ver, const char *path, struct stat *buf)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
DEBUG_VSIPRELOAD_COND = 1;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat(%s)\n", path);
if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
{
VSIStatBufL sStatBufL;
int ret;
std::string newpath;
if( (osCurDir.size() != 0 && path[0] != '/') )
{
newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
path = newpath.c_str();
}
ret = VSIStatL(path, &sStatBufL);
sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
if( ret == 0 )
{
copyVSIStatBufLToBuf(&sStatBufL, buf);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__xstat(%s) ret = 0, mode = %d, size=%d\n",
path, sStatBufL.st_mode, (int)sStatBufL.st_size);
}
return ret;
}
else
{
int ret = pfn__xstat(ver, path, buf);
if( ret == 0 )
{
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__xstat ret = 0, mode = %d\n", buf->st_mode);
}
return ret;
}
}
/************************************************************************/
/* __lxstat() */
/************************************************************************/
int __lxstat(int ver, const char *path, struct stat *buf)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
DEBUG_VSIPRELOAD_COND = 1;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__lxstat(%s)\n", path);
if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
{
VSIStatBufL sStatBufL;
int ret;
std::string newpath;
if( (osCurDir.size() != 0 && path[0] != '/') )
{
newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
path = newpath.c_str();
}
ret = VSIStatL(path, &sStatBufL);
sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
if( ret == 0 )
{
copyVSIStatBufLToBuf(&sStatBufL, buf);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__lxstat(%s) ret = 0, mode = %d, size=%d\n",
path, sStatBufL.st_mode, (int)sStatBufL.st_size);
}
return ret;
}
else
{
int ret = pfn__lxstat(ver, path, buf);
if( ret == 0 )
{
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__lxstat ret = 0, mode = %d\n", buf->st_mode);
}
return ret;
}
}
/************************************************************************/
/* __xstat64() */
/************************************************************************/
int __xstat64(int ver, const char *path, struct stat64 *buf)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
DEBUG_VSIPRELOAD_COND = 1;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat64(%s)\n", path);
if( (osCurDir.size() != 0 && path[0] != '/') || strncmp(path, "/vsi", 4) == 0 )
{
VSIStatBufL sStatBufL;
int ret;
std::string newpath;
if( (osCurDir.size() != 0 && path[0] != '/') )
{
newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
path = newpath.c_str();
}
ret = VSIStatL(path, &sStatBufL);
sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
if( ret == 0 )
{
copyVSIStatBufLToBuf64(&sStatBufL, buf);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__xstat64(%s) ret = 0, mode = %d, size = %d\n",
path, buf->st_mode, (int)buf->st_size);
}
return ret;
}
else
return pfn__xstat64(ver, path, buf);
}
/************************************************************************/
/* fseeko64() */
/************************************************************************/
int fseeko64 (FILE *stream, off64_t off, int whence)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseeko64(stream=%p, off=%d, whence=%d)\n",
stream, (int)off, whence);
if( fpVSIL != NULL )
return VSIFSeekLHelper(fpVSIL, off, whence);
else
return pfnfseeko64(stream, off, whence);
}
/************************************************************************/
/* fseeko() */
/************************************************************************/
int fseeko (FILE *stream, off_t off, int whence)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseeko(stream=%p, off=%d, whence=%d)\n",
stream, (int)off, whence);
if( fpVSIL != NULL )
return VSIFSeekLHelper(fpVSIL, off, whence);
else
return pfnfseeko64(stream, off, whence);
}
/************************************************************************/
/* fseek() */
/************************************************************************/
int fseek (FILE *stream, off_t off, int whence)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseek(stream=%p, off=%d, whence=%d)\n",
stream, (int)off, whence);
if( fpVSIL != NULL )
return VSIFSeekLHelper(fpVSIL, off, whence);
else
return pfnfseek(stream, off, whence);
}
/************************************************************************/
/* ftello64() */
/************************************************************************/
off64_t ftello64(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftello64(stream=%p)\n", stream);
if( fpVSIL != NULL )
return VSIFTellL(fpVSIL);
else
return pfnftello64(stream);
}
/************************************************************************/
/* ftello() */
/************************************************************************/
off_t ftello(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftello(stream=%p)\n", stream);
if( fpVSIL != NULL )
return VSIFTellL(fpVSIL);
else
return pfnftello64(stream);
}
/************************************************************************/
/* ftell() */
/************************************************************************/
off_t ftell(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftell(stream=%p)\n", stream);
if( fpVSIL != NULL )
return VSIFTellL(fpVSIL);
else
return pfnftell(stream);
}
/************************************************************************/
/* feof() */
/************************************************************************/
int feof(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "feof(stream=%p)\n", stream);
if( fpVSIL != NULL )
return VSIFEofL(fpVSIL);
else
return pfnfeof(stream);
}
/************************************************************************/
/* rewind() */
/************************************************************************/
void rewind(FILE *stream)
{
fseek(stream, 0, SEEK_SET);
}
/************************************************************************/
/* fflush() */
/************************************************************************/
int fflush(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fflush(stream=%p)\n", stream);
if( fpVSIL != NULL )
return 0;
else
return pfnfflush(stream);
}
/************************************************************************/
/* fgetpos() */
/************************************************************************/
int fgetpos(FILE *stream, fpos_t *pos)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fgetpos(stream=%p)\n", stream);
if( fpVSIL != NULL )
{
fprintf(stderr, "fgetpos() unimplemented for VSILFILE\n");
return -1; // FIXME
}
else
return pfnfgetpos(stream, pos);
}
/************************************************************************/
/* fsetpos() */
/************************************************************************/
int fsetpos(FILE *stream, fpos_t *pos)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fsetpos(stream=%p)\n", stream);
if( fpVSIL != NULL )
{
fprintf(stderr, "fsetpos() unimplemented for VSILFILE\n");
return -1; // FIXME
}
else
return pfnfsetpos(stream, pos);
}
/************************************************************************/
/* fileno() */
/************************************************************************/
int fileno(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fileno(stream=%p)\n", stream);
int fd;
if( fpVSIL != NULL )
fd = getfdFromVSILFILE(fpVSIL);
else
fd = pfnfileno(stream);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fileno(stream=%p) = %d\n", stream, fd);
return fd;
}
/************************************************************************/
/* ferror() */
/************************************************************************/
int ferror(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ferror(stream=%p)\n", stream);
if( fpVSIL != NULL )
{
fprintf(stderr, "ferror() unimplemented for VSILFILE\n");
return 0; // FIXME ?
}
else
return pfnferror(stream);
}
/************************************************************************/
/* clearerr() */
/************************************************************************/
void clearerr(FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "clearerr(stream=%p)\n", stream);
if( fpVSIL != NULL )
{
fprintf(stderr, "clearerr() unimplemented for VSILFILE\n");
}
else
pfnclearerr(stream);
}
/************************************************************************/
/* fdopen() */
/************************************************************************/
FILE * fdopen(int fd, const char *mode)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fdopen(fd=%d)\n", fd);
if( fpVSIL != NULL )
{
fprintf(stderr, "fdopen() unimplemented for VSILFILE\n");
return NULL; // FIXME ?
}
else
return pfnfdopen(fd, mode);
}
/************************************************************************/
/* freopen() */
/************************************************************************/
FILE *freopen(const char *path, const char *mode, FILE *stream)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(stream);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "freopen(path=%s,mode=%s,stream=%p)\n", path, mode, stream);
if( fpVSIL != NULL )
{
fprintf(stderr, "freopen() unimplemented for VSILFILE\n");
return NULL; // FIXME ?
}
else
return pfnfreopen(path, mode, stream);
}
/************************************************************************/
/* open() */
/************************************************************************/
int open(const char *path, int flags, ...)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 && path[0] != '/' )
DEBUG_VSIPRELOAD_COND = 1;
if (DEBUG_VSIPRELOAD_COND)
{
if( osCurDir.size() != 0 && path[0] != '/' )
fprintf(stderr, "open(%s)\n", CPLFormFilename(osCurDir.c_str(), path, NULL));
else
fprintf(stderr, "open(%s)\n", path);
}
va_list args;
va_start(args, flags);
mode_t mode = va_arg(args, mode_t);
int fd;
if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
{
VSIStatBufL sStatBufL;
char* newname = (char*)CPLFormFilename(osCurDir.c_str(), path, NULL);
if( strchr(osCurDir.c_str(), '/') != NULL && strcmp(path, "..") == 0 )
{
char* lastslash = strrchr(newname, '/');
if( lastslash != NULL )
{
*lastslash = 0;
lastslash = strrchr(newname, '/');
if( lastslash != NULL )
*lastslash = 0;
}
}
if( VSIStatL(newname, &sStatBufL) == 0 &&
S_ISDIR(sStatBufL.st_mode) )
{
fd = open("/dev/zero", O_RDONLY);
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
oMapDirFdToName[fd] = newname;
}
else
fd = -1;
}
else if( strncmp(path, "/vsi", 4) == 0 )
fd = VSIFopenHelper(path, flags);
else
fd = pfnopen(path, flags, mode);
va_end(args);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "open(%s) = %d\n", path, fd);
return fd;
}
/************************************************************************/
/* open64() */
/************************************************************************/
int open64(const char *path, int flags, ...)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 && path[0] != '/' )
DEBUG_VSIPRELOAD_COND = 1;
if (DEBUG_VSIPRELOAD_COND)
{
if( osCurDir.size() != 0 && path[0] != '/' )
fprintf(stderr, "open64(%s)\n", CPLFormFilename(osCurDir.c_str(), path, NULL));
else
fprintf(stderr, "open64(%s)\n", path);
}
va_list args;
va_start(args, flags);
mode_t mode = va_arg(args, mode_t);
int fd;
if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
{
VSIStatBufL sStatBufL;
char* newname = (char*)CPLFormFilename(osCurDir.c_str(), path, NULL);
if( strchr(osCurDir.c_str(), '/') != NULL && strcmp(path, "..") == 0 )
{
char* lastslash = strrchr(newname, '/');
if( lastslash != NULL )
{
*lastslash = 0;
lastslash = strrchr(newname, '/');
if( lastslash != NULL )
*lastslash = 0;
}
}
if( VSIStatL(newname, &sStatBufL) == 0 &&
S_ISDIR(sStatBufL.st_mode) )
{
fd = open("/dev/zero", O_RDONLY);
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
oMapDirFdToName[fd] = newname;
}
else
fd = -1;
}
else if( strncmp(path, "/vsi", 4) == 0 )
fd = VSIFopenHelper(path, flags);
else
fd = pfnopen64(path, flags, mode);
va_end(args);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "open64(%s) = %d\n", path, fd);
return fd;
}
/************************************************************************/
/* creat() */
/************************************************************************/
int creat(const char *path, mode_t mode)
{
return open64(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
}
/************************************************************************/
/* close() */
/************************************************************************/
int close(int fd)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
assert( oMapfdToVSIDIR.find(fd) == oMapfdToVSIDIR.end() );
if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
{
oMapDirFdToName.erase(fd);
if( DEBUG_VSIPRELOAD )
DEBUG_VSIPRELOAD_COND = 1;
}
}
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "close(fd=%d)\n", fd);
if( fpVSIL != NULL )
{
VSIFCloseL(fpVSIL);
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
oSetFiles.erase(fpVSIL);
pfnclose(oMapVSITofd[fpVSIL]);
oMapVSITofd.erase(fpVSIL);
oMapfdToVSI.erase(fd);
oMapVSIToString.erase(fpVSIL);
return 0;
}
else
return pfnclose(fd);
}
/************************************************************************/
/* read() */
/************************************************************************/
ssize_t read(int fd, void *buf, size_t count)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "read(fd=%d, count=%d)\n", fd, (int)count);
ssize_t ret;
if( fpVSIL != NULL )
ret = VSIFReadL(buf, 1, count, fpVSIL);
else
ret = pfnread(fd, buf, count);
if (DEBUG_VSIPRELOAD_COND && DEBUG_OUTPUT_READ && ret < 40)
{
fprintf(stderr, "read() : ");
for(int i=0;i<ret;i++)
{
if( ((unsigned char*)buf)[i] >= 'A' && ((unsigned char*)buf)[i] <= 'Z' )
fprintf(stderr, "%c ", ((unsigned char*)buf)[i]);
else
fprintf(stderr, "\\%02X ", ((unsigned char*)buf)[i]);
}
fprintf(stderr, "\n");
}
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "read() -> %d\n", (int)ret);
return ret;
}
/************************************************************************/
/* write() */
/************************************************************************/
ssize_t write(int fd, const void *buf, size_t count)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "write(fd=%d, count=%d)\n", fd, (int)count);
if( fpVSIL != NULL )
return VSIFWriteL(buf, 1, count, fpVSIL);
else
return pfnwrite(fd, buf, count);
}
/************************************************************************/
/* fsync() */
/************************************************************************/
int fsync(int fd)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fsync(fd=%d)\n", fd);
if( fpVSIL != NULL )
return 0;
else
return pfnfsync(fd);
}
/************************************************************************/
/* fdatasync() */
/************************************************************************/
int fdatasync(int fd)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fdatasync(fd=%d)\n", fd);
if( fpVSIL != NULL )
return 0;
else
return pfnfdatasync(fd);
}
/************************************************************************/
/* __fxstat() */
/************************************************************************/
int __fxstat (int ver, int fd, struct stat *buf)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
std::string name;
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
{
name = oMapDirFdToName[fd];
if( DEBUG_VSIPRELOAD )
DEBUG_VSIPRELOAD_COND = 1;
}
}
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat(fd=%d)\n", fd);
if( name.size() )
{
VSIStatBufL sStatBufL;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat(%s)\n", name.c_str());
int ret = VSIStatL(name.c_str(), &sStatBufL);
sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
if( ret == 0 )
{
copyVSIStatBufLToBuf(&sStatBufL, buf);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__fxstat ret = 0, mode = %d, size = %d\n",
sStatBufL.st_mode, (int)sStatBufL.st_size);
}
return ret;
}
else if( fpVSIL != NULL )
{
VSIStatBufL sStatBufL;
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
name = oMapVSIToString[fpVSIL];
}
int ret = VSIStatL(name.c_str(), &sStatBufL);
sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
if( ret == 0 )
{
copyVSIStatBufLToBuf(&sStatBufL, buf);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__fxstat ret = 0, mode = %d, size = %d\n",
sStatBufL.st_mode, (int)sStatBufL.st_size);
}
return ret;
}
else
return pfn__fxstat(ver, fd, buf);
}
/************************************************************************/
/* __fxstat64() */
/************************************************************************/
int __fxstat64 (int ver, int fd, struct stat64 *buf)
{
myinit();
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat64(fd=%d)\n", fd);
if( fpVSIL != NULL )
{
VSIStatBufL sStatBufL;
std::string name;
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
name = oMapVSIToString[fpVSIL];
}
int ret = VSIStatL(name.c_str(), &sStatBufL);
sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
if( ret == 0 )
{
copyVSIStatBufLToBuf64(&sStatBufL, buf);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__fxstat64 ret = 0, mode = %d, size = %d\n",
buf->st_mode, (int)buf->st_size);
}
return ret;
}
else
return pfn__fxstat64(ver, fd, buf);
}
/************************************************************************/
/* __fxstatat() */
/************************************************************************/
#ifdef HAVE_FSTATAT
int __fxstatat (int ver, int dirfd, const char *pathname, struct stat *buf,
int flags)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(pathname);
if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 )
DEBUG_VSIPRELOAD_COND = 1;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstatat(dirfd=%d,pathname=%s,flags=%d)\n", dirfd, pathname, flags);
if( osCurDir.size() != 0 || strncmp(pathname, "/vsi", 4) == 0 )
{
VSIStatBufL sStatBufL;
int ret;
if( osCurDir.size() && dirfd == AT_FDCWD && pathname[0] != '/' )
pathname = CPLFormFilename(osCurDir.c_str(), pathname, NULL);
ret = VSIStatL(pathname, &sStatBufL);
sStatBufL.st_ino = (int)CPLHashSetHashStr(pathname);
if( ret == 0 )
{
copyVSIStatBufLToBuf(&sStatBufL, buf);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"__fxstatat(%s) ret = 0, mode = %d, size = %d\n",
pathname, buf->st_mode, (int)buf->st_size);
}
return ret;
}
else
return pfn__fxstatat(ver, dirfd, pathname, buf, flags);
}
#endif
/************************************************************************/
/* lseek() */
/************************************************************************/
off_t lseek(int fd, off_t off, int whence)
{
myinit();
off_t ret;
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"lseek(fd=%d, off=%d, whence=%d)\n", fd, (int)off, whence);
if( fpVSIL != NULL )
{
VSIFSeekLHelper(fpVSIL, off, whence);
ret = VSIFTellL(fpVSIL);
}
else
ret = pfnlseek(fd, off, whence);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "lseek() -> ret = %d\n", (int)ret);
return ret;
}
/************************************************************************/
/* lseek64() */
/************************************************************************/
off64_t lseek64(int fd, off64_t off, int whence)
{
myinit();
off_t ret;
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"lseek64(fd=%d, off=%d, whence=%d)\n", fd, (int)off, whence);
if( fpVSIL != NULL )
{
VSIFSeekLHelper(fpVSIL, off, whence);
ret = VSIFTellL(fpVSIL);
}
else
ret = pfnlseek64(fd, off, whence);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
"lseek64() -> ret = %d\n", (int)ret);
return ret;
}
/************************************************************************/
/* truncate() */
/************************************************************************/
int truncate(const char *path, off_t length)
{
myinit();
int ret;
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "truncate(%s)\n", path);
if( strncmp(path, "/vsi", 4) == 0 )
{
VSILFILE* fpVSIL = VSIFOpenL(path, "wb+");
if( fpVSIL )
{
ret = VSIFTruncateL(fpVSIL, length);
VSIFCloseL(fpVSIL);
}
else
ret = -1;
}
else
ret = pfntruncate(path, length);
return ret;
}
/************************************************************************/
/* ftruncate() */
/************************************************************************/
int ftruncate(int fd, off_t length)
{
myinit();
int ret;
VSILFILE* fpVSIL = getVSILFILE(fd);
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftruncate(fd=%d)\n", fd);
if( fpVSIL != NULL )
{
ret = VSIFTruncateL(fpVSIL, length);
}
else
ret = pfnftruncate(fd, length);
return ret;
}
/************************************************************************/
/* opendir() */
/************************************************************************/
DIR *opendir(const char *name)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(name);
if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 )
DEBUG_VSIPRELOAD_COND = 1;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "opendir(%s)\n", name);
DIR * ret;
if( osCurDir.size() != 0 || strncmp(name, "/vsi", 4) == 0 )
{
char** papszDir;
if( osCurDir.size() != 0 && name[0] != '/' )
name = CPLFormFilename(osCurDir.c_str(), name, NULL);
papszDir = VSIReadDir(name);
if( papszDir == NULL )
{
VSIStatBufL sStatBufL;
if( VSIStatL(name, &sStatBufL) == 0 && S_ISDIR(sStatBufL.st_mode) )
{
papszDir = (char**) CPLMalloc(sizeof(char*));
papszDir[0] = NULL;
}
}
if( papszDir == NULL )
ret = NULL;
else
{
VSIDIR* mydir = (VSIDIR*)malloc(sizeof(VSIDIR));
mydir->pszDirname = CPLStrdup(name);
mydir->papszDir = papszDir;
mydir->nIter = 0;
mydir->fd = -1;
ret = (DIR*)mydir;
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
oSetVSIDIR.insert(mydir);
}
}
else
ret = pfnopendir(name);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "opendir(%s) -> %p\n", name, ret);
return ret;
}
/************************************************************************/
/* filldir() */
/************************************************************************/
static int filldir(VSIDIR* mydir)
{
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(mydir);
char* pszName = mydir->papszDir[mydir->nIter++];
if( pszName == NULL )
return FALSE;
mydir->ent.d_ino = 0;
mydir->ent.d_off = 0;
mydir->ent.d_reclen = sizeof(mydir->ent);
VSIStatBufL sStatBufL;
VSIStatL(CPLFormFilename(mydir->pszDirname, pszName, NULL), &sStatBufL);
if( DEBUG_VSIPRELOAD_COND && S_ISDIR(sStatBufL.st_mode) )
fprintf(stderr, "%s is dir\n", pszName);
mydir->ent.d_type = S_ISDIR(sStatBufL.st_mode) ? DT_DIR :
S_ISREG(sStatBufL.st_mode) ? DT_REG :
S_ISLNK(sStatBufL.st_mode) ? DT_LNK :
DT_UNKNOWN;
strncpy(mydir->ent.d_name, pszName, 256);
mydir->ent.d_name[255] = '\0';
mydir->ent64.d_ino = 0;
mydir->ent64.d_off = 0;
mydir->ent64.d_reclen = sizeof(mydir->ent64);
mydir->ent64.d_type = mydir->ent.d_type;
strcpy(mydir->ent64.d_name, mydir->ent.d_name);
return TRUE;
}
/************************************************************************/
/* readdir() */
/************************************************************************/
struct dirent *readdir(DIR *dirp)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "readdir(%p)\n", dirp);
if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
{
VSIDIR* mydir = (VSIDIR*)dirp;
if( !filldir(mydir) )
return FALSE;
return &(mydir->ent);
}
else
return pfnreaddir(dirp);
}
/************************************************************************/
/* readdir64() */
/************************************************************************/
struct dirent64 *readdir64(DIR *dirp)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "readdir64(%p)\n", dirp);
if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
{
VSIDIR* mydir = (VSIDIR*)dirp;
if( !filldir(mydir) )
return FALSE;
return &(mydir->ent64);
}
else
return pfnreaddir64(dirp);
}
/************************************************************************/
/* closedir() */
/************************************************************************/
int closedir(DIR *dirp)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "closedir(%p)\n", dirp);
if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
{
VSIDIR* mydir = (VSIDIR*)dirp;
CPLFree(mydir->pszDirname);
CSLDestroy(mydir->papszDir);
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
if( mydir->fd >= 0 )
{
oMapfdToVSIDIR.erase(mydir->fd);
close(mydir->fd);
}
oSetVSIDIR.erase(mydir);
free(mydir);
return 0;
}
else
return pfnclosedir(dirp);
}
/************************************************************************/
/* dirfd() */
/************************************************************************/
int dirfd(DIR *dirp)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "dirfd(%p)\n", dirp);
int ret;
if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
{
VSIDIR* mydir = (VSIDIR*)dirp;
if( mydir->fd < 0 )
{
mydir->fd = open("/dev/zero", O_RDONLY);
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
oMapfdToVSIDIR[mydir->fd] = mydir;
}
ret = mydir->fd;
}
else
ret = pfndirfd(dirp);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "dirfd(%p) -> %d\n", dirp, ret);
return ret;
}
/************************************************************************/
/* fchdir() */
/************************************************************************/
int fchdir(int fd)
{
VSIDIR* mydir = NULL;
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
if( oMapfdToVSIDIR.find(fd) != oMapfdToVSIDIR.end() )
mydir = oMapfdToVSIDIR[fd];
}
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(mydir);
std::string name;
{
CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX)
if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
{
name = oMapDirFdToName[fd];
if( DEBUG_VSIPRELOAD )
DEBUG_VSIPRELOAD_COND = 1;
}
}
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d)\n", fd);
if( name.size() )
{
osCurDir = name;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
return 0;
}
else if( mydir != NULL )
{
osCurDir = mydir->pszDirname;
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
return 0;
}
else
{
osCurDir = "";
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
return pfnfchdir(fd);
}
}
/************************************************************************/
/* acl_extended_file() */
/************************************************************************/
// #include <acl/acl.h>
extern "C" int acl_extended_file(const char *name);
DECLARE_SYMBOL(acl_extended_file, int, (const char *name));
int acl_extended_file(const char *path)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "acl_extended_file(%s)\n", path);
int ret;
if( strncmp(path, "/vsi", 4) == 0 )
ret = -1;
else
{
if( pfnacl_extended_file == NULL )
pfnacl_extended_file = (fnacl_extended_fileType) dlsym(RTLD_NEXT, "acl_extended_file");
if( pfnacl_extended_file == NULL )
ret = -1;
else
ret = pfnacl_extended_file(path);
}
return ret;
}
/************************************************************************/
/* getfilecon() */
/************************************************************************/
// #include <selinux/selinux.h>
extern "C" int getfilecon(const char *name, void* con);
DECLARE_SYMBOL(getfilecon, int, (const char *name, void* con));
int getfilecon(const char *path, /*security_context_t **/ void* con)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "getfilecon(%s)\n", path);
int ret;
if( strncmp(path, "/vsi", 4) == 0 )
{
errno = ENOTSUP;
ret = -1;
}
else
{
if( pfngetfilecon == NULL )
pfngetfilecon = (fngetfileconType) dlsym(RTLD_NEXT, "getfilecon");
if( pfngetfilecon == NULL )
ret = -1;
else
ret = pfngetfilecon(path, con);
}
return ret;
}
/************************************************************************/
/* lgetfilecon() */
/************************************************************************/
// #include <selinux/selinux.h>
extern "C" int lgetfilecon(const char *name, void* con);
DECLARE_SYMBOL(lgetfilecon, int, (const char *name, void* con));
int lgetfilecon(const char *path, /*security_context_t **/ void* con)
{
myinit();
int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "lgetfilecon(%s)\n", path);
int ret;
if( strncmp(path, "/vsi", 4) == 0 )
{
errno = ENOTSUP;
ret = -1;
}
else
{
if( pfnlgetfilecon == NULL )
pfnlgetfilecon = (fnlgetfileconType) dlsym(RTLD_NEXT, "lgetfilecon");
if( pfnlgetfilecon == NULL )
ret = -1;
else
ret = pfnlgetfilecon(path, con);
}
return ret;
}