LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - ogrsqlitevfs.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 137 180 76.1 %
Date: 2024-04-29 15:10:10 Functions: 19 26 73.1 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements SQLite VFS
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             : 
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2011-2012, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_port.h"
      30             : #include "ogr_sqlite.h"
      31             : 
      32             : #include <cstdio>
      33             : #include <cstdlib>
      34             : #include <cstring>
      35             : 
      36             : #include "cpl_atomic_ops.h"
      37             : #include "cpl_conv.h"
      38             : #include "cpl_error.h"
      39             : #include "cpl_string.h"
      40             : #include "cpl_vsi.h"
      41             : #include "ogrsqlitevfs.h"
      42             : 
      43             : #ifdef DEBUG_IO
      44             : #define DEBUG_ONLY
      45             : #else
      46             : #define DEBUG_ONLY CPL_UNUSED
      47             : #endif
      48             : 
      49             : // #define DEBUG_IO 1
      50             : 
      51             : typedef struct
      52             : {
      53             :     char szVFSName[64];
      54             :     sqlite3_vfs *pDefaultVFS;
      55             :     pfnNotifyFileOpenedType pfn;
      56             :     void *pfnUserData;
      57             :     int nCounter;
      58             : } OGRSQLiteVFSAppDataStruct;
      59             : 
      60             : #define GET_UNDERLYING_VFS(pVFS)                                               \
      61             :     ((OGRSQLiteVFSAppDataStruct *)pVFS->pAppData)->pDefaultVFS
      62             : 
      63             : typedef struct
      64             : {
      65             :     const struct sqlite3_io_methods *pMethods;
      66             :     VSILFILE *fp;
      67             :     int bDeleteOnClose;
      68             :     char *pszFilename;
      69             : } OGRSQLiteFileStruct;
      70             : 
      71       19465 : static int OGRSQLiteIOClose(sqlite3_file *pFile)
      72             : {
      73       19465 :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
      74             : #ifdef DEBUG_IO
      75             :     CPLDebug("SQLITE", "OGRSQLiteIOClose(%p (%s))", pMyFile->fp,
      76             :              pMyFile->pszFilename);
      77             : #endif
      78       19465 :     VSIFCloseL(pMyFile->fp);
      79       19465 :     if (pMyFile->bDeleteOnClose)
      80           0 :         VSIUnlink(pMyFile->pszFilename);
      81       19465 :     CPLFree(pMyFile->pszFilename);
      82       19465 :     return SQLITE_OK;
      83             : }
      84             : 
      85      219971 : static int OGRSQLiteIORead(sqlite3_file *pFile, void *pBuffer, int iAmt,
      86             :                            sqlite3_int64 iOfst)
      87             : {
      88      219971 :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
      89      219971 :     VSIFSeekL(pMyFile->fp, (vsi_l_offset)iOfst, SEEK_SET);
      90      219971 :     int nRead = (int)VSIFReadL(pBuffer, 1, iAmt, pMyFile->fp);
      91             : #ifdef DEBUG_IO
      92             :     CPLDebug("SQLITE", "OGRSQLiteIORead(%p, %d, %d) = %d", pMyFile->fp, iAmt,
      93             :              (int)iOfst, nRead);
      94             : #endif
      95      219971 :     if (nRead < iAmt)
      96             :     {
      97        4289 :         memset(((char *)pBuffer) + nRead, 0, iAmt - nRead);
      98        4289 :         return SQLITE_IOERR_SHORT_READ;
      99             :     }
     100      215682 :     return SQLITE_OK;
     101             : }
     102             : 
     103      398640 : static int OGRSQLiteIOWrite(sqlite3_file *pFile, const void *pBuffer, int iAmt,
     104             :                             sqlite3_int64 iOfst)
     105             : {
     106      398640 :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     107      398640 :     VSIFSeekL(pMyFile->fp, (vsi_l_offset)iOfst, SEEK_SET);
     108      398640 :     int nWritten = (int)VSIFWriteL(pBuffer, 1, iAmt, pMyFile->fp);
     109             : #ifdef DEBUG_IO
     110             :     CPLDebug("SQLITE", "OGRSQLiteIOWrite(%p, %d, %d) = %d", pMyFile->fp, iAmt,
     111             :              (int)iOfst, nWritten);
     112             : #endif
     113      398640 :     if (nWritten < iAmt)
     114             :     {
     115          24 :         return SQLITE_IOERR_WRITE;
     116             :     }
     117      398616 :     return SQLITE_OK;
     118             : }
     119             : 
     120          23 : static int OGRSQLiteIOTruncate(sqlite3_file *pFile, sqlite3_int64 size)
     121             : {
     122          23 :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     123             : #ifdef DEBUG_IO
     124             :     CPLDebug("SQLITE", "OGRSQLiteIOTruncate(%p, " CPL_FRMT_GIB ")", pMyFile->fp,
     125             :              size);
     126             : #endif
     127          23 :     int nRet = VSIFTruncateL(pMyFile->fp, size);
     128          23 :     return (nRet == 0) ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
     129             : }
     130             : 
     131        5976 : static int OGRSQLiteIOSync(DEBUG_ONLY sqlite3_file *pFile, DEBUG_ONLY int flags)
     132             : {
     133             : #ifdef DEBUG_IO
     134             :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     135             :     CPLDebug("SQLITE", "OGRSQLiteIOSync(%p, %d)", pMyFile->fp, flags);
     136             : #endif
     137        5976 :     return SQLITE_OK;
     138             : }
     139             : 
     140       85649 : static int OGRSQLiteIOFileSize(sqlite3_file *pFile, sqlite3_int64 *pSize)
     141             : {
     142       85649 :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     143       85649 :     vsi_l_offset nCurOffset = VSIFTellL(pMyFile->fp);
     144       85649 :     VSIFSeekL(pMyFile->fp, 0, SEEK_END);
     145       85649 :     *pSize = VSIFTellL(pMyFile->fp);
     146       85649 :     VSIFSeekL(pMyFile->fp, nCurOffset, SEEK_SET);
     147             : #ifdef DEBUG_IO
     148             :     CPLDebug("SQLITE", "OGRSQLiteIOFileSize(%p) = " CPL_FRMT_GIB, pMyFile->fp,
     149             :              *pSize);
     150             : #endif
     151       85649 :     return SQLITE_OK;
     152             : }
     153             : 
     154      139599 : static int OGRSQLiteIOLock(DEBUG_ONLY sqlite3_file *pFile, DEBUG_ONLY int flags)
     155             : {
     156             : #ifdef DEBUG_IO
     157             :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     158             :     CPLDebug("SQLITE", "OGRSQLiteIOLock(%p)", pMyFile->fp);
     159             : #endif
     160      139599 :     return SQLITE_OK;
     161             : }
     162             : 
     163      115076 : static int OGRSQLiteIOUnlock(DEBUG_ONLY sqlite3_file *pFile,
     164             :                              DEBUG_ONLY int flags)
     165             : {
     166             : #ifdef DEBUG_IO
     167             :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     168             :     CPLDebug("SQLITE", "OGRSQLiteIOUnlock(%p)", pMyFile->fp);
     169             : #endif
     170      115076 :     return SQLITE_OK;
     171             : }
     172             : 
     173           6 : static int OGRSQLiteIOCheckReservedLock(DEBUG_ONLY sqlite3_file *pFile,
     174             :                                         DEBUG_ONLY int *pResOut)
     175             : {
     176             : #ifdef DEBUG_IO
     177             :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     178             :     CPLDebug("SQLITE", "OGRSQLiteIOCheckReservedLock(%p)", pMyFile->fp);
     179             : #endif
     180           6 :     *pResOut = 0;
     181           6 :     return SQLITE_OK;
     182             : }
     183             : 
     184       96351 : static int OGRSQLiteIOFileControl(DEBUG_ONLY sqlite3_file *pFile,
     185             :                                   DEBUG_ONLY int op, DEBUG_ONLY void *pArg)
     186             : {
     187             : #ifdef DEBUG_IO
     188             :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     189             :     CPLDebug("SQLITE", "OGRSQLiteIOFileControl(%p, %d)", pMyFile->fp, op);
     190             : #endif
     191       96351 :     return SQLITE_NOTFOUND;
     192             : }
     193             : 
     194        4381 : static int OGRSQLiteIOSectorSize(DEBUG_ONLY sqlite3_file *pFile)
     195             : {
     196             : #ifdef DEBUG_IO
     197             :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     198             :     CPLDebug("SQLITE", "OGRSQLiteIOSectorSize(%p)", pMyFile->fp);
     199             : #endif
     200        4381 :     return 0;
     201             : }
     202             : 
     203       98943 : static int OGRSQLiteIODeviceCharacteristics(DEBUG_ONLY sqlite3_file *pFile)
     204             : {
     205             : #ifdef DEBUG_IO
     206             :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     207             :     CPLDebug("SQLITE", "OGRSQLiteIODeviceCharacteristics(%p)", pMyFile->fp);
     208             : #endif
     209       98943 :     return 0;
     210             : }
     211             : 
     212             : static const sqlite3_io_methods OGRSQLiteIOMethods = {
     213             :     1,
     214             :     OGRSQLiteIOClose,
     215             :     OGRSQLiteIORead,
     216             :     OGRSQLiteIOWrite,
     217             :     OGRSQLiteIOTruncate,
     218             :     OGRSQLiteIOSync,
     219             :     OGRSQLiteIOFileSize,
     220             :     OGRSQLiteIOLock,
     221             :     OGRSQLiteIOUnlock,
     222             :     OGRSQLiteIOCheckReservedLock,
     223             :     OGRSQLiteIOFileControl,
     224             :     OGRSQLiteIOSectorSize,
     225             :     OGRSQLiteIODeviceCharacteristics,
     226             :     nullptr,  // xShmMap
     227             :     nullptr,  // xShmLock
     228             :     nullptr,  // xShmBarrier
     229             :     nullptr,  // xShmUnmap
     230             :     nullptr,  // xFetch
     231             :     nullptr,  // xUnfetch
     232             : };
     233             : 
     234       19469 : static int OGRSQLiteVFSOpen(sqlite3_vfs *pVFS, const char *zName,
     235             :                             sqlite3_file *pFile, int flags, int *pOutFlags)
     236             : {
     237             : #ifdef DEBUG_IO
     238             :     CPLDebug("SQLITE", "OGRSQLiteVFSOpen(%s, %d)", zName ? zName : "(null)",
     239             :              flags);
     240             : #endif
     241             : 
     242       19469 :     OGRSQLiteVFSAppDataStruct *pAppData =
     243             :         (OGRSQLiteVFSAppDataStruct *)pVFS->pAppData;
     244             : 
     245       19469 :     if (zName == nullptr)
     246             :     {
     247           0 :         zName = CPLSPrintf("/vsimem/sqlite/%p_%d", pVFS,
     248           0 :                            CPLAtomicInc(&(pAppData->nCounter)));
     249             :     }
     250             : 
     251       19469 :     OGRSQLiteFileStruct *pMyFile = (OGRSQLiteFileStruct *)pFile;
     252       19469 :     pMyFile->pMethods = nullptr;
     253       19469 :     pMyFile->bDeleteOnClose = FALSE;
     254       19469 :     pMyFile->pszFilename = nullptr;
     255       19469 :     if (flags & SQLITE_OPEN_READONLY)
     256         741 :         pMyFile->fp = VSIFOpenL(zName, "rb");
     257       18728 :     else if (flags & SQLITE_OPEN_CREATE)
     258             :     {
     259             :         VSIStatBufL sStatBufL;
     260       18040 :         if (VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG) == 0)
     261          55 :             pMyFile->fp = VSIFOpenL(zName, "rb+");
     262             :         else
     263       17985 :             pMyFile->fp = VSIFOpenL(zName, "wb+");
     264             :     }
     265         688 :     else if (flags & SQLITE_OPEN_READWRITE)
     266         688 :         pMyFile->fp = VSIFOpenL(zName, "rb+");
     267             :     else
     268           0 :         pMyFile->fp = nullptr;
     269             : 
     270       19469 :     if (pMyFile->fp == nullptr)
     271           4 :         return SQLITE_CANTOPEN;
     272             : 
     273             : #ifdef DEBUG_IO
     274             :     CPLDebug("SQLITE", "OGRSQLiteVFSOpen() = %p", pMyFile->fp);
     275             : #endif
     276             : 
     277       19465 :     pfnNotifyFileOpenedType pfn = pAppData->pfn;
     278       19465 :     if (pfn)
     279             :     {
     280       19043 :         pfn(pAppData->pfnUserData, zName, pMyFile->fp);
     281             :     }
     282             : 
     283       19465 :     pMyFile->pMethods = &OGRSQLiteIOMethods;
     284       19465 :     pMyFile->bDeleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE);
     285       19465 :     pMyFile->pszFilename = CPLStrdup(zName);
     286             : 
     287       19465 :     if (pOutFlags != nullptr)
     288        2549 :         *pOutFlags = flags;
     289             : 
     290       19465 :     return SQLITE_OK;
     291             : }
     292             : 
     293       16916 : static int OGRSQLiteVFSDelete(DEBUG_ONLY sqlite3_vfs *pVFS, const char *zName,
     294             :                               int DEBUG_ONLY syncDir)
     295             : {
     296             : #ifdef DEBUG_IO
     297             :     CPLDebug("SQLITE", "OGRSQLiteVFSDelete(%s)", zName);
     298             : #endif
     299       16916 :     VSIUnlink(zName);
     300       16916 :     return SQLITE_OK;
     301             : }
     302             : 
     303      170972 : static int OGRSQLiteVFSAccess(DEBUG_ONLY sqlite3_vfs *pVFS, const char *zName,
     304             :                               int flags, int *pResOut)
     305             : {
     306             : #ifdef DEBUG_IO
     307             :     CPLDebug("SQLITE", "OGRSQLiteVFSAccess(%s, %d)", zName, flags);
     308             : #endif
     309             :     VSIStatBufL sStatBufL;
     310             :     int nRet;  // TODO(schwehr): Cleanup nRet and pResOut.  bools?
     311      170972 :     if (flags == SQLITE_ACCESS_EXISTS)
     312             :     {
     313             :         /* Do not try to check the presence of a journal or a wal on /vsicurl !
     314             :          */
     315      170972 :         if ((STARTS_WITH(zName, "/vsicurl/") ||
     316      170804 :              STARTS_WITH(zName, "/vsitar/") ||
     317      170804 :              STARTS_WITH(zName, "/vsizip/")) &&
     318         300 :             ((strlen(zName) > strlen("-journal") &&
     319         300 :               strcmp(zName + strlen(zName) - strlen("-journal"), "-journal") ==
     320         150 :                   0) ||
     321         150 :              (strlen(zName) > strlen("-wal") &&
     322         150 :               strcmp(zName + strlen(zName) - strlen("-wal"), "-wal") == 0)))
     323             :         {
     324         300 :             nRet = -1;
     325             :         }
     326             :         else
     327             :         {
     328      170672 :             nRet = VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG);
     329             :         }
     330             :     }
     331           0 :     else if (flags == SQLITE_ACCESS_READ)
     332             :     {
     333           0 :         VSILFILE *fp = VSIFOpenL(zName, "rb");
     334           0 :         nRet = fp ? 0 : -1;
     335           0 :         if (fp)
     336           0 :             VSIFCloseL(fp);
     337             :     }
     338           0 :     else if (flags == SQLITE_ACCESS_READWRITE)
     339             :     {
     340           0 :         VSILFILE *fp = VSIFOpenL(zName, "rb+");
     341           0 :         nRet = fp ? 0 : -1;
     342           0 :         if (fp)
     343           0 :             VSIFCloseL(fp);
     344             :     }
     345             :     else
     346             :     {
     347           0 :         nRet = -1;
     348             :     }
     349      170972 :     *pResOut = (nRet == 0);
     350      170972 :     return SQLITE_OK;
     351             : }
     352             : 
     353        2541 : static int OGRSQLiteVFSFullPathname(sqlite3_vfs *pVFS, const char *zName,
     354             :                                     int nOut, char *zOut)
     355             : {
     356        2541 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     357             : #ifdef DEBUG_IO
     358             :     CPLDebug("SQLITE", "OGRSQLiteVFSFullPathname(%s)", zName);
     359             : #endif
     360        2541 :     if (zName[0] == '/')
     361             :     {
     362        2539 :         if (static_cast<int>(strlen(zName)) >= nOut)
     363             :         {
     364             :             // The +8 comes from the fact that sqlite3 does this check as
     365             :             // it needs to be able to append .journal to the filename
     366           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     367             :                      "Maximum pathname length reserved for SQLite3 VFS "
     368             :                      "isn't large enough. Try raising "
     369             :                      "OGR_SQLITE_VFS_MAXPATHNAME to at least %d",
     370           0 :                      static_cast<int>(strlen(zName)) + 8);
     371           0 :             return SQLITE_CANTOPEN;
     372             :         }
     373        2539 :         strncpy(zOut, zName, nOut);
     374        2539 :         zOut[nOut - 1] = '\0';
     375        2539 :         return SQLITE_OK;
     376             :     }
     377           2 :     return pUnderlyingVFS->xFullPathname(pUnderlyingVFS, zName, nOut, zOut);
     378             : }
     379             : 
     380           0 : static void *OGRSQLiteVFSDlOpen(sqlite3_vfs *pVFS, const char *zFilename)
     381             : {
     382           0 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     383             :     // CPLDebug("SQLITE", "OGRSQLiteVFSDlOpen(%s)", zFilename);
     384           0 :     return pUnderlyingVFS->xDlOpen(pUnderlyingVFS, zFilename);
     385             : }
     386             : 
     387           0 : static void OGRSQLiteVFSDlError(sqlite3_vfs *pVFS, int nByte, char *zErrMsg)
     388             : {
     389           0 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     390             :     // CPLDebug("SQLITE", "OGRSQLiteVFSDlError()");
     391           0 :     pUnderlyingVFS->xDlError(pUnderlyingVFS, nByte, zErrMsg);
     392           0 : }
     393             : 
     394           0 : static void (*OGRSQLiteVFSDlSym(sqlite3_vfs *pVFS, void *pHandle,
     395             :                                 const char *zSymbol))(void)
     396             : {
     397           0 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     398             :     // CPLDebug("SQLITE", "OGRSQLiteVFSDlSym(%s)", zSymbol);
     399           0 :     return pUnderlyingVFS->xDlSym(pUnderlyingVFS, pHandle, zSymbol);
     400             : }
     401             : 
     402           0 : static void OGRSQLiteVFSDlClose(sqlite3_vfs *pVFS, void *pHandle)
     403             : {
     404           0 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     405             :     // CPLDebug("SQLITE", "OGRSQLiteVFSDlClose(%p)", pHandle);
     406           0 :     pUnderlyingVFS->xDlClose(pUnderlyingVFS, pHandle);
     407           0 : }
     408             : 
     409           0 : static int OGRSQLiteVFSRandomness(sqlite3_vfs *pVFS, int nByte, char *zOut)
     410             : {
     411           0 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     412             :     // CPLDebug("SQLITE", "OGRSQLiteVFSRandomness()");
     413           0 :     return pUnderlyingVFS->xRandomness(pUnderlyingVFS, nByte, zOut);
     414             : }
     415             : 
     416           0 : static int OGRSQLiteVFSSleep(sqlite3_vfs *pVFS, int microseconds)
     417             : {
     418           0 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     419             :     // CPLDebug("SQLITE", "OGRSQLiteVFSSleep()");
     420           0 :     return pUnderlyingVFS->xSleep(pUnderlyingVFS, microseconds);
     421             : }
     422             : 
     423             : // Derived for sqlite3.c implementation of unixCurrentTime64 and
     424             : // winCurrentTime64
     425             : #ifdef _WIN32
     426             : #include <windows.h>
     427             : 
     428             : static int OGRSQLiteVFSCurrentTimeInt64(sqlite3_vfs * /*pVFS*/,
     429             :                                         sqlite3_int64 *piNow)
     430             : {
     431             :     FILETIME ft;
     432             :     constexpr sqlite3_int64 winFiletimeEpoch =
     433             :         23058135 * (sqlite3_int64)8640000;
     434             :     constexpr sqlite3_int64 max32BitValue = (sqlite3_int64)2000000000 +
     435             :                                             (sqlite3_int64)2000000000 +
     436             :                                             (sqlite3_int64)294967296;
     437             : 
     438             : #if defined(_WIN32_WCE)
     439             :     SYSTEMTIME time;
     440             :     GetSystemTime(&time);
     441             :     /* if SystemTimeToFileTime() fails, it returns zero. */
     442             :     if (!SystemTimeToFileTime(&time, &ft))
     443             :     {
     444             :         return SQLITE_ERROR;
     445             :     }
     446             : #else
     447             :     GetSystemTimeAsFileTime(&ft);
     448             : #endif
     449             :     *piNow = winFiletimeEpoch +
     450             :              ((((sqlite3_int64)ft.dwHighDateTime) * max32BitValue) +
     451             :               (sqlite3_int64)ft.dwLowDateTime) /
     452             :                  (sqlite3_int64)10000;
     453             :     return SQLITE_OK;
     454             : }
     455             : #else
     456             : #include <sys/time.h>
     457             : 
     458        4006 : static int OGRSQLiteVFSCurrentTimeInt64(sqlite3_vfs * /*pVFS*/,
     459             :                                         sqlite3_int64 *piNow)
     460             : {
     461             :     struct timeval sNow;
     462        4006 :     constexpr sqlite3_int64 unixEpoch = 24405875 * (sqlite3_int64)8640000;
     463        4006 :     (void)gettimeofday(&sNow, nullptr); /* Cannot fail given valid arguments */
     464        4006 :     *piNow =
     465        4006 :         unixEpoch + 1000 * (sqlite3_int64)sNow.tv_sec + sNow.tv_usec / 1000;
     466             : 
     467        4006 :     return SQLITE_OK;
     468             : }
     469             : #endif
     470             : 
     471           0 : static int OGRSQLiteVFSCurrentTime(sqlite3_vfs * /*pVFS*/, double *p1)
     472             : {
     473           0 :     sqlite3_int64 i = 0;
     474           0 :     int rc = OGRSQLiteVFSCurrentTimeInt64(nullptr, &i);
     475           0 :     *p1 = i / 86400000.0;
     476           0 :     return rc;
     477             : }
     478             : 
     479          28 : static int OGRSQLiteVFSGetLastError(sqlite3_vfs *pVFS, int p1, char *p2)
     480             : {
     481          28 :     sqlite3_vfs *pUnderlyingVFS = GET_UNDERLYING_VFS(pVFS);
     482             :     // CPLDebug("SQLITE", "OGRSQLiteVFSGetLastError()");
     483          28 :     return pUnderlyingVFS->xGetLastError(pUnderlyingVFS, p1, p2);
     484             : }
     485             : 
     486        2418 : sqlite3_vfs *OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void *pfnUserData)
     487             : {
     488        2418 :     sqlite3_vfs *pDefaultVFS = sqlite3_vfs_find(nullptr);
     489        2418 :     sqlite3_vfs *pMyVFS = (sqlite3_vfs *)CPLCalloc(1, sizeof(sqlite3_vfs));
     490             : 
     491             :     OGRSQLiteVFSAppDataStruct *pVFSAppData =
     492        2418 :         (OGRSQLiteVFSAppDataStruct *)CPLCalloc(
     493             :             1, sizeof(OGRSQLiteVFSAppDataStruct));
     494             :     char szPtr[32];
     495        2418 :     snprintf(szPtr, sizeof(szPtr), "%p", pVFSAppData);
     496        2418 :     snprintf(pVFSAppData->szVFSName, sizeof(pVFSAppData->szVFSName),
     497             :              "OGRSQLITEVFS_%s", szPtr);
     498        2418 :     pVFSAppData->pDefaultVFS = pDefaultVFS;
     499        2418 :     pVFSAppData->pfn = pfn;
     500        2418 :     pVFSAppData->pfnUserData = pfnUserData;
     501        2418 :     pVFSAppData->nCounter = 0;
     502             : 
     503        2418 :     pMyVFS->iVersion = 2;
     504        2418 :     pMyVFS->szOsFile = sizeof(OGRSQLiteFileStruct);
     505             :     // must be large enough to hold potentially very long names like
     506             :     // /vsicurl/.... with AWS S3 security tokens
     507        2418 :     pMyVFS->mxPathname =
     508        2418 :         atoi(CPLGetConfigOption("OGR_SQLITE_VFS_MAXPATHNAME", "2048"));
     509        2418 :     pMyVFS->zName = pVFSAppData->szVFSName;
     510        2418 :     pMyVFS->pAppData = pVFSAppData;
     511        2418 :     pMyVFS->xOpen = OGRSQLiteVFSOpen;
     512        2418 :     pMyVFS->xDelete = OGRSQLiteVFSDelete;
     513        2418 :     pMyVFS->xAccess = OGRSQLiteVFSAccess;
     514        2418 :     pMyVFS->xFullPathname = OGRSQLiteVFSFullPathname;
     515        2418 :     pMyVFS->xDlOpen = OGRSQLiteVFSDlOpen;
     516        2418 :     pMyVFS->xDlError = OGRSQLiteVFSDlError;
     517        2418 :     pMyVFS->xDlSym = OGRSQLiteVFSDlSym;
     518        2418 :     pMyVFS->xDlClose = OGRSQLiteVFSDlClose;
     519        2418 :     pMyVFS->xRandomness = OGRSQLiteVFSRandomness;
     520        2418 :     pMyVFS->xSleep = OGRSQLiteVFSSleep;
     521        2418 :     pMyVFS->xCurrentTime = OGRSQLiteVFSCurrentTime;
     522        2418 :     pMyVFS->xGetLastError = OGRSQLiteVFSGetLastError;
     523        2418 :     pMyVFS->xCurrentTimeInt64 = OGRSQLiteVFSCurrentTimeInt64;
     524             : 
     525        2418 :     return pMyVFS;
     526             : }

Generated by: LCOV version 1.14