github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/sqlite3/vfs.c (about)

     1  #include <stdbool.h>
     2  #include <stddef.h>
     3  #include <time.h>
     4  
     5  #include "include.h"
     6  #include "sqlite3.h"
     7  
     8  int go_vfs_find(const char *zVfsName);
     9  int go_localtime(struct tm *, sqlite3_int64);
    10  
    11  int go_randomness(sqlite3_vfs *, int nByte, char *zOut);
    12  int go_sleep(sqlite3_vfs *, int microseconds);
    13  int go_current_time_64(sqlite3_vfs *, sqlite3_int64 *);
    14  
    15  int go_open(sqlite3_vfs *, sqlite3_filename zName, sqlite3_file *, int flags,
    16              int *pOutFlags, int *pOutVFS);
    17  int go_delete(sqlite3_vfs *, const char *zName, int syncDir);
    18  int go_access(sqlite3_vfs *, const char *zName, int flags, int *pResOut);
    19  int go_full_pathname(sqlite3_vfs *, const char *zName, int nOut, char *zOut);
    20  
    21  int go_close(sqlite3_file *);
    22  int go_read(sqlite3_file *, void *, int iAmt, sqlite3_int64 iOfst);
    23  int go_write(sqlite3_file *, const void *, int iAmt, sqlite3_int64 iOfst);
    24  int go_truncate(sqlite3_file *, sqlite3_int64 size);
    25  int go_sync(sqlite3_file *, int flags);
    26  int go_file_size(sqlite3_file *, sqlite3_int64 *pSize);
    27  int go_file_control(sqlite3_file *, int op, void *pArg);
    28  int go_sector_size(sqlite3_file *file);
    29  int go_device_characteristics(sqlite3_file *file);
    30  
    31  int go_lock(sqlite3_file *, int eLock);
    32  int go_unlock(sqlite3_file *, int eLock);
    33  int go_check_reserved_lock(sqlite3_file *, int *pResOut);
    34  
    35  int go_shm_map(sqlite3_file *, int iPg, int pgsz, int, void volatile **);
    36  int go_shm_lock(sqlite3_file *, int offset, int n, int flags);
    37  int go_shm_unmap(sqlite3_file *, int deleteFlag);
    38  void go_shm_barrier(sqlite3_file *);
    39  
    40  static int go_open_wrapper(sqlite3_vfs *vfs, sqlite3_filename zName,
    41                             sqlite3_file *file, int flags, int *pOutFlags) {
    42    static const sqlite3_io_methods go_io[2] = {
    43        {
    44            .iVersion = 1,
    45            .xClose = go_close,
    46            .xRead = go_read,
    47            .xWrite = go_write,
    48            .xTruncate = go_truncate,
    49            .xSync = go_sync,
    50            .xFileSize = go_file_size,
    51            .xLock = go_lock,
    52            .xUnlock = go_unlock,
    53            .xCheckReservedLock = go_check_reserved_lock,
    54            .xFileControl = go_file_control,
    55            .xSectorSize = go_sector_size,
    56            .xDeviceCharacteristics = go_device_characteristics,
    57        },
    58        {
    59            .iVersion = 2,
    60            .xClose = go_close,
    61            .xRead = go_read,
    62            .xWrite = go_write,
    63            .xTruncate = go_truncate,
    64            .xSync = go_sync,
    65            .xFileSize = go_file_size,
    66            .xLock = go_lock,
    67            .xUnlock = go_unlock,
    68            .xCheckReservedLock = go_check_reserved_lock,
    69            .xFileControl = go_file_control,
    70            .xSectorSize = go_sector_size,
    71            .xDeviceCharacteristics = go_device_characteristics,
    72            .xShmMap = go_shm_map,
    73            .xShmLock = go_shm_lock,
    74            .xShmBarrier = go_shm_barrier,
    75            .xShmUnmap = go_shm_unmap,
    76        }};
    77    int vfsID = 0;
    78    memset(file, 0, vfs->szOsFile);
    79    int rc = go_open(vfs, zName, file, flags, pOutFlags, &vfsID);
    80    if (rc) {
    81      return rc;
    82    }
    83    file->pMethods = &go_io[vfsID];
    84    return SQLITE_OK;
    85  }
    86  
    87  struct go_file {
    88    sqlite3_file base;
    89    go_handle handle;
    90  };
    91  
    92  int sqlite3_os_init() {
    93    static sqlite3_vfs os_vfs = {
    94        .iVersion = 2,
    95        .szOsFile = sizeof(struct go_file),
    96        .mxPathname = 1024,
    97        .zName = "os",
    98  
    99        .xOpen = go_open_wrapper,
   100        .xDelete = go_delete,
   101        .xAccess = go_access,
   102        .xFullPathname = go_full_pathname,
   103  
   104        .xRandomness = go_randomness,
   105        .xSleep = go_sleep,
   106        .xCurrentTimeInt64 = go_current_time_64,
   107    };
   108    return sqlite3_vfs_register(&os_vfs, /*default=*/true);
   109  }
   110  
   111  int localtime_s(struct tm *const pTm, time_t const *const pTime) {
   112    return go_localtime(pTm, (sqlite3_int64)*pTime);
   113  }
   114  
   115  sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName) {
   116    if (zVfsName && go_vfs_find(zVfsName)) {
   117      static sqlite3_vfs *go_vfs_list;
   118  
   119      for (sqlite3_vfs *it = go_vfs_list; it; it = it->pNext) {
   120        if (!strcmp(zVfsName, it->zName)) {
   121          return it;
   122        }
   123      }
   124  
   125      for (sqlite3_vfs **ptr = &go_vfs_list; *ptr;) {
   126        sqlite3_vfs *it = *ptr;
   127        if (go_vfs_find(it->zName)) {
   128          ptr = &it->pNext;
   129        } else {
   130          *ptr = it->pNext;
   131          free(it);
   132        }
   133      }
   134  
   135      sqlite3_vfs *head = go_vfs_list;
   136      go_vfs_list = malloc(sizeof(sqlite3_vfs) + strlen(zVfsName) + 1);
   137      char *name = (char *)(go_vfs_list + 1);
   138      strcpy(name, zVfsName);
   139      *go_vfs_list = (sqlite3_vfs){
   140          .iVersion = 2,
   141          .szOsFile = sizeof(struct go_file),
   142          .mxPathname = 1024,
   143          .zName = name,
   144          .pNext = head,
   145  
   146          .xOpen = go_open_wrapper,
   147          .xDelete = go_delete,
   148          .xAccess = go_access,
   149          .xFullPathname = go_full_pathname,
   150  
   151          .xRandomness = go_randomness,
   152          .xSleep = go_sleep,
   153          .xCurrentTimeInt64 = go_current_time_64,
   154      };
   155      return go_vfs_list;
   156    }
   157    return sqlite3_vfs_find_orig(zVfsName);
   158  }
   159  
   160  static_assert(offsetof(sqlite3_vfs, zName) == 16, "Unexpected offset");
   161  static_assert(offsetof(struct go_file, handle) == 4, "Unexpected offset");