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");