tkeyvfs_noroot.cc
Go to the documentation of this file.
1 /*#include "sqliteInt.h"*/
2 
3 // Ignore warnings in order to preserve the relationship between this
4 // file and the VFS template from which it was taken.
5 #pragma GCC diagnostic ignored "-Wcast-qual"
6 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
7 #pragma GCC diagnostic ignored "-Wunused-function"
8 #pragma GCC diagnostic ignored "-Wunused-parameter"
9 #pragma GCC diagnostic ignored "-Wunused-variable"
10 
11 #ifdef __clang__
12 #pragma clang diagnostic ignored "-Wunused-value"
13 #pragma clang diagnostic ignored "-Wc++11-narrowing"
14 #else
15 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
16 #endif
17 
18 extern "C" {
19 #include <sqlite3.h>
20 }
21 #define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
22 #define SQLITE_FCNTL_SIZE_HINT 5
23 #define SQLITE_FCNTL_CHUNK_SIZE 6
24 #define SQLITE_FCNTL_SYNC_OMITTED 8
25 
26 #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
27 #define SQLITE_DEFAULT_SECTOR_SIZE 512
28 
29 #define UNUSED_PARAMETER(x) (void)(x)
30 #define UNUSED_PARAMETER2(x, y) UNUSED_PARAMETER(x), UNUSED_PARAMETER(y)
31 
32 #define ArraySize(X) ((int)(sizeof(X) / sizeof(X[0])))
33 
34 typedef sqlite_int64 i64;
35 
36 #define _LARGE_FILE 1
37 #define _FILE_OFFSET_BITS 64
38 #define _LARGEFILE_SOURCE 1
39 
40 /*
41  * Save db to root file on close.
42  */
43 
44 #ifndef TKEYVFS_NO_ROOT
45 #include "TFile.h"
46 #include "TKey.h"
47 #endif // TKEYVFS_NO_ROOT
48 
49 #include <cassert>
50 #include <cerrno>
51 #include <cstdio>
52 #include <cstdlib>
53 #include <cstring>
54 extern "C" {
55 #include <dlfcn.h>
56 #include <fcntl.h>
57 #include <sys/stat.h>
58 #include <sys/time.h>
59 #include <sys/types.h>
60 #include <time.h>
61 #include <unistd.h>
62 }
63 
64 /*
65  * Debug tracing.
66  */
67 
68 #define TKEYVFS_TRACE 0
69 
70 /*
71  * Externally provided ROOT file, must be open.
72  */
73 
74 #ifndef TKEYVFS_NO_ROOT
75 static TFile* gRootFile;
76 #endif // TKEYVFS_NO_ROOT
77 
78 /*
79  * Memory Page size.
80  */
81 
82 #define MEMPAGE 2048
83 
84 /*
85 ** Maximum supported path-length.
86 */
87 #define MAX_PATHNAME 512
88 
89 #define SQLITE_TEMP_FILE_PREFIX "etilqs_"
90 
91 /*
92 ** The unixFile structure is subclass of sqlite3_file specific to the unix
93 ** VFS implementations.
94 */
95 struct unixFile {
96  sqlite3_io_methods const* pMethod; /* Always the first entry */
97 #ifndef TKEYVFS_NO_ROOT
98  TFile* rootFile; /* The ROOT file the db is stored in */
99  int saveToRootFile; /* On close, save db to root file */
100 #endif // TKEYVFS_NO_ROOT
101  char* pBuf; /* File contents */
102  i64 bufAllocated; /* File buffer size in bytes */
103  i64 fileSize; /* Current file size in bytes */
104  int eFileLock; /* The type of lock held on this fd */
105  int lastErrno; /* The unix errno from last I/O error */
106  const char* zPath; /* Name of the file */
107  int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
108  /* The next group of variables are used to track whether or not the
109  ** transaction counter in bytes 24-27 of database files are updated
110  ** whenever any part of the database changes. An assertion fault will
111  ** occur if a file is updated without also updating the transaction
112  ** counter. This test is made to avoid new problems similar to the
113  ** one described by ticket #3584.
114  */
115  unsigned char transCntrChng; /* True if the transaction counter changed */
116  unsigned char dbUpdate; /* True if any part of database file changed */
117  unsigned char inNormalWrite; /* True if in a normal write operation */
118 };
119 typedef struct unixFile unixFile;
120 
121 /*
122 ** Define various macros that are missing from some systems.
123 ** Must come after the include of the system headers.
124 */
125 #ifndef O_LARGEFILE
126 #define O_LARGEFILE 0
127 #endif
128 #ifdef SQLITE_DISABLE_LFS
129 #undef O_LARGEFILE
130 #define O_LARGEFILE 0
131 #endif
132 #ifndef O_NOFOLLOW
133 #define O_NOFOLLOW 0
134 #endif
135 #ifndef O_BINARY
136 #define O_BINARY 0
137 #endif
138 
139 #if 0 // F13
140 typedef void (*sqlite3_syscall_ptr)(void);
141 #endif // 0
142 
143 /* Function Directory */
144 static int sqlite3CantopenError(int lineno);
145 static int sqlite3Strlen30(const char* z);
146 static const sqlite3_io_methods* nolockIoFinderImpl(const char* z, unixFile* p);
147 static int unixLogErrorAtLine(int errcode,
148  const char* zFunc,
149  const char* zPath,
150  int iLine);
151 static int robust_open(const char* z, int f, int m);
152 static void robust_close(unixFile* pFile, int h, int lineno);
153 static int unixGetTempname(int nBuf, char* zBuf);
154 static int fcntlSizeHint(unixFile* pFile, i64 nByte);
155 static int seekAndRead(unixFile* id, sqlite3_int64 offset, void* pBuf, int cnt);
156 static int seekAndWrite(unixFile* id, i64 offset, const void* pBuf, int cnt);
157 /* IoMethods calls */
158 static int nolockClose(sqlite3_file* id);
159 static int unixRead(sqlite3_file* id,
160  void* pBuf,
161  int amt,
162  sqlite3_int64 offset);
163 static int unixWrite(sqlite3_file* id,
164  const void* pBuf,
165  int amt,
166  sqlite3_int64 offset);
167 static int unixTruncate(sqlite3_file* id, i64 nByte);
168 static int unixSync(sqlite3_file* id, int flags);
169 static int unixFileSize(sqlite3_file* id, i64* pSize);
170 static int nolockLock(sqlite3_file* NotUsed, int NotUsed2);
171 static int nolockUnlock(sqlite3_file* NotUsed, int NotUsed2);
172 static int nolockCheckReservedLock(sqlite3_file* NotUsed, int* pResOut);
173 static int unixFileControl(sqlite3_file* id, int op, void* pArg);
174 static int unixSectorSize(sqlite3_file* NotUsed);
175 static int unixDeviceCharacteristics(sqlite3_file* NotUsed);
176 /* VFS calls */
177 static int unixOpen(sqlite3_vfs* pVfs,
178  const char* zPath,
179  sqlite3_file* pFile,
180  int flags,
181  int* pOutFlags);
182 static int unixDelete(sqlite3_vfs* NotUsed, const char* zPath, int dirSync);
183 static int unixAccess(sqlite3_vfs* NotUsed,
184  const char* zPath,
185  int flags,
186  int* pResOut);
187 static int unixFullPathname(sqlite3_vfs* pVfs,
188  const char* zPath,
189  int nOut,
190  char* zOut);
191 static void* unixDlOpen(sqlite3_vfs* NotUsed, const char* zFilename);
192 static void unixDlError(sqlite3_vfs* NotUsed, int nBuf, char* zBufOut);
193 static void (*unixDlSym(sqlite3_vfs* NotUsed, void* p, const char* zSym))(void);
194 static void unixDlClose(sqlite3_vfs* NotUsed, void* pHandle);
195 static int unixRandomness(sqlite3_vfs* NotUsed, int nBuf, char* zBuf);
196 static int unixSleep(sqlite3_vfs* NotUsed, int microseconds);
197 static int unixCurrentTime(sqlite3_vfs* NotUsed, double* prNow);
198 static int unixGetLastError(sqlite3_vfs* NotUsed, int NotUsed2, char* NotUsed3);
199 static int unixCurrentTimeInt64(sqlite3_vfs* NotUsed, sqlite3_int64* piNow);
200 static int unixSetSystemCall(sqlite3_vfs* pNotUsed,
201  const char* zName,
202  sqlite3_syscall_ptr pNewFunc);
203 static sqlite3_syscall_ptr unixGetSystemCall(sqlite3_vfs* pNotUsed,
204  const char* zName);
205 static const char* unixNextSystemCall(sqlite3_vfs* p, const char* zName);
206 /**/
207 static int
209 {
210  fprintf(stderr,
211  "tkeyvfs.c: cannot open file at line %d of [%.10s]",
212  lineno,
213  20 + sqlite3_sourceid());
214  return SQLITE_CANTOPEN;
215 }
216 #define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
217 
218 /*
219 ** Compute a string length that is limited to what can be stored in
220 ** lower 30 bits of a 32-bit signed integer.
221 **
222 ** The value returned will never be negative. Nor will it ever be greater
223 ** than the actual length of the string. For very long strings (greater
224 ** than 1GiB) the value returned might be less than the true string length.
225 */
226 static int
227 sqlite3Strlen30(const char* z)
228 {
229  const char* z2 = z;
230  if (z == 0) {
231  return 0;
232  }
233  while (*z2) {
234  z2++;
235  }
236  return 0x3fffffff & (int)(z2 - z);
237 }
238 
239 /*
240 ** Many system calls are accessed through pointer-to-functions so that
241 ** they may be overridden at runtime to facilitate fault injection during
242 ** testing and sandboxing. The following array holds the names and pointers
243 ** to all overrideable system calls.
244 */
245 static struct unix_syscall {
246  const char* zName; /* Name of the sytem call */
247  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
248  sqlite3_syscall_ptr pDefault; /* Default value */
249 } aSyscall[] = {
250  {"open", (sqlite3_syscall_ptr)open, 0},
251 #define osOpen ((int (*)(const char*, int, ...))aSyscall[0].pCurrent)
252 
253  {"close", (sqlite3_syscall_ptr)close, 0},
254 #define osClose ((int (*)(int))aSyscall[1].pCurrent)
255 
256  {"access", (sqlite3_syscall_ptr)access, 0},
257 #define osAccess ((int (*)(const char*, int))aSyscall[2].pCurrent)
258 
259  {"getcwd", (sqlite3_syscall_ptr)getcwd, 0},
260 #define osGetcwd ((char* (*)(char*, size_t))aSyscall[3].pCurrent)
261 
262  {"stat", (sqlite3_syscall_ptr)stat, 0},
263 #define osStat ((int (*)(const char*, struct stat*))aSyscall[4].pCurrent)
264 
265 /*
266 ** The DJGPP compiler environment looks mostly like Unix, but it
267 ** lacks the fcntl() system call. So redefine fcntl() to be something
268 ** that always succeeds. This means that locking does not occur under
269 ** DJGPP. But it is DOS - what did you expect?
270 */
271 #ifdef __DJGPP__
272  {"fstat", 0, 0},
273 #define osFstat(a, b, c) 0
274 #else
275  {"fstat", (sqlite3_syscall_ptr)fstat, 0},
276 #define osFstat ((int (*)(int, struct stat*))aSyscall[5].pCurrent)
277 #endif
278 
279  {"ftruncate", (sqlite3_syscall_ptr)ftruncate, 0},
280 #define osFtruncate ((int (*)(int, off_t))aSyscall[6].pCurrent)
281 
282  {"fcntl", (sqlite3_syscall_ptr)fcntl, 0},
283 #define osFcntl ((int (*)(int, int, ...))aSyscall[7].pCurrent)
284 
285  {"read", (sqlite3_syscall_ptr)read, 0},
286 #define osRead ((ssize_t(*)(int, void*, size_t))aSyscall[8].pCurrent)
287 
288 #if defined(USE_PREAD)
289  {"pread", (sqlite3_syscall_ptr)pread, 0},
290 #else
291  {"pread", (sqlite3_syscall_ptr)0, 0},
292 #endif
293 #define osPread ((ssize_t(*)(int, void*, size_t, off_t))aSyscall[9].pCurrent)
294 
295 #if defined(USE_PREAD64)
296  {"pread64", (sqlite3_syscall_ptr)pread64, 0},
297 #else
298  {"pread64", (sqlite3_syscall_ptr)0, 0},
299 #endif
300 #define osPread64 ((ssize_t(*)(int, void*, size_t, off_t))aSyscall[10].pCurrent)
301 
302  {"write", (sqlite3_syscall_ptr)write, 0},
303 #define osWrite ((ssize_t(*)(int, const void*, size_t))aSyscall[11].pCurrent)
304 
305 #if defined(USE_PREAD)
306  {"pwrite", (sqlite3_syscall_ptr)pwrite, 0},
307 #else
308  {"pwrite", (sqlite3_syscall_ptr)0, 0},
309 #endif
310 #define osPwrite \
311  ((ssize_t(*)(int, const void*, size_t, off_t))aSyscall[12].pCurrent)
312 
313 #if defined(USE_PREAD64)
314  {"pwrite64", (sqlite3_syscall_ptr)pwrite64, 0},
315 #else
316  {"pwrite64", (sqlite3_syscall_ptr)0, 0},
317 #endif
318 #define osPwrite64 \
319  ((ssize_t(*)(int, const void*, size_t, off_t))aSyscall[13].pCurrent)
320 
321  {"fchmod", (sqlite3_syscall_ptr)0, 0},
322 #define osFchmod ((int (*)(int, mode_t))aSyscall[14].pCurrent)
323 
324 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
325  {"fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0},
326 #else
327  {"fallocate", (sqlite3_syscall_ptr)0, 0},
328 #endif
329 #define osFallocate ((int (*)(int, off_t, off_t))aSyscall[15].pCurrent)
330 
331 }; /* End of the overrideable system calls */
332 
333 static const sqlite3_io_methods nolockIoMethods = {
334  1, /* iVersion */
335  nolockClose, /* xClose */
336  unixRead, /* xRead */
337  unixWrite, /* xWrite */
338  unixTruncate, /* xTruncate */
339  unixSync, /* xSync */
340  unixFileSize, /* xFileSize */
341  nolockLock, /* xLock */
342  nolockUnlock, /* xUnlock */
343  nolockCheckReservedLock, /* xCheckReservedLock */
344  unixFileControl, /* xFileControl */
345  unixSectorSize, /* xSectorSize */
346  unixDeviceCharacteristics, /* xDeviceCapabilities */
347 #if 0
348  0, /* xShmMap */
349  0, /* xShmLock */
350  0, /* xShmBarrier */
351  0 /* xShmUnmap */
352 #endif // 0
353 };
354 
355 static const sqlite3_io_methods*
357 {
358  UNUSED_PARAMETER(z);
359  UNUSED_PARAMETER(p);
360  return &nolockIoMethods;
361 }
362 
363 static const sqlite3_io_methods* (*const nolockIoFinder)(const char*,
364  unixFile* p) =
366 
367 typedef const sqlite3_io_methods* (*finder_type)(const char*, unixFile*);
368 
369 /*
370 **
371 ** This function - unixLogError_x(), is only ever called via the macro
372 ** unixLogError().
373 **
374 ** It is invoked after an error occurs in an OS function and errno has been
375 ** set. It logs a message using sqlite3_log() containing the current value of
376 ** errno and, if possible, the human-readable equivalent from strerror() or
377 ** strerror_r().
378 **
379 ** The first argument passed to the macro should be the error code that
380 ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
381 ** The two subsequent arguments should be the name of the OS function that
382 ** failed (e.g. "unlink", "open") and the the associated file-system path,
383 ** if any.
384 */
385 #define unixLogError(a, b, c) unixLogErrorAtLine(a, b, c, __LINE__)
386 static int
387 unixLogErrorAtLine(int errcode, /* SQLite error code */
388  const char* zFunc, /* Name of OS function that failed */
389  const char* zPath, /* File path associated with error */
390  int iLine /* Source line number where error occurred */
391 )
392 {
393  char* zErr; /* Message from strerror() or equivalent */
394  int iErrno = errno; /* Saved syscall error number */
395  zErr = strerror(iErrno);
396  if (zPath == 0) {
397  zPath = "";
398  }
399  fprintf(stderr,
400  "tkeyvfs.c:%d: (%d) %s(%s) - %s",
401  iLine,
402  iErrno,
403  zFunc,
404  zPath,
405  zErr);
406  return errcode;
407 }
408 
409 /*
410 ** Retry open() calls that fail due to EINTR
411 */
412 static int
413 robust_open(const char* z, int f, int m)
414 {
415  int rc;
416 #if TKEYVFS_TRACE
417  fprintf(stderr, "Begin robust_open ...\n");
418 #endif /* TKEYVFS_TRACE */
419  do {
420  rc = osOpen(z, f, m);
421  } while (rc < 0 && errno == EINTR);
422 #if TKEYVFS_TRACE
423  fprintf(stderr, "End robust_open ...\n");
424 #endif /* TKEYVFS_TRACE */
425  return rc;
426 }
427 
428 /*
429 ** Close a file descriptor.
430 **
431 ** We assume that close() almost always works, since it is only in a
432 ** very sick application or on a very sick platform that it might fail.
433 ** If it does fail, simply leak the file descriptor, but do log the
434 ** error.
435 **
436 ** Note that it is not safe to retry close() after EINTR since the
437 ** file descriptor might have already been reused by another thread.
438 ** So we don't even try to recover from an EINTR. Just log the error
439 ** and move on.
440 */
441 static void
442 robust_close(unixFile* pFile, int h, int lineno)
443 {
444 /**/
445 #if TKEYVFS_TRACE
446  fprintf(stderr, "Begin robust_close ...\n");
447 #endif /* TKEYVFS_TRACE */
448  if (osClose(h)) {
449  if (pFile) {
450  unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close", pFile->zPath, lineno);
451  } else {
452  unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close", 0, lineno);
453  }
454  }
455 #if TKEYVFS_TRACE
456  fprintf(stderr, "End robust_close ...\n");
457 #endif /* TKEYVFS_TRACE */
458  /**/
459 }
460 
461 /*
462  * ** This function performs the parts of the "close file" operation
463  * ** common to all locking schemes. It closes the directory and file
464  * ** handles, if they are valid, and sets all fields of the unixFile
465  * ** structure to 0.
466  * **
467  * ** It is *not* necessary to hold the mutex when this routine is called,
468  * ** even on VxWorks. A mutex will be acquired on VxWorks by the
469  * ** vxworksReleaseFileId() routine.
470  * */
471 static int
472 closeUnixFile(sqlite3_file* id)
473 {
474  unixFile* pFile = (unixFile*)id;
475 #if TKEYVFS_TRACE
476  fprintf(stderr, "Begin closeUnixFile ...\n");
477  if (((unixFile*)id)->zPath) {
478  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
479  }
480 #ifndef TKEYVFS_NO_ROOT
481  fprintf(stderr, "saveToRootFile: %d\n", ((unixFile*)id)->saveToRootFile);
482 #endif // TKEYVFS_NO_ROOT
483 #endif /* TKEYVFS_TRACE */
484 #ifndef TKEYVFS_NO_ROOT
485  if (pFile->saveToRootFile) {
486  /**/
487 #if TKEYVFS_TRACE
488  fprintf(
489  stderr, "fileSize: 0x%016lx\n", (unsigned long long)pFile->fileSize);
490 #endif /* TKEYVFS_TRACE */
491  /* Create a tkey which will contain the contents
492  ** of the database in the root file */
493  TKey* k = new TKey(pFile->zPath,
494  "sqlite3 database file",
495  TKey::Class(),
496  pFile->fileSize /*nbytes*/,
497  pFile->rootFile /*dir*/);
498 #if TKEYVFS_TRACE
499  /* Ask the key for the size of the database file it contains. */
500  Int_t objlen = k->GetObjlen();
501  fprintf(stderr, "objlen: %d\n", objlen);
502 #endif /* TKEYVFS_TRACE */
503  /* Add the new key to the root file toplevel directory. */
504  /* Note: The tkey is now owned by the root file. */
505  Int_t cycle = pFile->rootFile->AppendKey(k);
506  /* Get a pointer to the i/o buffer inside the tkey. */
507  char* p = k->GetBuffer();
508  /* Copy the entire in-memory database file into the tkey i/o buffer. */
509  (void*)memcpy((void*)p, (void*)pFile->pBuf, (size_t)pFile->fileSize);
510  /* Write the tkey contents to the root file. */
511  /* Note: This has not yet written the top-level directory entry for the key.
512  */
513  Int_t cnt = k->WriteFile(cycle, 0 /*file*/);
514  if (cnt == -1) {
515  /* bad */
516  fprintf(stderr,
517  "tkeyvfs: failed to write root tkey containing database "
518  "to root file!\n");
519  }
520  /* Force the root file to flush the top-level directory entry for our tkey
521  * to disk. */
522  cnt = pFile->rootFile->Write();
523  if (cnt < 0) {
524  /* bad */
525  fprintf(stderr, "tkeyvfs: failed to write root file to disk!\n");
526  }
527  }
528 #endif // TKEYVFS_NO_ROOT
529  if (pFile->pBuf != nullptr) {
530  free(pFile->pBuf);
531  }
532  if (pFile->zPath != nullptr) {
533  free((void*)pFile->zPath);
534  }
535  memset(pFile, 0, sizeof(unixFile));
536 #if TKEYVFS_TRACE
537  fprintf(stderr, "End closeUnixFile ...\n");
538 #endif /* TKEYVFS_TRACE */
539  return SQLITE_OK;
540 }
541 
542 /*
543 ** Create a temporary file name in zBuf. zBuf must be allocated
544 ** by the calling process and must be big enough to hold at least
545 ** pVfs->mxPathname bytes.
546 */
547 static int
548 unixGetTempname(int nBuf, char* zBuf)
549 {
550  static const unsigned char zChars[] = "abcdefghijklmnopqrstuvwxyz"
551  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
552  "0123456789";
553  unsigned int i, j;
554 #if TKEYVFS_TRACE
555  fprintf(stderr, "Begin unixGetTempname ...\n");
556 #endif /* TKEYVFS_TRACE */
557  /* Check that the output buffer is large enough for the temporary file
558  ** name. If it is not, return SQLITE_ERROR.
559  */
560  if ((strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= (size_t)nBuf) {
561  /**/
562 #if TKEYVFS_TRACE
563  fprintf(stderr, "End unixGetTempname ...\n");
564 #endif /* TKEYVFS_TRACE */
565  return SQLITE_ERROR;
566  }
567  sqlite3_snprintf(nBuf - 17, zBuf, SQLITE_TEMP_FILE_PREFIX);
568  j = (int)strlen(zBuf);
569  sqlite3_randomness(15, &zBuf[j]);
570  for (i = 0; i < 15; i++, j++) {
571  zBuf[j] = (char)zChars[((unsigned char)zBuf[j]) % (sizeof(zChars) - 1)];
572  }
573  zBuf[j] = 0;
574 #if TKEYVFS_TRACE
575  fprintf(stderr, "End unixGetTempname ...\n");
576 #endif /* TKEYVFS_TRACE */
577  return SQLITE_OK;
578 }
579 
580 /*
581 ** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
582 ** file-control operation.
583 **
584 ** If the user has configured a chunk-size for this file, it could be
585 ** that the file needs to be extended at this point. Otherwise, the
586 ** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
587 */
588 static int
589 fcntlSizeHint(unixFile* pFile, i64 nByte)
590 {
591 /**/
592 #if TKEYVFS_TRACE
593  fprintf(stderr, "Begin fcntlSizeHint ...\n");
594 #endif /* TKEYVFS_TRACE */
595  if (pFile->szChunk) {
596  i64 nSize; /* Required file size */
597  i64 nAlloc;
598  nSize = ((nByte + (pFile->szChunk - 1)) / pFile->szChunk) * pFile->szChunk;
599  nAlloc = ((nSize + ((i64)(MEMPAGE - 1))) / ((i64)MEMPAGE)) * ((i64)MEMPAGE);
600  if ((nSize > pFile->fileSize) && (nAlloc > pFile->bufAllocated)) {
601  if (nAlloc > pFile->bufAllocated) {
602  char* pNewBuf = (char*)realloc((void*)pFile->pBuf, (size_t)nAlloc);
603  if (pNewBuf == nullptr) {
604  /**/
605 #if TKEYVFS_TRACE
606  fprintf(stderr, "End fcntlSizeHint ...\n");
607 #endif /* TKEYVFS_TRACE */
608  return SQLITE_IOERR_WRITE;
609  }
610  (void)memset(
611  pNewBuf + pFile->fileSize, 0, (size_t)(nAlloc - pFile->fileSize));
612  pFile->pBuf = pNewBuf;
613  pFile->bufAllocated = nAlloc;
614  } else {
615  (void)memset(
616  pFile->pBuf + pFile->fileSize, 0, (size_t)(nSize - pFile->fileSize));
617  }
618  pFile->fileSize = nSize;
619  }
620  }
621 #if TKEYVFS_TRACE
622  fprintf(stderr, "End fcntlSizeHint ...\n");
623 #endif /* TKEYVFS_TRACE */
624  return SQLITE_OK;
625 }
626 
627 /*
628 ** Seek to the offset passed as the second argument, then read cnt
629 ** bytes into pBuf. Return the number of bytes actually read.
630 **
631 ** NB: If you define USE_PREAD or USE_PREAD64, then it might also
632 ** be necessary to define _XOPEN_SOURCE to be 500. This varies from
633 ** one system to another. Since SQLite does not define USE_PREAD
634 ** any any form by default, we will not attempt to define _XOPEN_SOURCE.
635 ** See tickets #2741 and #2681.
636 **
637 ** To avoid stomping the errno value on a failed read the lastErrno value
638 ** is set before returning.
639 */
640 static int
641 seekAndRead(unixFile* id, sqlite3_int64 offset, void* pBuf, int cnt)
642 {
643 /**/
644 #if TKEYVFS_TRACE
645  fprintf(stderr, "Begin seekAndRead ...\n");
646 #endif /* TKEYVFS_TRACE */
647  if (offset >= id->fileSize) {
648  id->lastErrno = 0;
649 #if TKEYVFS_TRACE
650  fprintf(stderr, "End seekAndRead ...\n");
651 #endif /* TKEYVFS_TRACE */
652  return 0;
653  }
654  if ((offset + cnt) > id->fileSize) {
655  cnt = (offset + cnt) - id->fileSize;
656  }
657  (void*)memcpy(pBuf, (const void*)(id->pBuf + offset), (size_t)cnt);
658 #if TKEYVFS_TRACE
659  fprintf(stderr, "End seekAndRead ...\n");
660 #endif /* TKEYVFS_TRACE */
661  return cnt;
662 }
663 
664 /*
665 ** Seek to the offset in id->offset then read cnt bytes into pBuf.
666 ** Return the number of bytes actually read. Update the offset.
667 **
668 ** To avoid stomping the errno value on a failed write the lastErrno value
669 ** is set before returning.
670 */
671 static int
672 seekAndWrite(unixFile* id, i64 offset, const void* pBuf, int cnt)
673 {
674  unixFile* pFile = (unixFile*)id;
675 #if TKEYVFS_TRACE
676  fprintf(stderr, "Begin seekAndWrite ...\n");
677 #endif /* TKEYVFS_TRACE */
678  if ((offset + (i64)cnt) > id->bufAllocated) {
679  i64 nByte;
680  i64 newBufSize;
681  nByte = offset + ((i64)cnt);
682  if (pFile->szChunk) {
683  nByte =
684  ((nByte + (pFile->szChunk - 1)) / pFile->szChunk) * pFile->szChunk;
685  }
686  newBufSize =
687  ((nByte + (i64)(MEMPAGE - 1)) / ((i64)MEMPAGE)) * ((i64)MEMPAGE);
688  char* pNewBuf = (char*)realloc((void*)id->pBuf, (size_t)(newBufSize));
689  if (pNewBuf == nullptr) {
690  id->lastErrno = errno;
691 #if TKEYVFS_TRACE
692  fprintf(stderr, "End seekAndWrite ...\n");
693 #endif /* TKEYVFS_TRACE */
694  return 0;
695  }
696  if ((offset + (i64)cnt) < newBufSize) {
697  i64 zeroCnt = newBufSize - (offset + (i64)cnt);
698  (void*)memset((void*)(pNewBuf + offset + (i64)cnt), 0, (size_t)zeroCnt);
699  }
700  id->pBuf = pNewBuf;
701  id->bufAllocated = newBufSize;
702  }
703  (void*)memcpy((void*)(id->pBuf + offset), pBuf, (size_t)cnt);
704  if ((offset + (i64)cnt) > id->fileSize) {
705  id->fileSize = offset + (i64)cnt;
706  }
707 #if TKEYVFS_TRACE
708  fprintf(stderr, "End seekAndWrite ...\n");
709 #endif /* TKEYVFS_TRACE */
710  return cnt;
711 }
712 
713 /*--------------------------------------------------------------------------*/
714 /* IoMethods calls */
715 
716 static int
717 nolockClose(sqlite3_file* id)
718 {
719 /**/
720 #if TKEYVFS_TRACE
721  fprintf(stderr, "Begin nolockClose ...\n");
722 #endif /* TKEYVFS_TRACE */
723  int val = closeUnixFile(id);
724 #if TKEYVFS_TRACE
725  fprintf(stderr, "End nolockClose ...\n");
726 #endif /* TKEYVFS_TRACE */
727  return val;
728 }
729 
730 /*
731 ** Read data from a file into a buffer. Return SQLITE_OK if all
732 ** bytes were read successfully and SQLITE_IOERR if anything goes
733 ** wrong.
734 */
735 static int
736 unixRead(sqlite3_file* id, void* pBuf, int amt, sqlite3_int64 offset)
737 {
738  unixFile* pFile = (unixFile*)id;
739  int got;
740 #if TKEYVFS_TRACE
741  fprintf(stderr, "Begin unixRead ...\n");
742  if (((unixFile*)id)->zPath) {
743  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
744  }
745  fprintf(
746  stderr, "offset: 0x%016lx amt: 0x%08x\n", (unsigned long long)offset, amt);
747 #endif /* TKEYVFS_TRACE */
748  got = seekAndRead(pFile, offset, pBuf, amt);
749  if (got == amt) {
750  /**/
751 #if TKEYVFS_TRACE
752  fprintf(stderr, "End unixRead ...\n");
753 #endif /* TKEYVFS_TRACE */
754  return SQLITE_OK;
755  } else if (got < 0) {
756  /* lastErrno set by seekAndRead */
757 #if TKEYVFS_TRACE
758  fprintf(stderr, "End unixRead ...\n");
759 #endif /* TKEYVFS_TRACE */
760  return SQLITE_IOERR_READ;
761  } else {
762  pFile->lastErrno = 0; /* not a system error */
763  /* Unread parts of the buffer must be zero-filled */
764  memset(&((char*)pBuf)[got], 0, amt - got);
765 #if TKEYVFS_TRACE
766  fprintf(stderr, "End unixRead ...\n");
767 #endif /* TKEYVFS_TRACE */
768  return SQLITE_IOERR_SHORT_READ;
769  }
770 }
771 
772 /*
773 ** Write data from a buffer into a file. Return SQLITE_OK on success
774 ** or some other error code on failure.
775 */
776 static int
777 unixWrite(sqlite3_file* id, const void* pBuf, int amt, sqlite3_int64 offset)
778 {
779  unixFile* pFile = (unixFile*)id;
780  int wrote = 0;
781 #if TKEYVFS_TRACE
782  fprintf(stderr, "Begin unixWrite ...\n");
783  if (((unixFile*)id)->zPath) {
784  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
785  }
786  fprintf(
787  stderr, "offset: 0x%016lx amt: 0x%08x\n", (unsigned long long)offset, amt);
788 #endif /* TKEYVFS_TRACE */
789  /* If we are doing a normal write to a database file (as opposed to
790  ** doing a hot-journal rollback or a write to some file other than a
791  ** normal database file) then record the fact that the database
792  ** has changed. If the transaction counter is modified, record that
793  ** fact too.
794  */
795  if (pFile->inNormalWrite) {
796  pFile->dbUpdate = 1; /* The database has been modified */
797  if ((offset <= 24) && (offset + amt >= 27)) {
798  int rc;
799  char oldCntr[4];
800  rc = seekAndRead(pFile, 24, oldCntr, 4);
801  if (rc != 4 || memcmp(oldCntr, &((char*)pBuf)[24 - offset], 4) != 0) {
802  pFile->transCntrChng = 1; /* The transaction counter has changed */
803  }
804  }
805  }
806  while ((amt > 0) && ((wrote = seekAndWrite(pFile, offset, pBuf, amt)) > 0)) {
807  amt -= wrote;
808  offset += wrote;
809  pBuf = &((char*)pBuf)[wrote];
810  }
811  if (amt > 0) {
812  if (wrote < 0) {
813  /* lastErrno set by seekAndWrite */
814 #if TKEYVFS_TRACE
815  fprintf(stderr, "End unixWrite ...\n");
816 #endif /* TKEYVFS_TRACE */
817  return SQLITE_IOERR_WRITE;
818  } else {
819  pFile->lastErrno = 0; /* not a system error */
820 #if TKEYVFS_TRACE
821  fprintf(stderr, "End unixWrite ...\n");
822 #endif /* TKEYVFS_TRACE */
823  return SQLITE_FULL;
824  }
825  }
826 #if TKEYVFS_TRACE
827  fprintf(stderr, "End unixWrite ...\n");
828 #endif /* TKEYVFS_TRACE */
829  return SQLITE_OK;
830 }
831 
832 /*
833 ** Truncate an open file to a specified size
834 */
835 static int
836 unixTruncate(sqlite3_file* id, i64 nByte)
837 {
838  unixFile* pFile = (unixFile*)id;
839  int rc;
840 #if TKEYVFS_TRACE
841  fprintf(stderr, "Begin unixTruncate ...\n");
842  if (((unixFile*)id)->zPath) {
843  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
844  }
845  fprintf(stderr, "nByte: 0x%016lx\n", (unsigned long long)nByte);
846 #endif /* TKEYVFS_TRACE */
847  /* If the user has configured a chunk-size for this file, truncate the
848  ** file so that it consists of an integer number of chunks (i.e. the
849  ** actual file size after the operation may be larger than the requested
850  ** size).
851  */
852  if (pFile->szChunk) {
853  nByte = ((nByte + pFile->szChunk - 1) / pFile->szChunk) * pFile->szChunk;
854  }
855  if (nByte == 0) {
856  free(pFile->pBuf);
857  pFile->pBuf = (char*)calloc(1, MEMPAGE);
858  if (pFile->pBuf == nullptr) {
859  pFile->bufAllocated = 0;
860  pFile->fileSize = 0;
861  pFile->lastErrno = errno;
862 #if TKEYVFS_TRACE
863  fprintf(stderr, "End unixTruncate ...\n");
864 #endif /* TKEYVFS_TRACE */
865  return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
866  }
867  pFile->bufAllocated = MEMPAGE;
868  pFile->fileSize = 0;
869  } else {
870  i64 newBufSize =
871  ((nByte + (i64)(MEMPAGE - 1)) / ((i64)MEMPAGE)) * ((i64)MEMPAGE);
872  i64 zeroCnt = newBufSize - nByte;
873  char* pNewBuf = (char*)realloc((void*)pFile->pBuf, (size_t)newBufSize);
874  if (pNewBuf == nullptr) {
875  pFile->lastErrno = errno;
876 #if TKEYVFS_TRACE
877  fprintf(stderr, "End unixTruncate ...\n");
878 #endif /* TKEYVFS_TRACE */
879  return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
880  }
881  (void*)memset((void*)(pNewBuf + nByte), 0, (size_t)zeroCnt);
882  pFile->pBuf = pNewBuf;
883  pFile->bufAllocated = newBufSize;
884  pFile->fileSize = nByte;
885  }
886  /* If we are doing a normal write to a database file (as opposed to
887  ** doing a hot-journal rollback or a write to some file other than a
888  ** normal database file) and we truncate the file to zero length,
889  ** that effectively updates the change counter. This might happen
890  ** when restoring a database using the backup API from a zero-length
891  ** source.
892  */
893  if (pFile->inNormalWrite && (nByte == 0)) {
894  pFile->transCntrChng = 1;
895  }
896 #if TKEYVFS_TRACE
897  fprintf(stderr, "End unixTruncate ...\n");
898 #endif /* TKEYVFS_TRACE */
899  return SQLITE_OK;
900 }
901 
902 /*
903 ** Make sure all writes to a particular file are committed to disk.
904 **
905 ** If dataOnly==0 then both the file itself and its metadata (file
906 ** size, access time, etc) are synced. If dataOnly!=0 then only the
907 ** file data is synced.
908 **
909 ** Under Unix, also make sure that the directory entry for the file
910 ** has been created by fsync-ing the directory that contains the file.
911 ** If we do not do this and we encounter a power failure, the directory
912 ** entry for the journal might not exist after we reboot. The next
913 ** SQLite to access the file will not know that the journal exists (because
914 ** the directory entry for the journal was never created) and the transaction
915 ** will not roll back - possibly leading to database corruption.
916 */
917 static int
918 unixSync(sqlite3_file* id, int flags)
919 {
920  UNUSED_PARAMETER2(id, flags);
921 #if TKEYVFS_TRACE
922  fprintf(stderr, "Begin unixSync ...\n");
923  if (((unixFile*)id)->zPath) {
924  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
925  }
926 #endif /* TKEYVFS_TRACE */
927 #if TKEYVFS_TRACE
928  fprintf(stderr, "End unixSync ...\n");
929 #endif /* TKEYVFS_TRACE */
930  return SQLITE_OK;
931 }
932 
933 /*
934 ** Determine the current size of a file in bytes
935 */
936 static int
937 unixFileSize(sqlite3_file* id, i64* pSize)
938 {
939  unixFile* p = (unixFile*)id;
940 #if TKEYVFS_TRACE
941  fprintf(stderr, "Begin unixFileSize ...\n");
942  if (((unixFile*)id)->zPath) {
943  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
944  }
945 #endif /* TKEYVFS_TRACE */
946  *pSize = p->fileSize;
947  /* When opening a zero-size database, the findInodeInfo() procedure
948  ** writes a single byte into that file in order to work around a bug
949  ** in the OS-X msdos filesystem. In order to avoid problems with upper
950  ** layers, we need to report this file size as zero even though it is
951  ** really 1. Ticket #3260.
952  */
953  if (*pSize == 1) {
954  *pSize = 0;
955  }
956 #if TKEYVFS_TRACE
957  fprintf(stderr, "End unixFileSize ...\n");
958 #endif /* TKEYVFS_TRACE */
959  return SQLITE_OK;
960 }
961 
962 static int
963 nolockLock(sqlite3_file* id /*NotUsed*/, int NotUsed2)
964 {
965  /*UNUSED_PARAMETER2(NotUsed, NotUsed2);*/
966  UNUSED_PARAMETER(NotUsed2);
967 #if TKEYVFS_TRACE
968  fprintf(stderr, "Begin nolockLock ...\n");
969  if (((unixFile*)id)->zPath) {
970  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
971  }
972 #endif /* TKEYVFS_TRACE */
973 #if TKEYVFS_TRACE
974  fprintf(stderr, "End nolockLock ...\n");
975 #endif /* TKEYVFS_TRACE */
976  return SQLITE_OK;
977 }
978 
979 static int
980 nolockUnlock(sqlite3_file* id /*NotUsed*/, int NotUsed2)
981 {
982  /*UNUSED_PARAMETER2(NotUsed, NotUsed2);*/
983  UNUSED_PARAMETER(NotUsed2);
984 #if TKEYVFS_TRACE
985  fprintf(stderr, "Begin nolockUnlock ...\n");
986  if (((unixFile*)id)->zPath) {
987  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
988  }
989 #endif /* TKEYVFS_TRACE */
990 #if TKEYVFS_TRACE
991  fprintf(stderr, "End nolockUnlock ...\n");
992 #endif /* TKEYVFS_TRACE */
993  return SQLITE_OK;
994 }
995 
996 static int
997 nolockCheckReservedLock(sqlite3_file* id /*NotUsed*/, int* pResOut)
998 {
999 /*UNUSED_PARAMETER(NotUsed);*/
1000 #if TKEYVFS_TRACE
1001  fprintf(stderr, "Begin nolockCheckReservedLock ...\n");
1002  if (((unixFile*)id)->zPath) {
1003  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
1004  }
1005 #endif /* TKEYVFS_TRACE */
1006  *pResOut = 0;
1007 #if TKEYVFS_TRACE
1008  fprintf(stderr, "End nolockCheckReservedLock ...\n");
1009 #endif /* TKEYVFS_TRACE */
1010  return SQLITE_OK;
1011 }
1012 
1013 /*
1014 ** Information and control of an open file handle.
1015 */
1016 static int
1017 unixFileControl(sqlite3_file* id, int op, void* pArg)
1018 {
1019 /**/
1020 #if TKEYVFS_TRACE
1021  fprintf(stderr, "Begin unixFileControl ...\n");
1022  if (((unixFile*)id)->zPath) {
1023  fprintf(stderr, "filename: %s\n", ((unixFile*)id)->zPath);
1024  }
1025 #endif /* TKEYVFS_TRACE */
1026  switch (op) {
1027  case SQLITE_FCNTL_LOCKSTATE: {
1028  /**/
1029 #if TKEYVFS_TRACE
1030  fprintf(stderr, "op: LOCKSTATE\n");
1031 #endif /* TKEYVFS_TRACE */
1032  *(int*)pArg = ((unixFile*)id)->eFileLock;
1033  /*SQLITE_LOCK_NONE*/
1034 #if TKEYVFS_TRACE
1035  fprintf(stderr, "End unixFileControl ...\n");
1036 #endif /* TKEYVFS_TRACE */
1037  return SQLITE_OK;
1038  }
1039  case SQLITE_LAST_ERRNO: {
1040  /**/
1041 #if TKEYVFS_TRACE
1042  fprintf(stderr, "op: LAST_ERRNO\n");
1043 #endif /* TKEYVFS_TRACE */
1044  *(int*)pArg = ((unixFile*)id)->lastErrno;
1045 #if TKEYVFS_TRACE
1046  fprintf(stderr, "End unixFileControl ...\n");
1047 #endif /* TKEYVFS_TRACE */
1048  return SQLITE_OK;
1049  }
1050  case SQLITE_FCNTL_CHUNK_SIZE: {
1051  /**/
1052 #if TKEYVFS_TRACE
1053  fprintf(stderr, "op: CHUNK_SIZE\n");
1054  fprintf(stderr, "szChunk: %d\n", *(int*)pArg);
1055 #endif /* TKEYVFS_TRACE */
1056  ((unixFile*)id)->szChunk = *(int*)pArg;
1057 #if TKEYVFS_TRACE
1058  fprintf(stderr, "End unixFileControl ...\n");
1059 #endif /* TKEYVFS_TRACE */
1060  return SQLITE_OK;
1061  }
1062  case SQLITE_FCNTL_SIZE_HINT: {
1063  /**/
1064 #if TKEYVFS_TRACE
1065  fprintf(stderr, "op: SIZE_HINT\n");
1066  fprintf(stderr, "hint: 0x%016lx\n", *(i64*)pArg);
1067 #endif /* TKEYVFS_TRACE */
1068  int val = fcntlSizeHint((unixFile*)id, *(i64*)pArg);
1069 #if TKEYVFS_TRACE
1070  fprintf(stderr, "End unixFileControl ...\n");
1071 #endif /* TKEYVFS_TRACE */
1072  return val;
1073  }
1074  /* The pager calls this method to signal that it has done
1075  ** a rollback and that the database is therefore unchanged and
1076  ** it hence it is OK for the transaction change counter to be
1077  ** unchanged.
1078  */
1080  /**/
1081 #if TKEYVFS_TRACE
1082  fprintf(stderr, "op: DB_UNCHANGED\n");
1083 #endif /* TKEYVFS_TRACE */
1084  ((unixFile*)id)->dbUpdate = 0;
1085 #if TKEYVFS_TRACE
1086  fprintf(stderr, "End unixFileControl ...\n");
1087 #endif /* TKEYVFS_TRACE */
1088  return SQLITE_OK;
1089  }
1091  /**/
1092 #if TKEYVFS_TRACE
1093  fprintf(stderr, "op: SYNC_OMITTED\n");
1094  fprintf(stderr, "End unixFileControl ...\n");
1095 #endif /* TKEYVFS_TRACE */
1096  return SQLITE_OK; /* A no-op */
1097  }
1098  }
1099 #if TKEYVFS_TRACE
1100  fprintf(stderr, "End unixFileControl ...\n");
1101 #endif /* TKEYVFS_TRACE */
1102  return SQLITE_NOTFOUND;
1103 }
1104 
1105 /*
1106 ** Return the sector size in bytes of the underlying block device for
1107 ** the specified file. This is almost always 512 bytes, but may be
1108 ** larger for some devices.
1109 **
1110 ** SQLite code assumes this function cannot fail. It also assumes that
1111 ** if two files are created in the same file-system directory (i.e.
1112 ** a database and its journal file) that the sector size will be the
1113 ** same for both.
1114 */
1115 static int
1116 unixSectorSize(sqlite3_file* NotUsed)
1117 {
1118  UNUSED_PARAMETER(NotUsed);
1119 #if TKEYVFS_TRACE
1120  fprintf(stderr, "Begin unixSectorSize ...\n");
1121 #endif /* TKEYVFS_TRACE */
1122 #if TKEYVFS_TRACE
1123  fprintf(stderr, "End unixSectorSize ...\n");
1124 #endif /* TKEYVFS_TRACE */
1126 }
1127 
1128 /*
1129 ** Return the device characteristics for the file. This is always 0 for unix.
1130 */
1131 static int
1132 unixDeviceCharacteristics(sqlite3_file* NotUsed)
1133 {
1134  UNUSED_PARAMETER(NotUsed);
1135 #if TKEYVFS_TRACE
1136  fprintf(stderr, "Begin unixDeviceCharacteristics ...\n");
1137 #endif /* TKEYVFS_TRACE */
1138 #if TKEYVFS_TRACE
1139  fprintf(stderr, "End unixDeviceCharacteristics ...\n");
1140 #endif /* TKEYVFS_TRACE */
1141  return 0;
1142 }
1143 
1144 /*--------------------------------------------------------------------------*/
1145 /* VFS calls */
1146 
1147 /*
1148 ** Open the file zPath.
1149 **
1150 ** Previously, the SQLite OS layer used three functions in place of this
1151 ** one:
1152 **
1153 ** sqlite3OsOpenReadWrite();
1154 ** sqlite3OsOpenReadOnly();
1155 ** sqlite3OsOpenExclusive();
1156 **
1157 ** These calls correspond to the following combinations of flags:
1158 **
1159 ** ReadWrite() -> (READWRITE | CREATE)
1160 ** ReadOnly() -> (READONLY)
1161 ** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
1162 **
1163 ** The old OpenExclusive() accepted a boolean argument - "delFlag". If
1164 ** true, the file was configured to be automatically deleted when the
1165 ** file handle closed. To achieve the same effect using this new
1166 ** interface, add the DELETEONCLOSE flag to those specified above for
1167 ** OpenExclusive().
1168 */
1169 static int
1170 unixOpen(sqlite3_vfs* /*pVfs*/, /* The VFS for which this is the xOpen method */
1171  const char* zPath, /* Pathname of file to be opened */
1172  sqlite3_file* pFile, /* The file descriptor to be filled in */
1173  int flags, /* Input flags to control the opening */
1174  int* pOutFlags /* Output flags returned to SQLite core */
1175 )
1176 {
1177  unixFile* p = (unixFile*)pFile;
1178  int eType = flags & 0xFFFFFF00; /* Type of file to open */
1179  int rc = SQLITE_OK;
1180  // int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); // Not used.
1181  int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
1182  int isCreate = (flags & SQLITE_OPEN_CREATE);
1183  int isReadonly = (flags & SQLITE_OPEN_READONLY);
1184  int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
1185  char zTmpname[MAX_PATHNAME + 1];
1186  const char* zName = zPath;
1187 #if TKEYVFS_TRACE
1188  fprintf(stderr, "Begin unixOpen ...\n");
1189  if (zPath != nullptr) {
1190  fprintf(stderr, "filename: %s\n", zPath);
1191  }
1192 #endif /* TKEYVFS_TRACE */
1193  memset(p, 0, sizeof(unixFile));
1194  if (pOutFlags) {
1195  *pOutFlags = flags;
1196  }
1197  if (!zName) {
1198  rc = unixGetTempname(MAX_PATHNAME + 1, zTmpname);
1199  if (rc != SQLITE_OK) {
1200  return rc;
1201  }
1202  zName = zTmpname;
1203  }
1204  if (zName != nullptr) {
1205  p->zPath = (char*)malloc(strlen(zName) + 1);
1206  if (p->zPath != nullptr) {
1207  (void*)strcpy((char*)p->zPath, zName);
1208  }
1209  }
1210  p->lastErrno = 0;
1211  p->pMethod = &nolockIoMethods;
1212 #ifndef TKEYVFS_NO_ROOT
1213  p->rootFile = nullptr;
1214  if (eType & SQLITE_OPEN_MAIN_DB) {
1215  p->rootFile = gRootFile;
1216  }
1217  p->saveToRootFile =
1218  (p->rootFile && p->rootFile->IsWritable() &&
1219  (eType & SQLITE_OPEN_MAIN_DB) && (isCreate || isReadWrite) && !isDelete);
1220 #endif // TKEYVFS_NO_ROOT
1221  if ((eType & SQLITE_OPEN_MAIN_DB) && !isCreate) {
1222  /**/
1223  i64 nBytes = 0;
1224  i64 nAlloc = 0;
1225 #ifndef TKEYVFS_NO_ROOT
1226  Bool_t status = kFALSE;
1227  TKey* k = 0;
1228  char* pKeyBuf = 0;
1229  /* Read the highest numbered cycle of the tkey which contains
1230  ** the database from the root file. */
1231  k = p->rootFile->GetKey(p->zPath, 9999 /*cycle*/);
1232  /* Force the tkey to allocate an i/o buffer for its contents. */
1233  k->SetBuffer();
1234  /* Read the contents of the tkey from the root file. */
1235  status = k->ReadFile();
1236  if (!status) {
1237  /**/
1238 #if TKEYVFS_TRACE
1239  fprintf(stderr, "End unixOpen ...\n");
1240 #endif /* TKEYVFS_TRACE */
1241  rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
1242  return rc;
1243  }
1244  /* Get a pointer to the tkey i/o buffer. */
1245  pKeyBuf = k->GetBuffer();
1246  /* Get the size of the contained database file from the tkey. */
1247  nBytes = k->GetObjlen();
1248  /* Allocate enough memory pages to contain the database file. */
1249  nAlloc =
1250  ((nBytes + ((i64)(MEMPAGE - 1))) / ((i64)MEMPAGE)) * ((i64)MEMPAGE);
1251  p->pBuf = (char*)malloc((size_t)nAlloc);
1252 #else // TKEYVFS_NO_ROOT
1253  /* If not using root, a database file read is a noop. */
1254  nBytes = 0;
1255  nAlloc = MEMPAGE;
1256  p->pBuf = (char*)calloc(1, MEMPAGE);
1257 #endif // TKEYVFS_NO_ROOT
1258  if (p->pBuf == nullptr) {
1259  /**/
1260 #if TKEYVFS_TRACE
1261  fprintf(stderr, "End unixOpen ...\n");
1262 #endif /* TKEYVFS_TRACE */
1263  rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
1264  return rc;
1265  }
1266 #ifndef TKEYVFS_NO_ROOT
1267  /* Copy the entire database file from the tkey i/o buffer
1268  ** into our in-memory database. */
1269  (void*)memcpy(p->pBuf, pKeyBuf, (size_t)nBytes);
1270 #endif // TKEYVFS_NO_ROOT
1271  p->bufAllocated = nAlloc;
1272  p->fileSize = nBytes;
1273  /**/
1274  } else {
1275  p->pBuf = (char*)calloc(1, MEMPAGE);
1276  if (p->pBuf == nullptr) {
1277  /**/
1278 #if TKEYVFS_TRACE
1279  fprintf(stderr, "End unixOpen ...\n");
1280 #endif /* TKEYVFS_TRACE */
1281  rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
1282  return rc;
1283  }
1284  p->bufAllocated = MEMPAGE;
1285  p->fileSize = 0;
1286  }
1287  rc = SQLITE_OK;
1288 #if TKEYVFS_TRACE
1289  fprintf(stderr, "End unixOpen ...\n");
1290 #endif /* TKEYVFS_TRACE */
1291  return rc;
1292 }
1293 
1294 /*
1295 ** Delete the file at zPath. If the dirSync argument is true, fsync()
1296 ** the directory after deleting the file.
1297 */
1298 static int
1299 unixDelete(sqlite3_vfs* NotUsed, /* VFS containing this as the xDelete method */
1300  const char* /*zPath*/, /* Name of file to be deleted */
1301  int /*dirSync*/ /* If true, fsync() directory after deleting file */
1302 )
1303 {
1304  int rc = SQLITE_OK;
1305  UNUSED_PARAMETER(NotUsed);
1306 #if TKEYVFS_TRACE
1307  fprintf(stderr, "Begin unixDelete ...\n");
1308  if (zPath != nullptr) {
1309  fprintf(stderr, "filename: %s\n", zPath);
1310  }
1311 #endif /* TKEYVFS_TRACE */
1312 #if TKEYVFS_TRACE
1313  fprintf(stderr, "End unixDelete ...\n");
1314 #endif /* TKEYVFS_TRACE */
1315  return rc;
1316 }
1317 
1318 /*
1319 ** Test the existance of or access permissions of file zPath. The
1320 ** test performed depends on the value of flags:
1321 **
1322 ** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
1323 ** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
1324 ** SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
1325 **
1326 ** Otherwise return 0.
1327 */
1328 static int
1329 unixAccess(sqlite3_vfs* NotUsed, /* The VFS containing this xAccess method */
1330  const char* /*zPath*/, /* Path of the file to examine */
1331  int flags, /* What do we want to learn about the zPath file? */
1332  int* pResOut /* Write result boolean here */
1333 )
1334 {
1335  int amode = 0;
1336  UNUSED_PARAMETER(NotUsed);
1337 #if TKEYVFS_TRACE
1338  fprintf(stderr, "Begin unixAccess ...\n");
1339  if (zPath != nullptr) {
1340  fprintf(stderr, "filename: %s\n", zPath);
1341  }
1342 #endif /* TKEYVFS_TRACE */
1343  switch (flags) {
1344  case SQLITE_ACCESS_EXISTS:
1345  /**/
1346 #if TKEYVFS_TRACE
1347  fprintf(stderr, "op: SQLITE_ACCESS_EXISTS\n");
1348 #endif /* TKEYVFS_TRACE */
1349  amode = F_OK;
1350  break;
1351  case SQLITE_ACCESS_READWRITE:
1352  /**/
1353 #if TKEYVFS_TRACE
1354  fprintf(stderr, "op: SQLITE_ACCESS_READWRITE\n");
1355 #endif /* TKEYVFS_TRACE */
1356  amode = W_OK | R_OK;
1357  break;
1358  case SQLITE_ACCESS_READ:
1359  /**/
1360 #if TKEYVFS_TRACE
1361  fprintf(stderr, "op: SQLITE_ACCESS_READ\n");
1362 #endif /* TKEYVFS_TRACE */
1363  amode = R_OK;
1364  break;
1365  default:
1366  assert(!"Invalid flags argument");
1367  }
1368  *pResOut = 0;
1369 #if TKEYVFS_TRACE
1370  fprintf(stderr, "End unixAccess ...\n");
1371 #endif /* TKEYVFS_TRACE */
1372  return SQLITE_OK;
1373 }
1374 
1375 /*
1376 ** Turn a relative pathname into a full pathname. The relative path
1377 ** is stored as a nul-terminated string in the buffer pointed to by
1378 ** zPath.
1379 **
1380 ** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
1381 ** (in this case, MAX_PATHNAME bytes). The full-path is written to
1382 ** this buffer before returning.
1383 */
1384 static int
1385 unixFullPathname(sqlite3_vfs* pVfs, /* Pointer to vfs object */
1386  const char* zPath, /* Possibly relative input path */
1387  int nOut, /* Size of output buffer in bytes */
1388  char* zOut /* Output buffer */
1389 )
1390 {
1391 /**/
1392 #if TKEYVFS_TRACE
1393  fprintf(stderr, "Begin unixFullPathName ...\n");
1394  if (zPath != nullptr) {
1395  fprintf(stderr, "filename: %s\n", zPath);
1396  }
1397 #endif /* TKEYVFS_TRACE */
1398  assert(pVfs->mxPathname == MAX_PATHNAME);
1399  UNUSED_PARAMETER(pVfs);
1400  zOut[nOut - 1] = '\0';
1401  sqlite3_snprintf(nOut, zOut, "%s", zPath);
1402 #if TKEYVFS_TRACE
1403  fprintf(stderr, "End unixFullPathName ...\n");
1404 #endif /* TKEYVFS_TRACE */
1405  return SQLITE_OK;
1406 }
1407 
1408 /*
1409 ** Interfaces for opening a shared library, finding entry points
1410 ** within the shared library, and closing the shared library.
1411 */
1412 static void*
1413 unixDlOpen(sqlite3_vfs* NotUsed, const char* zFilename)
1414 {
1415  UNUSED_PARAMETER(NotUsed);
1416 #if TKEYVFS_TRACE
1417  fprintf(stderr, "Begin unixFullPathName ...\n");
1418 #endif /* TKEYVFS_TRACE */
1419  void* p = dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
1420 #if TKEYVFS_TRACE
1421  fprintf(stderr, "End unixFullPathName ...\n");
1422 #endif /* TKEYVFS_TRACE */
1423  return p;
1424 }
1425 
1426 /*
1427 ** SQLite calls this function immediately after a call to unixDlSym() or
1428 ** unixDlOpen() fails (returns a null pointer). If a more detailed error
1429 ** message is available, it is written to zBufOut. If no error message
1430 ** is available, zBufOut is left unmodified and SQLite uses a default
1431 ** error message.
1432 */
1433 static void
1434 unixDlError(sqlite3_vfs* NotUsed, int nBuf, char* zBufOut)
1435 {
1436  const char* zErr;
1437  UNUSED_PARAMETER(NotUsed);
1438 #if TKEYVFS_TRACE
1439  fprintf(stderr, "Begin unixDlError ...\n");
1440 #endif /* TKEYVFS_TRACE */
1441  zErr = dlerror();
1442  if (zErr) {
1443  sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
1444  }
1445 #if TKEYVFS_TRACE
1446  fprintf(stderr, "End unixDlError ...\n");
1447 #endif /* TKEYVFS_TRACE */
1448  /**/
1449 }
1450 
1451 static void (*unixDlSym(sqlite3_vfs* NotUsed, void* p, const char* zSym))(void)
1452 {
1453  /*
1454  ** GCC with -pedantic-errors says that C90 does not allow a void* to be
1455  ** cast into a pointer to a function. And yet the library dlsym() routine
1456  ** returns a void* which is really a pointer to a function. So how do we
1457  ** use dlsym() with -pedantic-errors?
1458  **
1459  ** Variable x below is defined to be a pointer to a function taking
1460  ** parameters void* and const char* and returning a pointer to a function.
1461  ** We initialize x by assigning it a pointer to the dlsym() function.
1462  ** (That assignment requires a cast.) Then we call the function that
1463  ** x points to.
1464  **
1465  ** This work-around is unlikely to work correctly on any system where
1466  ** you really cannot cast a function pointer into void*. But then, on the
1467  ** other hand, dlsym() will not work on such a system either, so we have
1468  ** not really lost anything.
1469  */
1470  void (*(*x)(void*, const char*))(void);
1471  UNUSED_PARAMETER(NotUsed);
1472 #if TKEYVFS_TRACE
1473  fprintf(stderr, "Begin unixDlSym ...\n");
1474 #endif /* TKEYVFS_TRACE */
1475  x = (void (*(*)(void*, const char*))(void))dlsym;
1476  return (*x)(p, zSym);
1477 }
1478 
1479 static void
1480 unixDlClose(sqlite3_vfs* NotUsed, void* pHandle)
1481 {
1482  UNUSED_PARAMETER(NotUsed);
1483 #if TKEYVFS_TRACE
1484  fprintf(stderr, "Begin unixDlClose ...\n");
1485 #endif /* TKEYVFS_TRACE */
1486  dlclose(pHandle);
1487 #if TKEYVFS_TRACE
1488  fprintf(stderr, "End unixDlClose ...\n");
1489 #endif /* TKEYVFS_TRACE */
1490  /**/
1491 }
1492 
1493 /*
1494 ** Write nBuf bytes of random data to the supplied buffer zBuf.
1495 */
1496 static int
1497 unixRandomness(sqlite3_vfs* NotUsed, int nBuf, char* zBuf)
1498 {
1499  UNUSED_PARAMETER(NotUsed);
1500  assert((size_t)nBuf >= (sizeof(time_t) + sizeof(int)));
1501 #if TKEYVFS_TRACE
1502  fprintf(stderr, "Begin unixRandomness ...\n");
1503 #endif /* TKEYVFS_TRACE */
1504  /* We have to initialize zBuf to prevent valgrind from reporting
1505  ** errors. The reports issued by valgrind are incorrect - we would
1506  ** prefer that the randomness be increased by making use of the
1507  ** uninitialized space in zBuf - but valgrind errors tend to worry
1508  ** some users. Rather than argue, it seems easier just to initialize
1509  ** the whole array and silence valgrind, even if that means less randomness
1510  ** in the random seed.
1511  **
1512  ** When testing, initializing zBuf[] to zero is all we do. That means
1513  ** that we always use the same random number sequence. This makes the
1514  ** tests repeatable.
1515  */
1516  memset(zBuf, 0, nBuf);
1517  {
1518  int pid, fd;
1519  fd = robust_open("/dev/urandom", O_RDONLY, 0);
1520  if (fd < 0) {
1521  time_t t;
1522  time(&t);
1523  memcpy(zBuf, &t, sizeof(t));
1524  pid = getpid();
1525  memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
1526  assert(sizeof(t) + sizeof(pid) <= (size_t)nBuf);
1527  nBuf = sizeof(t) + sizeof(pid);
1528  } else {
1529  do {
1530  nBuf = osRead(fd, zBuf, nBuf);
1531  } while (nBuf < 0 && errno == EINTR);
1532  robust_close(0, fd, __LINE__);
1533  }
1534  }
1535 #if TKEYVFS_TRACE
1536  fprintf(stderr, "End unixRandomness ...\n");
1537 #endif /* TKEYVFS_TRACE */
1538  return nBuf;
1539 }
1540 
1541 /*
1542 ** Sleep for a little while. Return the amount of time slept.
1543 ** The argument is the number of microseconds we want to sleep.
1544 ** The return value is the number of microseconds of sleep actually
1545 ** requested from the underlying operating system, a number which
1546 ** might be greater than or equal to the argument, but not less
1547 ** than the argument.
1548 */
1549 static int
1550 unixSleep(sqlite3_vfs* NotUsed, int microseconds)
1551 {
1552  UNUSED_PARAMETER(NotUsed);
1553 #if TKEYVFS_TRACE
1554  fprintf(stderr, "Begin unixSleep ...\n");
1555 #endif /* TKEYVFS_TRACE */
1556  usleep(microseconds);
1557 #if TKEYVFS_TRACE
1558  fprintf(stderr, "End unixSleep ...\n");
1559 #endif /* TKEYVFS_TRACE */
1560  return microseconds;
1561 }
1562 
1563 /*
1564 ** Find the current time (in Universal Coordinated Time). Write the
1565 ** current time and date as a Julian Day number into *prNow and
1566 ** return 0. Return 1 if the time and date cannot be found.
1567 */
1568 static int
1569 unixCurrentTime(sqlite3_vfs* NotUsed, double* prNow)
1570 {
1571  sqlite3_int64 i;
1572  UNUSED_PARAMETER(NotUsed);
1573 #if TKEYVFS_TRACE
1574  fprintf(stderr, "Begin unixCurrentTime ...\n");
1575 #endif /* TKEYVFS_TRACE */
1576  unixCurrentTimeInt64(0, &i);
1577  *prNow = i / 86400000.0;
1578 #if TKEYVFS_TRACE
1579  fprintf(stderr, "End unixCurrentTime ...\n");
1580 #endif /* TKEYVFS_TRACE */
1581  return 0;
1582 }
1583 
1584 /*
1585 ** We added the xGetLastError() method with the intention of providing
1586 ** better low-level error messages when operating-system problems come up
1587 ** during SQLite operation. But so far, none of that has been implemented
1588 ** in the core. So this routine is never called. For now, it is merely
1589 ** a place-holder.
1590 */
1591 static int
1592 unixGetLastError(sqlite3_vfs* NotUsed, int NotUsed2, char* NotUsed3)
1593 {
1594  UNUSED_PARAMETER(NotUsed);
1595  UNUSED_PARAMETER(NotUsed2);
1596  UNUSED_PARAMETER(NotUsed3);
1597 #if TKEYVFS_TRACE
1598  fprintf(stderr, "Begin unixGetLastError ...\n");
1599  fprintf(stderr, "End unixGetLastError ...\n");
1600 #endif /* TKEYVFS_TRACE */
1601  return 0;
1602 }
1603 
1604 /*
1605 ** Find the current time (in Universal Coordinated Time). Write into *piNow
1606 ** the current time and date as a Julian Day number times 86_400_000. In
1607 ** other words, write into *piNow the number of milliseconds since the Julian
1608 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
1609 ** proleptic Gregorian calendar.
1610 **
1611 ** On success, return 0. Return 1 if the time and date cannot be found.
1612 */
1613 static int
1614 unixCurrentTimeInt64(sqlite3_vfs* NotUsed, sqlite3_int64* piNow)
1615 {
1616  static const sqlite3_int64 unixEpoch = 24405875 * (sqlite3_int64)8640000;
1617  struct timeval sNow;
1618 #if TKEYVFS_TRACE
1619  fprintf(stderr, "Begin unixCurrentTimeInt64 ...\n");
1620 #endif /* TKEYVFS_TRACE */
1621  gettimeofday(&sNow, 0);
1622  *piNow = unixEpoch + 1000 * (sqlite3_int64)sNow.tv_sec + sNow.tv_usec / 1000;
1623  UNUSED_PARAMETER(NotUsed);
1624 #if TKEYVFS_TRACE
1625  fprintf(stderr, "End unixCurrentTimeInt64 ...\n");
1626 #endif /* TKEYVFS_TRACE */
1627  return 0;
1628 }
1629 
1630 /*
1631 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
1632 ** "unix" VFSes. Return SQLITE_OK opon successfully updating the
1633 ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
1634 ** system call named zName.
1635 */
1636 static int
1638  sqlite3_vfs* pNotUsed, /* The VFS pointer. Not used */
1639  const char* zName, /* Name of system call to override */
1640  sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
1641 )
1642 {
1643  unsigned int i;
1644  int rc = SQLITE_NOTFOUND;
1645  UNUSED_PARAMETER(pNotUsed);
1646 #if TKEYVFS_TRACE
1647  fprintf(stderr, "Begin unixSetSystemCall ...\n");
1648 #endif /* TKEYVFS_TRACE */
1649  if (zName == 0) {
1650  /* If no zName is given, restore all system calls to their default
1651  ** settings and return nullptr
1652  */
1653  rc = SQLITE_OK;
1654  for (i = 0; i < sizeof(aSyscall) / sizeof(aSyscall[0]); i++) {
1655  if (aSyscall[i].pDefault) {
1657  }
1658  }
1659  } else {
1660  /* If zName is specified, operate on only the one system call
1661  ** specified.
1662  */
1663  for (i = 0; i < sizeof(aSyscall) / sizeof(aSyscall[0]); i++) {
1664  if (strcmp(zName, aSyscall[i].zName) == 0) {
1665  if (aSyscall[i].pDefault == 0) {
1667  }
1668  rc = SQLITE_OK;
1669  if (pNewFunc == 0) {
1670  pNewFunc = aSyscall[i].pDefault;
1671  }
1672  aSyscall[i].pCurrent = pNewFunc;
1673  break;
1674  }
1675  }
1676  }
1677 #if TKEYVFS_TRACE
1678  fprintf(stderr, "End unixSetSystemCall ...\n");
1679 #endif /* TKEYVFS_TRACE */
1680  return rc;
1681 }
1682 
1683 /*
1684 ** Return the value of a system call. Return nullptr if zName is not a
1685 ** recognized system call name. nullptr is also returned if the system call
1686 ** is currently undefined.
1687 */
1688 static sqlite3_syscall_ptr
1689 unixGetSystemCall(sqlite3_vfs* pNotUsed, const char* zName)
1690 {
1691  unsigned int i;
1692  UNUSED_PARAMETER(pNotUsed);
1693 #if TKEYVFS_TRACE
1694  fprintf(stderr, "Begin unixGetSystemCall ...\n");
1695 #endif /* TKEYVFS_TRACE */
1696  for (i = 0; i < sizeof(aSyscall) / sizeof(aSyscall[0]); i++) {
1697  if (strcmp(zName, aSyscall[i].zName) == 0) {
1698  /**/
1699 #if TKEYVFS_TRACE
1700  fprintf(stderr, "End unixGetSystemCall ...\n");
1701 #endif /* TKEYVFS_TRACE */
1702  return aSyscall[i].pCurrent;
1703  }
1704  }
1705 #if TKEYVFS_TRACE
1706  fprintf(stderr, "End unixGetSystemCall ...\n");
1707 #endif /* TKEYVFS_TRACE */
1708  return 0;
1709 }
1710 
1711 /*
1712 ** Return the name of the first system call after zName. If zName==nullptr
1713 ** then return the name of the first system call. Return nullptr if zName
1714 ** is the last system call or if zName is not the name of a valid
1715 ** system call.
1716 */
1717 static const char*
1718 unixNextSystemCall(sqlite3_vfs* p, const char* zName)
1719 {
1720  int i = -1;
1721  UNUSED_PARAMETER(p);
1722 #if TKEYVFS_TRACE
1723  fprintf(stderr, "Begin unixNextSystemCall ...\n");
1724 #endif /* TKEYVFS_TRACE */
1725  if (zName) {
1726  for (i = 0; i < ArraySize(aSyscall) - 1; i++) {
1727  if (strcmp(zName, aSyscall[i].zName) == 0) {
1728  break;
1729  }
1730  }
1731  }
1732  for (i++; i < ArraySize(aSyscall); i++) {
1733  if (aSyscall[i].pCurrent != 0) {
1734  /**/
1735 #if TKEYVFS_TRACE
1736  fprintf(stderr, "End unixNextSystemCall ...\n");
1737 #endif /* TKEYVFS_TRACE */
1738  return aSyscall[i].zName;
1739  }
1740  }
1741 #if TKEYVFS_TRACE
1742  fprintf(stderr, "End unixNextSystemCall ...\n");
1743 #endif /* TKEYVFS_TRACE */
1744  return nullptr;
1745 }
1746 
1747 #ifndef TKEYVFS_NO_ROOT
1748 class RootFileSentry {
1749 public:
1750  RootFileSentry(TFile* fPtr);
1751  ~RootFileSentry() noexcept;
1752 };
1753 
1754 RootFileSentry::RootFileSentry(TFile* fPtr)
1755 {
1756  gRootFile = fPtr;
1757 }
1758 
1760 {
1761  gRootFile = nullptr;
1762 }
1763 #endif
1764 
1765 extern "C" {
1766 int
1768 {
1769 /*
1770 ** The following macro defines an initializer for an sqlite3_vfs object.
1771 ** The name of the VFS is NAME. The pAppData is a pointer to a pointer
1772 ** to the "finder" function. (pAppData is a pointer to a pointer because
1773 ** silly C90 rules prohibit a void* from being cast to a function pointer
1774 ** and so we have to go through the intermediate pointer to avoid problems
1775 ** when compiling with -pedantic-errors on GCC.)
1776 **
1777 ** The FINDER parameter to this macro is the name of the pointer to the
1778 ** finder-function. The finder-function returns a pointer to the
1779 ** sqlite_io_methods object that implements the desired locking
1780 ** behaviors. See the division above that contains the IOMETHODS
1781 ** macro for addition information on finder-functions.
1782 **
1783 ** Most finders simply return a pointer to a fixed sqlite3_io_methods
1784 ** object. But the "autolockIoFinder" available on MacOSX does a little
1785 ** more than that; it looks at the filesystem type that hosts the
1786 ** database file and tries to choose an locking method appropriate for
1787 ** that filesystem time.
1788 */
1789 #define UNIXVFS(VFSNAME, FINDER) \
1790  { \
1791  1, /* iVersion */ \
1792  sizeof(unixFile), /* szOsFile */ \
1793  MAX_PATHNAME, /* mxPathname */ \
1794  0, /* pNext */ \
1795  VFSNAME, /* zName */ \
1796  (void*)&FINDER, /* pAppData */ \
1797  unixOpen, /* xOpen */ \
1798  unixDelete, /* xDelete */ \
1799  unixAccess, /* xAccess */ \
1800  unixFullPathname, /* xFullPathname */ \
1801  unixDlOpen, /* xDlOpen */ \
1802  unixDlError, /* xDlError */ \
1803  unixDlSym, /* xDlSym */ \
1804  unixDlClose, /* xDlClose */ \
1805  unixRandomness, /* xRandomness */ \
1806  unixSleep, /* xSleep */ \
1807  unixCurrentTime, /* xCurrentTime */ \
1808  unixGetLastError, /* xGetLastError */ \
1809  /* unixCurrentTimeInt64, v2, xCurrentTimeInt64 */ \
1810  /* unixSetSystemCall, v3, xSetSystemCall */ \
1811  /* unixGetSystemCall, v3, xGetSystemCall */ \
1812  /* unixNextSystemCall, v3, xNextSystemCall */ \
1813  }
1814  /*
1815  ** All default VFSes for unix are contained in the following array.
1816  **
1817  ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
1818  ** by the SQLite core when the VFS is registered. So the following
1819  ** array cannot be const.
1820  */
1821  static sqlite3_vfs aVfs[] = {
1822  UNIXVFS("tkeyvfs", nolockIoFinder),
1823  };
1824  unsigned int i; /* Loop counter */
1825  /* Double-check that the aSyscall[] array has been constructed
1826  ** correctly. See ticket [bb3a86e890c8e96ab] */
1827  assert(ArraySize(aSyscall) == 16);
1828  /* Register all VFSes defined in the aVfs[] array */
1829  for (i = 0; i < (sizeof(aVfs) / sizeof(sqlite3_vfs)); i++) {
1830  sqlite3_vfs_register(&aVfs[i], 0);
1831  }
1832  return SQLITE_OK;
1833 }
1834 
1835 int
1836 tkeyvfs_open_v2(const char* filename, /* Database filename (UTF-8) */
1837  sqlite3** ppDb, /* OUT: SQLite db handle */
1838  int flags /* Flags */
1839 #ifndef TKEYVFS_NO_ROOT
1840  ,
1841  TFile* rootFile /* IN-OUT: Root file, must be already open. */
1842 #endif // TKEYVFS_NO_ROOT
1843 )
1844 {
1845 #ifndef TKEYVFS_NO_ROOT
1846  RootFileSentry rfs(rootFile);
1847  // Note that the sentry *is* the correct thing to do, here:
1848  // gRootFile is required in unixOpen(), which is called as part of
1849  // the chain of functions of which sqlite3_open_v2() is the first
1850  // call. By the time we return from sqlite3_open_v2() then, we no
1851  // longer require gRootFile and the sentry can do the job of
1852  // cleaning up when it goes out of scope.
1853 #endif // TKEYVFS_NO_ROOT
1854  return sqlite3_open_v2(filename,
1855  ppDb,
1856  flags,
1857 #ifdef TKEYVFS_NO_ROOT
1858  nullptr
1859 #else
1860  "tkeyvfs"
1861 #endif
1862  );
1863 }
1864 }
#define osFstat
#define ArraySize(X)
static int nolockLock(sqlite3_file *NotUsed, int NotUsed2)
static const double m
Definition: Units.h:79
#define unixLogError(a, b, c)
#define osRead
static int unixTruncate(sqlite3_file *id, i64 nByte)
sqlite_int64 i64
Definition: tkeyvfs.cc:34
static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle)
unsigned char transCntrChng
Definition: tkeyvfs.cc:116
#define UNUSED_PARAMETER2(x, y)
RootFileSentry(TFile *fPtr)
Definition: tkeyvfs.cc:1755
static int unixWrite(sqlite3_file *id, const void *pBuf, int amt, sqlite3_int64 offset)
static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow)
TFile * rootFile
Definition: tkeyvfs.cc:99
sqlite3_syscall_ptr pDefault
Definition: tkeyvfs.cc:249
static int sqlite3CantopenError(int lineno)
#define SQLITE_FCNTL_SYNC_OMITTED
#define osClose
static int unixDelete(sqlite3_vfs *NotUsed, const char *zPath, int dirSync)
#define osGetcwd
static int unixSetSystemCall(sqlite3_vfs *pNotUsed, const char *zName, sqlite3_syscall_ptr pNewFunc)
const char * zName
Definition: tkeyvfs.cc:247
char * pBuf
Definition: tkeyvfs.cc:102
static int unixRead(sqlite3_file *id, void *pBuf, int amt, sqlite3_int64 offset)
sqlite3_syscall_ptr pCurrent
Definition: tkeyvfs.cc:248
static int unixLogErrorAtLine(int errcode, const char *zFunc, const char *zPath, int iLine)
static const sqlite3_io_methods *(*const nolockIoFinder)(const char *, unixFile *p)
#define SQLITE_FCNTL_DB_UNCHANGED
static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut)
#define osPwrite
#define osPwrite64
static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt)
static int unixAccess(sqlite3_vfs *NotUsed, const char *zPath, int flags, int *pResOut)
static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow)
static int robust_open(const char *z, int f, int m)
static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut)
#define osPread
static int unixOpen(sqlite3_vfs *pVfs, const char *zPath, sqlite3_file *pFile, int flags, int *pOutFlags)
#define SQLITE_TEMP_FILE_PREFIX
#define SQLITE_FCNTL_SIZE_HINT
~RootFileSentry() noexcept
Definition: tkeyvfs.cc:1760
static const sqlite3_io_methods * nolockIoFinderImpl(const char *z, unixFile *p)
#define osStat
static struct unix_syscall aSyscall[]
#define osWrite
static TFile * gRootFile
static int unixSync(sqlite3_file *id, int flags)
static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3)
static const char * unixNextSystemCall(sqlite3_vfs *p, const char *zName)
#define MEMPAGE
int eFileLock
Definition: tkeyvfs.cc:105
static int closeUnixFile(sqlite3_file *id)
double z
static sqlite3_syscall_ptr unixGetSystemCall(sqlite3_vfs *pNotUsed, const char *zName)
#define osFallocate
#define osAccess
static int unixGetTempname(int nBuf, char *zBuf)
sqlite_int64 i64
#define osFcntl
sqlite3_io_methods const * pMethod
Definition: tkeyvfs.cc:97
int saveToRootFile
Definition: tkeyvfs.cc:100
static void robust_close(unixFile *pFile, int h, int lineno)
unsigned char inNormalWrite
Definition: tkeyvfs.cc:118
#define UNUSED_PARAMETER(x)
int h
Definition: myvfs.c:113
static void(*)(void) unixDlSym(sqlite3_vfs *NotUsed, void *p, const char *zSym)
p
Definition: test.py:228
#define MAX_PATHNAME
i64 bufAllocated
Definition: tkeyvfs.cc:103
static int nolockClose(sqlite3_file *id)
int tkeyvfs_open_v2(const char *filename, sqlite3 **ppDb, int flags, TFile *rootFile )
static int unixDeviceCharacteristics(sqlite3_file *NotUsed)
static int unixFileSize(sqlite3_file *id, i64 *pSize)
static int fcntlSizeHint(unixFile *pFile, i64 nByte)
static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf)
int lastErrno
Definition: tkeyvfs.cc:106
static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2)
static int sqlite3Strlen30(const char *z)
static const sqlite3_io_methods nolockIoMethods
static int unixFullPathname(sqlite3_vfs *pVfs, const char *zPath, int nOut, char *zOut)
#define SQLITE_CANTOPEN_BKPT
#define osFtruncate
#define osFchmod
unsigned char dbUpdate
Definition: tkeyvfs.cc:117
int tkeyvfs_init(void)
def access(path, mode)
const char * zPath
Definition: tkeyvfs.cc:107
#define UNIXVFS(VFSNAME, FINDER)
static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt)
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds)
def open(path, mode='r', buf=-1)
int szChunk
Definition: tkeyvfs.cc:108
#define osOpen
#define SQLITE_FCNTL_CHUNK_SIZE
static int unixSectorSize(sqlite3_file *NotUsed)
i64 fileSize
Definition: tkeyvfs.cc:104
#define osPread64
static void * unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename)
static int unixFileControl(sqlite3_file *id, int op, void *pArg)
#define SQLITE_DEFAULT_SECTOR_SIZE