[tarantool-patches] Re: [PATCH v1 1/1] sql: drop useless code from os_unix.c

  • From: Kirill Shcherbatov <kshcherbatov@xxxxxxxxxxxxx>
  • To: tarantool-patches@xxxxxxxxxxxxx, Nikita Pettik <korablev@xxxxxxxxxxxxx>
  • Date: Tue, 3 Jul 2018 14:27:46 +0300

Unfortunately no. I have removed 642 lines in the patch I pushed on
the branch. Please, squash and then LGTM.
Thank you for review. I've have squashed your changes. 
I've also tested branch on FreeBSD and returned missing LARGE_FILE macro 
definition.

Nikita, please, take a look.

==========================================

Resolves #3284.
---
 src/box/sql/os.c        |  154 --
 src/box/sql/os.h        |   38 +-
 src/box/sql/os_unix.c   | 6167 ++++++++---------------------------------------
 src/box/sql/pragma.c    |    8 -
 src/box/sql/sqliteInt.h |   34 -
 5 files changed, 1069 insertions(+), 5332 deletions(-)

diff --git a/src/box/sql/os.c b/src/box/sql/os.c
index 19841bf..7c11318 100644
--- a/src/box/sql/os.c
+++ b/src/box/sql/os.c
@@ -70,16 +70,7 @@ int sqlite3_open_file_count = 0;
  *
  *     sqlite3OsRead()
  *     sqlite3OsWrite()
- *     sqlite3OsSync()
- *     sqlite3OsFileSize()
- *     sqlite3OsLock()
- *     sqlite3OsCheckReservedLock()
- *     sqlite3OsFileControl()
- *     sqlite3OsShmMap()
  *     sqlite3OsOpen()
- *     sqlite3OsDelete()
- *     sqlite3OsAccess()
- *     sqlite3OsFullPathname()
  *
  */
 #if defined(SQLITE_TEST)
@@ -123,123 +114,12 @@ sqlite3OsWrite(sqlite3_file * id, const void *pBuf, int 
amt, i64 offset)
        return id->pMethods->xWrite(id, pBuf, amt, offset);
 }
 
-int
-sqlite3OsTruncate(sqlite3_file * id, i64 size)
-{
-       return id->pMethods->xTruncate(id, size);
-}
-
-int
-sqlite3OsSync(sqlite3_file * id, int flags)
-{
-       DO_OS_MALLOC_TEST(id);
-       return id->pMethods->xSync(id, flags);
-}
-
-int
-sqlite3OsFileSize(sqlite3_file * id, i64 * pSize)
-{
-       DO_OS_MALLOC_TEST(id);
-       return id->pMethods->xFileSize(id, pSize);
-}
-
-int
-sqlite3OsLock(sqlite3_file * id, int lockType)
-{
-       DO_OS_MALLOC_TEST(id);
-       return id->pMethods->xLock(id, lockType);
-}
-
-int
-sqlite3OsUnlock(sqlite3_file * id, int lockType)
-{
-       return id->pMethods->xUnlock(id, lockType);
-}
-
-int
-sqlite3OsCheckReservedLock(sqlite3_file * id, int *pResOut)
-{
-       DO_OS_MALLOC_TEST(id);
-       return id->pMethods->xCheckReservedLock(id, pResOut);
-}
-
-/*
- * Use sqlite3OsFileControl() when we are doing something that might fail
- * and we need to know about the failures.  Use sqlite3OsFileControlHint()
- * when simply tossing information over the wall to the VFS and we do not
- * really care if the VFS receives and understands the information since it
- * is only a hint and can be safely ignored.  The sqlite3OsFileControlHint()
- * routine has no return value since the return value would be meaningless.
- */
-int
-sqlite3OsFileControl(sqlite3_file * id, int op, void *pArg)
-{
-#ifdef SQLITE_TEST
-       if (op != SQLITE_FCNTL_COMMIT_PHASETWO) {
-               /* Faults are not injected into COMMIT_PHASETWO because, 
assuming SQLite
-                * is using a regular VFS, it is called after the corresponding
-                * transaction has been committed. Injecting a fault at this 
point
-                * confuses the test scripts - the COMMIT comand returns 
SQLITE_NOMEM
-                * but the transaction is committed anyway.
-                *
-                * The core must call OsFileControl() though, not 
OsFileControlHint(),
-                * as if a custom VFS (e.g. zipvfs) returns an error here, it 
probably
-                * means the commit really has failed and an error should be 
returned
-                * to the user.
-                */
-               DO_OS_MALLOC_TEST(id);
-       }
-#endif
-       return id->pMethods->xFileControl(id, op, pArg);
-}
-
 void
 sqlite3OsFileControlHint(sqlite3_file * id, int op, void *pArg)
 {
        (void)id->pMethods->xFileControl(id, op, pArg);
 }
 
-int
-sqlite3OsSectorSize(sqlite3_file * id)
-{
-       int (*xSectorSize) (sqlite3_file *) = id->pMethods->xSectorSize;
-       return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
-}
-
-int
-sqlite3OsDeviceCharacteristics(sqlite3_file * id)
-{
-       return id->pMethods->xDeviceCharacteristics(id);
-}
-
-int
-sqlite3OsShmLock(sqlite3_file * id, int offset, int n, int flags)
-{
-       return id->pMethods->xShmLock(id, offset, n, flags);
-}
-
-void
-sqlite3OsShmBarrier(sqlite3_file * id)
-{
-       id->pMethods->xShmBarrier(id);
-}
-
-int
-sqlite3OsShmUnmap(sqlite3_file * id, int deleteFlag)
-{
-       return id->pMethods->xShmUnmap(id, deleteFlag);
-}
-
-int
-sqlite3OsShmMap(sqlite3_file * id,     /* Database file handle */
-               int iPage, int pgsz, int bExtend,       /* True to extend file 
if necessary */
-               void volatile **pp      /* OUT: Pointer to mapping */
-    )
-{
-       DO_OS_MALLOC_TEST(id);
-       return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
-}
-
 #if SQLITE_MAX_MMAP_SIZE>0
 /* The real implementation of xFetch and xUnfetch */
 int
@@ -296,30 +176,6 @@ sqlite3OsOpen(sqlite3_vfs * pVfs,
 }
 
 int
-sqlite3OsDelete(sqlite3_vfs * pVfs, const char *zPath, int dirSync)
-{
-       DO_OS_MALLOC_TEST(0);
-       assert(dirSync == 0 || dirSync == 1);
-       return pVfs->xDelete(pVfs, zPath, dirSync);
-}
-
-int
-sqlite3OsAccess(sqlite3_vfs * pVfs, const char *zPath, int flags, int *pResOut)
-{
-       DO_OS_MALLOC_TEST(0);
-       return pVfs->xAccess(pVfs, zPath, flags, pResOut);
-}
-
-int
-sqlite3OsFullPathname(sqlite3_vfs * pVfs,
-                     const char *zPath, int nPathOut, char *zPathOut)
-{
-       DO_OS_MALLOC_TEST(0);
-       zPathOut[0] = 0;
-       return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
-}
-
-int
 sqlite3OsRandomness(sqlite3_vfs * pVfs, int nByte, char *zBufOut)
 {
        return pVfs->xRandomness(pVfs, nByte, zBufOut);
@@ -480,13 +336,3 @@ sqlite3_vfs_register(sqlite3_vfs * pVfs, int makeDflt)
        assert(vfsList);
        return SQLITE_OK;
 }
-
-/*
- * Unregister a VFS so that it is no longer accessible.
- */
-int
-sqlite3_vfs_unregister(sqlite3_vfs * pVfs)
-{
-       vfsUnlink(pVfs);
-       return SQLITE_OK;
-}
diff --git a/src/box/sql/os.h b/src/box/sql/os.h
index 500b864..9476583 100644
--- a/src/box/sql/os.h
+++ b/src/box/sql/os.h
@@ -41,13 +41,6 @@
 #ifndef _SQLITE_OS_H_
 #define _SQLITE_OS_H_
 
-/* If the SET_FULLSYNC macro is not defined above, then make it
- * a no-op
- */
-#ifndef SET_FULLSYNC
-#define SET_FULLSYNC(x,y)
-#endif
-
 /*
  * The default size of a disk sector
  */
@@ -81,8 +74,7 @@
 #endif
 
 /*
- * The following values may be passed as the second argument to
- * sqlite3OsLock(). The various locks exhibit the following semantics:
+ * The various locks exhibit the following semantics:
  *
  * SHARED:    Any number of processes may hold a SHARED lock simultaneously.
  * RESERVED:  A single process may hold a RESERVED lock on a file at
@@ -92,10 +84,9 @@
  *            SHARED locks may be obtained by other processes.
  * EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
  *
- * PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
- * process that requests an EXCLUSIVE lock may actually obtain a PENDING
- * lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
- * sqlite3OsLock().
+ * PENDING_LOCK A process that requests an EXCLUSIVE lock may
+ * actually obtain a PENDING lock. This can be upgraded to an
+ * EXCLUSIVE lock.
  */
 #define NO_LOCK         0
 #define SHARED_LOCK     1
@@ -130,11 +121,7 @@
  * 1GB boundary.
  *
  */
-#ifdef SQLITE_OMIT_WSD
-#define PENDING_BYTE     (0x40000000)
-#else
 #define PENDING_BYTE      sqlite3PendingByte
-#endif
 #define RESERVED_BYTE     (PENDING_BYTE+1)
 #define SHARED_FIRST      (PENDING_BYTE+2)
 #define SHARED_SIZE       510
@@ -150,21 +137,7 @@ int sqlite3OsInit(void);
 void sqlite3OsClose(sqlite3_file *);
 int sqlite3OsRead(sqlite3_file *, void *, int amt, i64 offset);
 int sqlite3OsWrite(sqlite3_file *, const void *, int amt, i64 offset);
-int sqlite3OsTruncate(sqlite3_file *, i64 size);
-int sqlite3OsSync(sqlite3_file *, int);
-int sqlite3OsFileSize(sqlite3_file *, i64 * pSize);
-int sqlite3OsLock(sqlite3_file *, int);
-int sqlite3OsUnlock(sqlite3_file *, int);
-int sqlite3OsCheckReservedLock(sqlite3_file * id, int *pResOut);
-int sqlite3OsFileControl(sqlite3_file *, int, void *);
 void sqlite3OsFileControlHint(sqlite3_file *, int, void *);
-#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
-int sqlite3OsSectorSize(sqlite3_file * id);
-int sqlite3OsDeviceCharacteristics(sqlite3_file * id);
-int sqlite3OsShmMap(sqlite3_file *, int, int, int, void volatile **);
-int sqlite3OsShmLock(sqlite3_file * id, int, int, int);
-void sqlite3OsShmBarrier(sqlite3_file * id);
-int sqlite3OsShmUnmap(sqlite3_file * id, int);
 int sqlite3OsFetch(sqlite3_file * id, i64, int, void **);
 int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
 
@@ -172,9 +145,6 @@ int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
  * Functions for accessing sqlite3_vfs methods
  */
 int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int *);
-int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
-int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
-int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
 int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
 int sqlite3OsSleep(sqlite3_vfs *, int);
 int sqlite3OsGetLastError(sqlite3_vfs *);
diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c
index 262d178..ce21e44 100644
--- a/src/box/sql/os_unix.c
+++ b/src/box/sql/os_unix.c
@@ -29,80 +29,7 @@
  * SUCH DAMAGE.
  */
 
-/*
- *
- * This file contains the VFS implementation for unix-like operating systems.
- *
- * There are actually several different VFS implementations in this file.
- * The differences are in the way that file locking is done.  The default
- * implementation uses Posix Advisory Locks.  Alternative implementations
- * use flock(), dot-files, various proprietary locking schemas, or simply
- * skip locking all together.
- *
- * This source file is organized into divisions where the logic for various
- * subfunctions is contained within the appropriate division.  PLEASE
- * KEEP THE STRUCTURE OF THIS FILE INTACT.  New code should be placed
- * in the correct division and should be clearly labeled.
- *
- * The layout of divisions is as follows:
- *
- *   *  General-purpose declarations and utility functions.
- *   *  Various locking primitive implementations (all except proxy locking):
- *      + for Posix Advisory Locks
- *      + for no-op locks
- *      + for dot-file locks
- *      + for flock() locking
- *      + for AFP filesystem locks (MacOSX only)
- *   *  sqlite3_file methods not associated with locking.
- *   *  Definitions of sqlite3_io_methods objects for all locking
- *      methods plus "finder" functions for each locking method.
- *   *  sqlite3_vfs method implementations.
- *   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
- *   *  Definitions of sqlite3_vfs objects for all locking methods
- *      plus implementations of sqlite3_os_init() and sqlite3_os_end().
- */
 #include "sqliteInt.h"
-
-/*
- * There are various methods for file locking used for concurrency
- * control:
- *
- *   1. POSIX locking (the default),
- *   2. No locking,
- *   3. Dot-file locking,
- *   4. flock() locking,
- *   5. AFP locking (OSX only),
- *   6. proxy locking. (OSX only)
- *
- * Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
- * is defined to 1.  The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
- * selection of the appropriate locking style based on the filesystem
- * where the database is located.
- */
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-#if defined(__APPLE__)
-#define SQLITE_ENABLE_LOCKING_STYLE 1
-#else
-#define SQLITE_ENABLE_LOCKING_STYLE 0
-#endif
-#endif
-
-/* Use pread() and pwrite() if they are available */
-#if defined(__APPLE__)
-#define HAVE_PREAD 1
-#define HAVE_PWRITE 1
-#endif
-#if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64)
-#undef USE_PREAD
-#define USE_PREAD64 1
-#elif defined(HAVE_PREAD) && defined(HAVE_PWRITE)
-#undef USE_PREAD64
-#define USE_PREAD 1
-#endif
-
-/*
- * standard include files.
- */
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -110,28 +37,8 @@
 #include <time.h>
 #include <sys/time.h>
 #include <errno.h>
-#if SQLITE_MAX_MMAP_SIZE>0
 #include <sys/mman.h>
-#endif
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-#include <sys/ioctl.h>
-#include <sys/file.h>
-#include <sys/param.h>
-#endif                         /* SQLITE_ENABLE_LOCKING_STYLE */
-
-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-#include <sys/mount.h>
-#endif
-
-#ifdef HAVE_UTIME
-#include <utime.h>
-#endif
 
-/*
- * Allowed values of unixFile.fsFlags
- */
-#define SQLITE_FSFLAGS_IS_MSDOS     0x1
 
 /*
  * Default permissions when creating a new file
@@ -152,19 +59,6 @@
  */
 #define MAX_PATHNAME 512
 
-/*
- * Maximum supported symbolic links
- */
-#define SQLITE_MAX_SYMLINKS 100
-
-/*
- * Only set the lastErrno if the error code is a real error and not
- * a normal expected return code of SQLITE_BUSY or SQLITE_OK
- */
-#define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
-
-/* Forward references */
-typedef struct unixShm unixShm;        /* Connection shared memory */
 typedef struct unixShmNode unixShmNode;        /* Shared memory instance */
 typedef struct unixInodeInfo unixInodeInfo;    /* An i-node */
 typedef struct UnixUnusedFd UnixUnusedFd;      /* An unused file descriptor */
@@ -194,44 +88,14 @@ struct unixFile {
        unsigned char eFileLock;        /* The type of lock held on this fd */
        unsigned short int ctrlFlags;   /* Behavioral bits.  UNIXFILE_* flags */
        int lastErrno;          /* The unix errno from last I/O error */
-       void *lockingContext;   /* Locking style specific state */
        UnixUnusedFd *pUnused;  /* Pre-allocated UnixUnusedFd */
        const char *zPath;      /* Name of the file */
-       unixShm *pShm;          /* Shared memory segment information */
        int szChunk;            /* Configured by FCNTL_CHUNK_SIZE */
-#if SQLITE_MAX_MMAP_SIZE>0
        int nFetchOut;          /* Number of outstanding xFetch refs */
        sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */
        sqlite3_int64 mmapSizeActual;   /* Actual size of mapping at pMapRegion 
*/
        sqlite3_int64 mmapSizeMax;      /* Configured FCNTL_MMAP_SIZE value */
        void *pMapRegion;       /* Memory mapped region */
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE
-       int openFlags;          /* The flags specified at open() */
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
-       unsigned fsFlags;       /* cached details from statfs() */
-#endif
-#ifdef SQLITE_DEBUG
-       /* The next group of variables are used to track whether or not the
-        * transaction counter in bytes 24-27 of database files are updated
-        * whenever any part of the database changes.  An assertion fault will
-        * occur if a file is updated without also updating the transaction
-        * counter.  This test is made to avoid new problems similar to the
-        * one described by ticket #3584.
-        */
-       unsigned char transCntrChng;    /* True if the transaction counter 
changed */
-       unsigned char dbUpdate; /* True if any part of database file changed */
-       unsigned char inNormalWrite;    /* True if in a normal write operation 
*/
-
-#endif
-
-#ifdef SQLITE_TEST
-       /* In test mode, increase the size of this structure a bit so that
-        * it is larger than the struct CrashFile defined in test6.c.
-        */
-       char aPadding[32];
-#endif
 };
 
 /* This variable holds the process id (pid) from when the xRandomness()
@@ -245,11 +109,7 @@ static pid_t randomnessPid = 0;
  */
 #define UNIXFILE_EXCL        0x01      /* Connections from one process only */
 #define UNIXFILE_RDONLY      0x02      /* Connection is read only */
-#ifndef SQLITE_DISABLE_DIRSYNC
 #define UNIXFILE_DIRSYNC    0x08       /* Directory sync needed */
-#else
-#define UNIXFILE_DIRSYNC    0x00
-#endif
 #define UNIXFILE_DELETE      0x20      /* Delete on close */
 #define UNIXFILE_URI         0x40      /* Filename might have query parameters 
*/
 #define UNIXFILE_NOLOCK      0x80      /* Do no file locking */
@@ -262,6 +122,9 @@ static pid_t randomnessPid = 0;
 /*
  * Define various macros that are missing from some systems.
  */
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
 #ifndef O_LARGEFILE
 #define O_LARGEFILE 0
 #endif
@@ -272,293 +135,6 @@ static pid_t randomnessPid = 0;
 #ifndef O_NOFOLLOW
 #define O_NOFOLLOW 0
 #endif
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/*
- * HAVE_MREMAP defaults to true on Linux and false everywhere else.
- */
-#if !defined(HAVE_MREMAP)
-#if defined(__linux__) && defined(_GNU_SOURCE)
-#define HAVE_MREMAP 1
-#else
-#define HAVE_MREMAP 0
-#endif
-#endif
-
-
-
-/*
- * Different Unix systems declare open() in different ways.  Same use
- * open(const char*,int,mode_t).  Others use open(const char*,int,...).
- * The difference is important when using a pointer to the function.
- *
- * The safest way to deal with the problem is to always use this wrapper
- * which always has the same well-defined interface.
- */
-static int
-posixOpen(const char *zFile, int flags, int mode)
-{
-       return open(zFile, flags, mode);
-}
-
-/* Forward reference */
-static int openDirectory(const char *, int *);
-#if SQLITE_MAX_MMAP_SIZE > 0
-static int unixGetpagesize(void);
-#endif
-
-/*
- * Many system calls are accessed through pointer-to-functions so that
- * they may be overridden at runtime to facilitate fault injection during
- * testing and sandboxing.  The following array holds the names and pointers
- * to all overrideable system calls.
- */
-static struct unix_syscall {
-       const char *zName;      /* Name of the system call */
-       sqlite3_syscall_ptr pCurrent;   /* Current value of the system call */
-       sqlite3_syscall_ptr pDefault;   /* Default value */
-} aSyscall[] = {
-       {
-       "open", (sqlite3_syscall_ptr) posixOpen, 0},
-#define osOpen      ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
-       {
-       "close", (sqlite3_syscall_ptr) close, 0},
-#define osClose     ((int(*)(int))aSyscall[1].pCurrent)
-       {
-       "access", (sqlite3_syscall_ptr) access, 0},
-#define osAccess    ((int(*)(const char*,int))aSyscall[2].pCurrent)
-       {
-       "getcwd", (sqlite3_syscall_ptr) getcwd, 0},
-#define osGetcwd    ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
-       {
-       "stat", (sqlite3_syscall_ptr) stat, 0},
-#define osStat      ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
-       {
-       "fstat", (sqlite3_syscall_ptr) fstat, 0},
-#define osFstat     ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
-       {
-       "ftruncate", (sqlite3_syscall_ptr) ftruncate, 0},
-#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
-       {
-       "fcntl", (sqlite3_syscall_ptr) fcntl, 0},
-#define osFcntl     ((int(*)(int,int,...))aSyscall[7].pCurrent)
-       {
-       "read", (sqlite3_syscall_ptr) read, 0},
-#define osRead      ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
-       {
-       "pread", (sqlite3_syscall_ptr) pread, 0},
-#else
-       {
-       "pread", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osPread     ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
-#if defined(USE_PREAD64)
-       {
-       "pread64", (sqlite3_syscall_ptr) pread64, 0},
-#else
-       {
-       "pread64", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent)
-       {
-       "write", (sqlite3_syscall_ptr) write, 0},
-#define osWrite     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
-#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
-       {
-       "pwrite", (sqlite3_syscall_ptr) pwrite, 0},
-#else
-       {
-       "pwrite", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osPwrite    ((ssize_t(*)(int,const void*,size_t,off_t))\
-                    aSyscall[12].pCurrent)
-#if defined(USE_PREAD64)
-       {
-       "pwrite64", (sqlite3_syscall_ptr) pwrite64, 0},
-#else
-       {
-       "pwrite64", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off64_t))\
-                    aSyscall[13].pCurrent)
-       {
-       "fchmod", (sqlite3_syscall_ptr) fchmod, 0},
-#define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)
-#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
-       {
-       "fallocate", (sqlite3_syscall_ptr) posix_fallocate, 0},
-#else
-       {
-       "fallocate", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
-       {
-       "unlink", (sqlite3_syscall_ptr) unlink, 0},
-#define osUnlink    ((int(*)(const char*))aSyscall[16].pCurrent)
-       {
-       "openDirectory", (sqlite3_syscall_ptr) openDirectory, 0},
-#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
-       {
-       "mkdir", (sqlite3_syscall_ptr) mkdir, 0},
-#define osMkdir     ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
-       {
-       "rmdir", (sqlite3_syscall_ptr) rmdir, 0},
-#define osRmdir     ((int(*)(const char*))aSyscall[19].pCurrent)
-#if defined(HAVE_FCHOWN)
-       {
-       "fchown", (sqlite3_syscall_ptr) fchown, 0},
-#else
-       {
-       "fchown", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
-       {
-       "geteuid", (sqlite3_syscall_ptr) geteuid, 0},
-#define osGeteuid   ((uid_t(*)(void))aSyscall[21].pCurrent)
-
-#if SQLITE_MAX_MMAP_SIZE>0
-       {
-       "mmap", (sqlite3_syscall_ptr) mmap, 0},
-#else
-       {
-       "mmap", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osMmap 
((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
-#if SQLITE_MAX_MMAP_SIZE>0
-       {
-       "munmap", (sqlite3_syscall_ptr) munmap, 0},
-#else
-       {
-       "munmap", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent)
-#if HAVE_MREMAP && (SQLITE_MAX_MMAP_SIZE>0)
-       {
-       "mremap", (sqlite3_syscall_ptr) mremap, 0},
-#else
-       {
-       "mremap", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
-#if SQLITE_MAX_MMAP_SIZE>0
-       {
-       "getpagesize", (sqlite3_syscall_ptr) unixGetpagesize, 0},
-#else
-       {
-       "getpagesize", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
-#if defined(HAVE_READLINK)
-       {
-       "readlink", (sqlite3_syscall_ptr) readlink, 0},
-#else
-       {
-       "readlink", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osReadlink ((ssize_t(*)(const 
char*,char*,size_t))aSyscall[26].pCurrent)
-#if defined(HAVE_LSTAT)
-       {
-       "lstat", (sqlite3_syscall_ptr) lstat, 0},
-#else
-       {
-       "lstat", (sqlite3_syscall_ptr) 0, 0},
-#endif
-#define osLstat      ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
-};                             /* End of the overrideable system calls */
-
-
-/*
- * This is the xSetSystemCall() method of sqlite3_vfs for all of the
- * "unix" VFSes.  Return SQLITE_OK opon successfully updating the
- * system call pointer, or SQLITE_NOTFOUND if there is no configurable
- * system call named zName.
- */
-static int
-unixSetSystemCall(sqlite3_vfs * pNotUsed,      /* The VFS pointer.  Not used */
-                 const char *zName,    /* Name of system call to override */
-                 sqlite3_syscall_ptr pNewFunc  /* Pointer to new system call 
value */
-    )
-{
-       unsigned int i;
-       int rc = SQLITE_NOTFOUND;
-
-       UNUSED_PARAMETER(pNotUsed);
-       if (zName == 0) {
-               /* If no zName is given, restore all system calls to their 
default
-                * settings and return NULL
-                */
-               rc = SQLITE_OK;
-               for (i = 0; i < sizeof(aSyscall) / sizeof(aSyscall[0]); i++) {
-                       if (aSyscall[i].pDefault) {
-                               aSyscall[i].pCurrent = aSyscall[i].pDefault;
-                       }
-               }
-       } else {
-               /* If zName is specified, operate on only the one system call
-                * specified.
-                */
-               for (i = 0; i < sizeof(aSyscall) / sizeof(aSyscall[0]); i++) {
-                       if (strcmp(zName, aSyscall[i].zName) == 0) {
-                               if (aSyscall[i].pDefault == 0) {
-                                       aSyscall[i].pDefault =
-                                           aSyscall[i].pCurrent;
-                               }
-                               rc = SQLITE_OK;
-                               if (pNewFunc == 0)
-                                       pNewFunc = aSyscall[i].pDefault;
-                               aSyscall[i].pCurrent = pNewFunc;
-                               break;
-                       }
-               }
-       }
-       return rc;
-}
-
-/*
- * Return the value of a system call.  Return NULL if zName is not a
- * recognized system call name.  NULL is also returned if the system call
- * is currently undefined.
- */
-static sqlite3_syscall_ptr
-unixGetSystemCall(sqlite3_vfs * pNotUsed, const char *zName)
-{
-       unsigned int i;
-
-       UNUSED_PARAMETER(pNotUsed);
-       for (i = 0; i < sizeof(aSyscall) / sizeof(aSyscall[0]); i++) {
-               if (strcmp(zName, aSyscall[i].zName) == 0)
-                       return aSyscall[i].pCurrent;
-       }
-       return 0;
-}
-
-/*
- * Return the name of the first system call after zName.  If zName==NULL
- * then return the name of the first system call.  Return NULL if zName
- * is the last system call or if zName is not the name of a valid
- * system call.
- */
-static const char *
-unixNextSystemCall(sqlite3_vfs * p, const char *zName)
-{
-       int i = -1;
-
-       UNUSED_PARAMETER(p);
-       if (zName) {
-               for (i = 0; i < ArraySize(aSyscall) - 1; i++) {
-                       if (strcmp(zName, aSyscall[i].zName) == 0)
-                               break;
-               }
-       }
-       for (i++; i < ArraySize(aSyscall); i++) {
-               if (aSyscall[i].pCurrent != 0)
-                       return aSyscall[i].zName;
-       }
-       return 0;
-}
 
 /*
  * Do not accept any file descriptor less than this value, in order to avoid
@@ -592,11 +168,7 @@ robust_open(const char *z, int f, mode_t m)
        int fd;
        mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
        while (1) {
-#if defined(O_CLOEXEC)
-               fd = osOpen(z, f | O_CLOEXEC, m2);
-#else
-               fd = osOpen(z, f, m2);
-#endif
+               fd = open(z, f | O_CLOEXEC, m2);
                if (fd < 0) {
                        if (errno == EINTR)
                                continue;
@@ -604,95 +176,26 @@ robust_open(const char *z, int f, mode_t m)
                }
                if (fd >= SQLITE_MINIMUM_FILE_DESCRIPTOR)
                        break;
-               osClose(fd);
+               close(fd);
                sqlite3_log(SQLITE_WARNING,
                            "attempt to open \"%s\" as file descriptor %d", z,
                            fd);
                fd = -1;
-               if (osOpen("/dev/null", f, m) < 0)
+               if (open("/dev/null", f, m) < 0)
                        break;
        }
        if (fd >= 0) {
                if (m != 0) {
                        struct stat statbuf;
-                       if (osFstat(fd, &statbuf) == 0
-                           && statbuf.st_size == 0
-                           && (statbuf.st_mode & 0777) != m) {
-                               osFchmod(fd, m);
-                       }
+                       if (fstat(fd, &statbuf) == 0 &&
+                           statbuf.st_size == 0 &&
+                           (statbuf.st_mode & 0777) != m)
+                               fchmod(fd, m);
                }
-#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
-               osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
-#endif
        }
        return fd;
 }
 
-#ifdef SQLITE_LOCK_TRACE
-/*
- * Print out information about all locking operations.
- *
- * This routine is used for troubleshooting locks on multithreaded
- * platforms.  Enable by compiling with the -DSQLITE_LOCK_TRACE
- * command-line option on the compiler.  This code is normally
- * turned off.
- */
-static int
-lockTrace(int fd, int op, struct flock *p)
-{
-       char *zOpName, *zType;
-       int s;
-       int savedErrno;
-       if (op == F_GETLK) {
-               zOpName = "GETLK";
-       } else if (op == F_SETLK) {
-               zOpName = "SETLK";
-       } else {
-               s = osFcntl(fd, op, p);
-               sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
-               return s;
-       }
-       if (p->l_type == F_RDLCK) {
-               zType = "RDLCK";
-       } else if (p->l_type == F_WRLCK) {
-               zType = "WRLCK";
-       } else if (p->l_type == F_UNLCK) {
-               zType = "UNLCK";
-       } else {
-               assert(0);
-       }
-       assert(p->l_whence == SEEK_SET);
-       s = osFcntl(fd, op, p);
-       savedErrno = errno;
-       sqlite3DebugPrintf("fcntl %d %s %s %d %d %d %d\n",
-                          fd, zOpName, zType, (int)p->l_start,
-                          (int)p->l_len, (int)p->l_pid, s);
-       if (s == (-1) && op == F_SETLK
-           && (p->l_type == F_RDLCK || p->l_type == F_WRLCK)) {
-               struct flock l2;
-               l2 = *p;
-               osFcntl(fd, F_GETLK, &l2);
-               if (l2.l_type == F_RDLCK) {
-                       zType = "RDLCK";
-               } else if (l2.l_type == F_WRLCK) {
-                       zType = "WRLCK";
-               } else if (l2.l_type == F_UNLCK) {
-                       zType = "UNLCK";
-               } else {
-                       assert(0);
-               }
-               sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
-                                  zType, (int)l2.l_start, (int)l2.l_len,
-                                  (int)l2.l_pid);
-       }
-       errno = savedErrno;
-       return s;
-}
-
-#undef osFcntl
-#define osFcntl lockTrace
-#endif                         /* SQLITE_LOCK_TRACE */
-
 /*
  * Retry ftruncate() calls that fail due to EINTR
  *
@@ -704,48 +207,11 @@ robust_ftruncate(int h, sqlite3_int64 sz)
 {
        int rc;
        do {
-               rc = osFtruncate(h, sz);
+               rc = ftruncate(h, sz);
        } while (rc < 0 && errno == EINTR);
        return rc;
 }
 
-/*
- * This routine translates a standard POSIX errno code into something
- * useful to the clients of the sqlite3 functions.  Specifically, it is
- * intended to translate a variety of "try again" errors into SQLITE_BUSY
- * and a variety of "please close the file descriptor NOW" errors into
- * SQLITE_IOERR
- *
- * Errors during initialization of locks, or file system support for locks,
- * should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
- */
-static int
-sqliteErrorFromPosixError(int posixError, int sqliteIOErr)
-{
-       assert((sqliteIOErr == SQLITE_IOERR_LOCK) ||
-              (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
-              (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
-              (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK));
-       switch (posixError) {
-       case EACCES:
-       case EAGAIN:
-       case ETIMEDOUT:
-       case EBUSY:
-       case EINTR:
-       case ENOLCK:
-               /* random NFS retry error, unless during file system support
-                * introspection, in which it actually means what it says
-                */
-               return SQLITE_BUSY;
-
-       case EPERM:
-               return SQLITE_PERM;
-
-       default:
-               return sqliteIOErr;
-       }
-}
-
 /******************************************************************************
  ************************** Posix Advisory Locking ****************************
  *
@@ -861,9 +327,6 @@ struct unixInodeInfo {
        UnixUnusedFd *pUnused;  /* Unused file descriptors to close */
        unixInodeInfo *pNext;   /* List of all unixInodeInfo objects */
        unixInodeInfo *pPrev;   /*    .... doubly linked */
-#if SQLITE_ENABLE_LOCKING_STYLE
-       unsigned long long sharedByte;  /* for AFP simulated shared lock */
-#endif
 };
 
 /*
@@ -925,7 +388,7 @@ unixLogErrorAtLine(int errcode,     /* SQLite error code */
 static void
 robust_close(unixFile * pFile, int h, int lineno)
 {
-       if (osClose(h)) {
+       if (close(h) != 0) {
                unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
                                   pFile ? pFile->zPath : 0, lineno);
        }
@@ -1008,38 +471,11 @@ findInodeInfo(unixFile * pFile,  /* Unix file with file 
desc used in the key */
         * create a unique name for the file.
         */
        fd = pFile->h;
-       rc = osFstat(fd, &statbuf);
+       rc = fstat(fd, &statbuf);
        if (rc != 0) {
                storeLastErrno(pFile, errno);
                return SQLITE_IOERR;
        }
-#ifdef __APPLE__
-       /* On OS X on an msdos filesystem, the inode number is reported
-        * incorrectly for zero-size files.  See ticket #3260.  To work
-        * around this problem (we consider it a bug in OS X, not SQLite)
-        * we always increase the file size to 1 by writing a single byte
-        * prior to accessing the inode number.  The one byte written is
-        * an ASCII 'S' character which also happens to be the first byte
-        * in the header of every SQLite database.  In this way, if there
-        * is a race condition such that another thread has already populated
-        * the first page of the database, no damage is done.
-        */
-       if (statbuf.st_size == 0
-           && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS) != 0) {
-               do {
-                       rc = osWrite(fd, "S", 1);
-               } while (rc < 0 && errno == EINTR);
-               if (rc != 1) {
-                       storeLastErrno(pFile, errno);
-                       return SQLITE_IOERR;
-               }
-               rc = osFstat(fd, &statbuf);
-               if (rc != 0) {
-                       storeLastErrno(pFile, errno);
-                       return SQLITE_IOERR;
-               }
-       }
-#endif
 
        memset(&fileId, 0, sizeof(fileId));
        fileId.dev = statbuf.st_dev;
@@ -1075,9 +511,9 @@ static int
 fileHasMoved(unixFile * pFile)
 {
        struct stat buf;
-       return pFile->pInode != 0 &&
-           (osStat(pFile->zPath, &buf) != 0
-            || (u64) buf.st_ino != pFile->pInode->fileId.ino);
+       return pFile->pInode != NULL && (stat(pFile->zPath, &buf) != 0 ||
+                                        (u64) buf.st_ino !=
+                                        pFile->pInode->fileId.ino);
 }
 
 /*
@@ -1099,7 +535,7 @@ verifyDbFile(unixFile * pFile)
        if (pFile->ctrlFlags & UNIXFILE_NOLOCK)
                return;
 
-       rc = osFstat(pFile->h, &buf);
+       rc = fstat(pFile->h, &buf);
        if (rc != 0) {
                sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s",
                            pFile->zPath);
@@ -1123,34 +559,6 @@ verifyDbFile(unixFile * pFile)
 }
 
 /*
- * This routine checks if there is a RESERVED lock held on the specified
- * file by this or any other process. If such a lock is held, set *pResOut
- * to a non-zero value otherwise *pResOut is set to zero.  The return value
- * is set to SQLITE_OK unless an I/O error occurs during lock checking.
- */
-static int
-unixCheckReservedLock(sqlite3_file * id, int *pResOut)
-{
-       int rc = SQLITE_OK;
-       int reserved = 0;
-       unixFile *pFile = (unixFile *) id;
-
-       SimulateIOError(return SQLITE_IOERR_CHECKRESERVEDLOCK;
-           );
-
-       assert(pFile);
-       assert(pFile->eFileLock <= SHARED_LOCK);
-
-       /* Check if a thread in this process holds such a lock */
-       if (pFile->pInode->eFileLock > SHARED_LOCK) {
-               reserved = 1;
-       }
-
-       *pResOut = reserved;
-       return rc;
-}
-
-/*
  * Attempt to set a system-lock on the file pFile.  The lock is
  * described by pLock.
  *
@@ -1184,7 +592,7 @@ unixFileLock(unixFile * pFile, struct flock *pLock)
                        lock.l_start = SHARED_FIRST;
                        lock.l_len = SHARED_SIZE;
                        lock.l_type = F_WRLCK;
-                       rc = osFcntl(pFile->h, F_SETLK, &lock);
+                       rc = fcntl(pFile->h, F_SETLK, &lock);
                        if (rc < 0)
                                return rc;
                        pInode->bProcessLock = 1;
@@ -1193,235 +601,8 @@ unixFileLock(unixFile * pFile, struct flock *pLock)
                        rc = 0;
                }
        } else {
-               rc = osFcntl(pFile->h, F_SETLK, pLock);
-       }
-       return rc;
-}
-
-/*
- * Lock the file with the lock specified by parameter eFileLock - one
- * of the following:
- *
- *     (1) SHARED_LOCK
- *     (2) RESERVED_LOCK
- *     (3) PENDING_LOCK
- *     (4) EXCLUSIVE_LOCK
- *
- * Sometimes when requesting one lock state, additional lock states
- * are inserted in between.  The locking might fail on one of the later
- * transitions leaving the lock state different from what it started but
- * still short of its goal.  The following chart shows the allowed
- * transitions and the inserted intermediate states:
- *
- *    UNLOCKED -> SHARED
- *    SHARED -> RESERVED
- *    SHARED -> (PENDING) -> EXCLUSIVE
- *    RESERVED -> (PENDING) -> EXCLUSIVE
- *    PENDING -> EXCLUSIVE
- *
- * This routine will only increase a lock.  Use the sqlite3OsUnlock()
- * routine to lower a locking level.
- */
-static int
-unixLock(sqlite3_file * id, int eFileLock)
-{
-       /* The following describes the implementation of the various locks and
-        * lock transitions in terms of the POSIX advisory shared and exclusive
-        * lock primitives (called read-locks and write-locks below, to avoid
-        * confusion with SQLite lock names).
-        *
-        * Symbols defined in os.h indentify the 'pending byte' and the 
'reserved
-        * byte', each single bytes at well known offsets, and the 'shared byte
-        * range', a range of 510 bytes at a well known offset.
-        *
-        * To obtain a SHARED lock, a read-lock is obtained on the 'pending
-        * byte'.  If this is successful, 'shared byte range' is read-locked
-        * and the lock on the 'pending byte' released.
-        *
-        * A process may only obtain a RESERVED lock after it has a SHARED lock.
-        * A RESERVED lock is implemented by grabbing a write-lock on the
-        * 'reserved byte'.
-        *
-        * A process may only obtain a PENDING lock after it has obtained a
-        * SHARED lock. A PENDING lock is implemented by obtaining a write-lock
-        * on the 'pending byte'. This ensures that no new SHARED locks can be
-        * obtained, but existing SHARED locks are allowed to persist. A process
-        * does not have to obtain a RESERVED lock on the way to a PENDING lock.
-        * This property is used by the algorithm for rolling back a journal 
file
-        * after a crash.
-        *
-        * An EXCLUSIVE lock, obtained after a PENDING lock is held, is
-        * implemented by obtaining a write-lock on the entire 'shared byte
-        * range'. Since all other locks require a read-lock on one of the bytes
-        * within this range, this ensures that no other locks are held on the
-        * database.
-        */
-       int rc = SQLITE_OK;
-       unixFile *pFile = (unixFile *) id;
-       unixInodeInfo *pInode;
-       struct flock lock;
-       int tErrno = 0;
-
-       assert(pFile);
-
-       /* If there is already a lock of this type or more restrictive on the
-        * unixFile, do nothing.
-        */
-       if (pFile->eFileLock >= eFileLock)
-               return SQLITE_OK;
-
-       /* Make sure the locking sequence is correct.
-        *  (1) We never move from unlocked to anything higher than shared lock.
-        *  (2) SQLite never explicitly requests a pendig lock.
-        *  (3) A shared lock is always held when a reserve lock is requested.
-        */
-       assert(pFile->eFileLock != NO_LOCK || eFileLock == SHARED_LOCK);
-       assert(eFileLock != PENDING_LOCK);
-       assert(eFileLock != RESERVED_LOCK || pFile->eFileLock == SHARED_LOCK);
-
-       pInode = pFile->pInode;
-
-       /* If some thread using this PID has a lock via a different unixFile*
-        * handle that precludes the requested lock, return BUSY.
-        */
-       if ((pFile->eFileLock != pInode->eFileLock &&
-            (pInode->eFileLock >= PENDING_LOCK || eFileLock > SHARED_LOCK))
-           ) {
-               rc = SQLITE_BUSY;
-               goto end_lock;
-       }
-
-       /* If a SHARED lock is requested, and some thread using this PID already
-        * has a SHARED or RESERVED lock, then increment reference counts and
-        * return SQLITE_OK.
-        */
-       if (eFileLock == SHARED_LOCK &&
-           (pInode->eFileLock == SHARED_LOCK
-            || pInode->eFileLock == RESERVED_LOCK)) {
-               assert(eFileLock == SHARED_LOCK);
-               assert(pFile->eFileLock == 0);
-               assert(pInode->nShared > 0);
-               pFile->eFileLock = SHARED_LOCK;
-               pInode->nShared++;
-               pInode->nLock++;
-               goto end_lock;
-       }
-
-       /* A PENDING lock is needed before acquiring a SHARED lock and before
-        * acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
-        * be released.
-        */
-       lock.l_len = 1L;
-       lock.l_whence = SEEK_SET;
-       if (eFileLock == SHARED_LOCK
-           || (eFileLock == EXCLUSIVE_LOCK && pFile->eFileLock < PENDING_LOCK)
-           ) {
-               lock.l_type = (eFileLock == SHARED_LOCK ? F_RDLCK : F_WRLCK);
-               lock.l_start = PENDING_BYTE;
-               if (unixFileLock(pFile, &lock)) {
-                       tErrno = errno;
-                       rc = sqliteErrorFromPosixError(tErrno,
-                                                      SQLITE_IOERR_LOCK);
-                       if (rc != SQLITE_BUSY) {
-                               storeLastErrno(pFile, tErrno);
-                       }
-                       goto end_lock;
-               }
-       }
-
-       /* If control gets to this point, then actually go ahead and make
-        * operating system calls for the specified lock.
-        */
-       if (eFileLock == SHARED_LOCK) {
-               assert(pInode->nShared == 0);
-               assert(pInode->eFileLock == 0);
-               assert(rc == SQLITE_OK);
-
-               /* Now get the read-lock */
-               lock.l_start = SHARED_FIRST;
-               lock.l_len = SHARED_SIZE;
-               if (unixFileLock(pFile, &lock)) {
-                       tErrno = errno;
-                       rc = sqliteErrorFromPosixError(tErrno,
-                                                      SQLITE_IOERR_LOCK);
-               }
-
-               /* Drop the temporary PENDING lock */
-               lock.l_start = PENDING_BYTE;
-               lock.l_len = 1L;
-               lock.l_type = F_UNLCK;
-               if (unixFileLock(pFile, &lock) && rc == SQLITE_OK) {
-                       /* This could happen with a network mount */
-                       tErrno = errno;
-                       rc = SQLITE_IOERR_UNLOCK;
-               }
-
-               if (rc) {
-                       if (rc != SQLITE_BUSY) {
-                               storeLastErrno(pFile, tErrno);
-                       }
-                       goto end_lock;
-               } else {
-                       pFile->eFileLock = SHARED_LOCK;
-                       pInode->nLock++;
-                       pInode->nShared = 1;
-               }
-       } else if (eFileLock == EXCLUSIVE_LOCK && pInode->nShared > 1) {
-               /* We are trying for an exclusive lock but another thread in 
this
-                * same process is still holding a shared lock.
-                */
-               rc = SQLITE_BUSY;
-       } else {
-               /* The request was for a RESERVED or EXCLUSIVE lock.  It is
-                * assumed that there is a SHARED or greater lock on the file
-                * already.
-                */
-               assert(0 != pFile->eFileLock);
-               lock.l_type = F_WRLCK;
-
-               assert(eFileLock == RESERVED_LOCK
-                      || eFileLock == EXCLUSIVE_LOCK);
-               if (eFileLock == RESERVED_LOCK) {
-                       lock.l_start = RESERVED_BYTE;
-                       lock.l_len = 1L;
-               } else {
-                       lock.l_start = SHARED_FIRST;
-                       lock.l_len = SHARED_SIZE;
-               }
-
-               if (unixFileLock(pFile, &lock)) {
-                       tErrno = errno;
-                       rc = sqliteErrorFromPosixError(tErrno,
-                                                      SQLITE_IOERR_LOCK);
-                       if (rc != SQLITE_BUSY) {
-                               storeLastErrno(pFile, tErrno);
-                       }
-               }
-       }
-
-#ifdef SQLITE_DEBUG
-       /* Set up the transaction-counter change checking flags when
-        * transitioning from a SHARED to a RESERVED lock.  The change
-        * from SHARED to RESERVED marks the beginning of a normal
-        * write operation.
-        */
-       if (rc == SQLITE_OK
-           && pFile->eFileLock <= SHARED_LOCK && eFileLock == RESERVED_LOCK) {
-               pFile->transCntrChng = 0;
-               pFile->dbUpdate = 0;
-               pFile->inNormalWrite = 1;
+               rc = fcntl(pFile->h, F_SETLK, pLock);
        }
-#endif
-
-       if (rc == SQLITE_OK) {
-               pFile->eFileLock = eFileLock;
-               pInode->eFileLock = eFileLock;
-       } else if (eFileLock == EXCLUSIVE_LOCK) {
-               pFile->eFileLock = PENDING_LOCK;
-               pInode->eFileLock = PENDING_LOCK;
-       }
-
- end_lock:
        return rc;
 }
 
@@ -1472,18 +653,6 @@ posixUnlock(sqlite3_file * id, int eFileLock, int 
handleNFSUnlock)
        if (pFile->eFileLock > SHARED_LOCK) {
                assert(pInode->eFileLock == pFile->eFileLock);
 
-#ifdef SQLITE_DEBUG
-               /* When reducing a lock such that other processes can start
-                * reading the database file again, make sure that the
-                * transaction counter was updated if any part of the database
-                * file changed.  If the transaction counter is not updated,
-                * other connections to the same file might not realize that
-                * the file has changed and hence might not know to flush their
-                * cache.  The use of a stale cache can lead to database 
corruption.
-                */
-               pFile->inNormalWrite = 0;
-#endif
-
                /* downgrading to a shared lock on NFS involves clearing the 
write lock
                 * before establishing the readlock - to avoid a race condition 
we downgrade
                 * the lock in 2 blocks, so that part of the range will be 
covered by a
@@ -1494,50 +663,8 @@ posixUnlock(sqlite3_file * id, int eFileLock, int 
handleNFSUnlock)
                 *  4:   [RRRR.]
                 */
                if (eFileLock == SHARED_LOCK) {
-#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
                        (void)handleNFSUnlock;
                        assert(handleNFSUnlock == 0);
-#endif
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-                       if (handleNFSUnlock) {
-                               int tErrno;     /* Error code from system call 
errors */
-                               off_t divSize = SHARED_SIZE - 1;
-
-                               lock.l_type = F_UNLCK;
-                               lock.l_whence = SEEK_SET;
-                               lock.l_start = SHARED_FIRST;
-                               lock.l_len = divSize;
-                               if (unixFileLock(pFile, &lock) == (-1)) {
-                                       tErrno = errno;
-                                       rc = SQLITE_IOERR_UNLOCK;
-                                       storeLastErrno(pFile, tErrno);
-                                       goto end_unlock;
-                               }
-                               lock.l_type = F_RDLCK;
-                               lock.l_whence = SEEK_SET;
-                               lock.l_start = SHARED_FIRST;
-                               lock.l_len = divSize;
-                               if (unixFileLock(pFile, &lock) == (-1)) {
-                                       tErrno = errno;
-                                       rc = sqliteErrorFromPosixError(tErrno,
-                                                                      
SQLITE_IOERR_RDLOCK);
-                                       if (IS_LOCK_ERROR(rc)) {
-                                               storeLastErrno(pFile, tErrno);
-                                       }
-                                       goto end_unlock;
-                               }
-                               lock.l_type = F_UNLCK;
-                               lock.l_whence = SEEK_SET;
-                               lock.l_start = SHARED_FIRST + divSize;
-                               lock.l_len = SHARED_SIZE - divSize;
-                               if (unixFileLock(pFile, &lock) == (-1)) {
-                                       tErrno = errno;
-                                       rc = SQLITE_IOERR_UNLOCK;
-                                       storeLastErrno(pFile, tErrno);
-                                       goto end_unlock;
-                               }
-                       } else
-#endif                         /* defined(__APPLE__) && 
SQLITE_ENABLE_LOCKING_STYLE */
                        {
                                lock.l_type = F_RDLCK;
                                lock.l_whence = SEEK_SET;
@@ -1617,16 +744,12 @@ posixUnlock(sqlite3_file * id, int eFileLock, int 
handleNFSUnlock)
 static int
 unixUnlock(sqlite3_file * id, int eFileLock)
 {
-#if SQLITE_MAX_MMAP_SIZE>0
        assert(eFileLock == SHARED_LOCK || ((unixFile *) id)->nFetchOut == 0);
-#endif
        return posixUnlock(id, eFileLock, 0);
 }
 
-#if SQLITE_MAX_MMAP_SIZE>0
 static int unixMapfile(unixFile * pFd, i64 nByte);
 static void unixUnmapfile(unixFile * pFd);
-#endif
 
 /*
  * This function performs the parts of the "close file" operation
@@ -1645,13 +768,6 @@ closeUnixFile(sqlite3_file * id)
                robust_close(pFile, pFile->h, __LINE__);
                pFile->h = -1;
        }
-#ifdef SQLITE_UNLINK_AFTER_CLOSE
-       if (pFile->ctrlFlags & UNIXFILE_DELETE) {
-               osUnlink(pFile->zPath);
-               sqlite3_free(*(char **)&pFile->zPath);
-               pFile->zPath = 0;
-       }
-#endif
        OpenCounter(-1);
        sqlite3_free(pFile->pUnused);
        memset(pFile, 0, sizeof(unixFile));
@@ -1689,45 +805,6 @@ unixClose(sqlite3_file * id)
 /************** End of the posix advisory lock implementation *****************
  *****************************************************************************/
 
-/******************************************************************************
- ***************************** No-op Locking **********************************
- *
- * Of the various locking implementations available, this is by far the
- * simplest:  locking is ignored.  No attempt is made to lock the database
- * file for reading or writing.
- *
- * This locking mode is appropriate for use on read-only databases
- * (ex: databases that are burned into CD-ROM, for example.)  It can
- * also be used if the application employs some external mechanism to
- * prevent simultaneous access of the same database by two or more
- * database connections.  But there is a serious risk of database
- * corruption if this locking mode is used in situations where multiple
- * database connections are accessing the same database file at the same
- * time and one or more of those connections are writing.
- */
-
-static int
-nolockCheckReservedLock(sqlite3_file * NotUsed, int *pResOut)
-{
-       UNUSED_PARAMETER(NotUsed);
-       *pResOut = 0;
-       return SQLITE_OK;
-}
-
-static int
-nolockLock(sqlite3_file * NotUsed, int NotUsed2)
-{
-       UNUSED_PARAMETER2(NotUsed, NotUsed2);
-       return SQLITE_OK;
-}
-
-static int
-nolockUnlock(sqlite3_file * NotUsed, int NotUsed2)
-{
-       UNUSED_PARAMETER2(NotUsed, NotUsed2);
-       return SQLITE_OK;
-}
-
 /*
  * Close the file.
  */
@@ -1737,4396 +814,1330 @@ nolockClose(sqlite3_file * id)
        return closeUnixFile(id);
 }
 
-/******************* End of the no-op lock implementation *********************
+
+/******************* End of the non-op lock implementation *******************
  *****************************************************************************/
 
 /******************************************************************************
- ************************ Begin dot-file Locking ******************************
- *
- * The dotfile locking implementation uses the existence of separate lock
- * files (really a directory) to control access to the database.  This works
- * on just about every filesystem imaginable.  But there are serious downsides:
- *
- *    (1)  There is zero concurrency.  A single reader blocks all other
- *         connections from reading or writing the database.
- *
- *    (2)  An application crash or power loss can leave stale lock files
- *         sitting around that need to be cleared manually.
- *
- * Nevertheless, a dotlock is an appropriate locking mode for use if no
- * other locking strategy is available.
- *
- * Dotfile locking works by creating a subdirectory in the same directory as
- * the database and with the same name but with a ".lock" extension added.
- * The existence of a lock directory implies an EXCLUSIVE lock.  All other
- * lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
- */
-
-/*
- * The file suffix added to the data base filename in order to create the
- * lock directory.
- */
-#define DOTLOCK_SUFFIX ".lock"
-
-/*
- * This routine checks if there is a RESERVED lock held on the specified
- * file by this or any other process. If such a lock is held, set *pResOut
- * to a non-zero value otherwise *pResOut is set to zero.  The return value
- * is set to SQLITE_OK unless an I/O error occurs during lock checking.
+ *************** Non-locking sqlite3_file methods *****************************
  *
- * In dotfile locking, either a lock exists or it does not.  So in this
- * variation of CheckReservedLock(), *pResOut is set to true if any lock
- * is held on the file and false if the file is unlocked.
+ * The next division contains implementations for all methods of the
+ * sqlite3_file object other than the locking methods.  The locking
+ * methods were defined in divisions above (one locking method per
+ * division).  Those methods that are common to all locking modes
+ * are gather together into this division.
  */
-static int
-dotlockCheckReservedLock(sqlite3_file * id, int *pResOut)
-{
-       int rc = SQLITE_OK;
-       int reserved = 0;
-       unixFile *pFile = (unixFile *) id;
-
-       SimulateIOError(return SQLITE_IOERR_CHECKRESERVEDLOCK;
-           );
-
-       assert(pFile);
-       reserved = osAccess((const char *)pFile->lockingContext, 0) == 0;
-       *pResOut = reserved;
-       return rc;
-}
 
 /*
- * Lock the file with the lock specified by parameter eFileLock - one
- * of the following:
- *
- *     (1) SHARED_LOCK
- *     (2) RESERVED_LOCK
- *     (3) PENDING_LOCK
- *     (4) EXCLUSIVE_LOCK
- *
- * Sometimes when requesting one lock state, additional lock states
- * are inserted in between.  The locking might fail on one of the later
- * transitions leaving the lock state different from what it started but
- * still short of its goal.  The following chart shows the allowed
- * transitions and the inserted intermediate states:
- *
- *    UNLOCKED -> SHARED
- *    SHARED -> RESERVED
- *    SHARED -> (PENDING) -> EXCLUSIVE
- *    RESERVED -> (PENDING) -> EXCLUSIVE
- *    PENDING -> EXCLUSIVE
+ * Seek to the offset passed as the second argument, then read cnt
+ * bytes into pBuf. Return the number of bytes actually read.
  *
- * This routine will only increase a lock.  Use the sqlite3OsUnlock()
- * routine to lower a locking level.
+ * NB:  If you define USE_PREAD or USE_PREAD64, then it might also
+ * be necessary to define _XOPEN_SOURCE to be 500.  This varies from
+ * one system to another.  Since SQLite does not define USE_PREAD
+ * in any form by default, we will not attempt to define _XOPEN_SOURCE.
+ * See tickets #2741 and #2681.
  *
- * With dotfile locking, we really only support state (4): EXCLUSIVE.
- * But we track the other locking levels internally.
+ * To avoid stomping the errno value on a failed read the lastErrno value
+ * is set before returning.
  */
 static int
-dotlockLock(sqlite3_file * id, int eFileLock)
+seekAndRead(unixFile * id, sqlite3_int64 offset, void *pBuf, int cnt)
 {
-       unixFile *pFile = (unixFile *) id;
-       char *zLockFile = (char *)pFile->lockingContext;
-       int rc;
-
-       /* If we have any lock, then the lock file already exists.  All we have
-        * to do is adjust our internal record of the lock level.
-        */
-       if (pFile->eFileLock > NO_LOCK) {
-               pFile->eFileLock = eFileLock;
-               /* Always update the timestamp on the old file */
-#ifdef HAVE_UTIME
-               utime(zLockFile, NULL);
-#else
-               utimes(zLockFile, NULL);
-#endif
-               return SQLITE_OK;
-       }
+       int got;
+       int prior = 0;
+       i64 newOffset;
 
-       /* grab an exclusive lock */
-       rc = osMkdir(zLockFile, 0777);
-       if (rc < 0) {
-               /* failed to open/create the lock directory */
-               int tErrno = errno;
-               if (EEXIST == tErrno) {
-                       rc = SQLITE_BUSY;
-               } else {
-                       rc = sqliteErrorFromPosixError(tErrno,
-                                                      SQLITE_IOERR_LOCK);
-                       if (rc != SQLITE_BUSY) {
-                               storeLastErrno(pFile, tErrno);
+       assert(cnt == (cnt & 0x1ffff));
+       assert(id->h > 2);
+       do {
+               newOffset = lseek(id->h, offset, SEEK_SET);
+               SimulateIOError(newOffset = -1);
+               if (newOffset < 0) {
+                       storeLastErrno((unixFile *) id, errno);
+                       return -1;
+               }
+               got = read(id->h, pBuf, cnt);
+               if (got == cnt)
+                       break;
+               if (got < 0) {
+                       if (errno == EINTR) {
+                               got = 1;
+                               continue;
                        }
+                       prior = 0;
+                       storeLastErrno((unixFile *) id, errno);
+                       break;
+               } else if (got > 0) {
+                       cnt -= got;
+                       offset += got;
+                       prior += got;
+                       pBuf = (void *)(got + (char *)pBuf);
                }
-               return rc;
-       }
-
-       /* got it, set the type and return ok */
-       pFile->eFileLock = eFileLock;
-       return rc;
+       } while (got > 0);
+       return got + prior;
 }
 
 /*
- * Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
- * must be either NO_LOCK or SHARED_LOCK.
- *
- * If the locking level of the file descriptor is already at or below
- * the requested locking level, this routine is a no-op.
- *
- * When the locking level reaches NO_LOCK, delete the lock file.
+ * Read data from a file into a buffer.  Return SQLITE_OK if all
+ * bytes were read successfully and SQLITE_IOERR if anything goes
+ * wrong.
  */
 static int
-dotlockUnlock(sqlite3_file * id, int eFileLock)
+unixRead(sqlite3_file * id, void *pBuf, int amt, sqlite3_int64 offset)
 {
        unixFile *pFile = (unixFile *) id;
-       char *zLockFile = (char *)pFile->lockingContext;
-       int rc;
-
-       assert(pFile);
-       assert(eFileLock <= SHARED_LOCK);
-
-       /* no-op if possible */
-       if (pFile->eFileLock == eFileLock) {
-               return SQLITE_OK;
-       }
+       int got;
+       assert(id);
+       assert(offset >= 0);
+       assert(amt > 0);
 
-       /* To downgrade to shared, simply update our internal notion of the
-        * lock state.  No need to mess with the file on disk.
+#if SQLITE_MAX_MMAP_SIZE>0
+       /* Deal with as much of this read request as possible by transfering
+        * data from the memory mapping using memcpy().
         */
-       if (eFileLock == SHARED_LOCK) {
-               pFile->eFileLock = SHARED_LOCK;
-               return SQLITE_OK;
-       }
-
-       /* To fully unlock the database, delete the lock file */
-       assert(eFileLock == NO_LOCK);
-       rc = osRmdir(zLockFile);
-       if (rc < 0) {
-               int tErrno = errno;
-               if (tErrno == ENOENT) {
-                       rc = SQLITE_OK;
+       if (offset < pFile->mmapSize) {
+               if (offset + amt <= pFile->mmapSize) {
+                       memcpy(pBuf, &((u8 *) (pFile->pMapRegion))[offset],
+                              amt);
+                       return SQLITE_OK;
                } else {
-                       rc = SQLITE_IOERR_UNLOCK;
-                       storeLastErrno(pFile, tErrno);
+                       int nCopy = pFile->mmapSize - offset;
+                       memcpy(pBuf, &((u8 *) (pFile->pMapRegion))[offset],
+                              nCopy);
+                       pBuf = &((u8 *) pBuf)[nCopy];
+                       amt -= nCopy;
+                       offset += nCopy;
                }
-               return rc;
        }
-       pFile->eFileLock = NO_LOCK;
-       return SQLITE_OK;
+#endif
+
+       got = seekAndRead(pFile, offset, pBuf, amt);
+       if (got == amt) {
+               return SQLITE_OK;
+       } else if (got < 0) {
+               /* lastErrno set by seekAndRead */
+               return SQLITE_IOERR_READ;
+       } else {
+               storeLastErrno(pFile, 0);       /* not a system error */
+               /* Unread parts of the buffer must be zero-filled */
+               memset(&((char *)pBuf)[got], 0, amt - got);
+               return SQLITE_IOERR_SHORT_READ;
+       }
 }
 
 /*
- * Close a file.  Make sure the lock has been released before closing.
+ * Attempt to seek the file-descriptor passed as the first argument to
+ * absolute offset iOff, then attempt to write nBuf bytes of data from
+ * pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
+ * return the actual number of bytes written (which may be less than
+ * nBuf).
  */
 static int
-dotlockClose(sqlite3_file * id)
+seekAndWriteFd(int fd,         /* File descriptor to write to */
+              i64 iOff,        /* File offset to begin writing at */
+              const void *pBuf,        /* Copy data from this buffer to the 
file */
+              int nBuf,        /* Size of buffer pBuf in bytes */
+              int *piErrno     /* OUT: Error number if error occurs */
+    )
 {
-       unixFile *pFile = (unixFile *) id;
-       assert(id != 0);
-       dotlockUnlock(id, NO_LOCK);
-       sqlite3_free(pFile->lockingContext);
-       return closeUnixFile(id);
-}
+       int rc = 0;             /* Value returned by system call */
 
-/****************** End of the dot-file lock implementation *******************
- *****************************************************************************/
+       assert(nBuf == (nBuf & 0x1ffff));
+       assert(fd > 2);
+       assert(piErrno != 0);
+       nBuf &= 0x1ffff;
+       do {
+               i64 iSeek = lseek(fd, iOff, SEEK_SET);
+               SimulateIOError(iSeek = -1);
+               if (iSeek < 0) {
+                       rc = -1;
+                       break;
+               }
+               rc = write(fd, pBuf, nBuf);
+       } while (rc < 0 && errno == EINTR);
 
-/******************************************************************************
- ************************* Begin flock Locking ********************************
- *
- * Use the flock() system call to do file locking.
- *
- * flock() locking is like dot-file locking in that the various
- * fine-grain locking levels supported by SQLite are collapsed into
- * a single exclusive lock.  In other words, SHARED, RESERVED, and
- * PENDING locks are the same thing as an EXCLUSIVE lock.  SQLite
- * still works when you do this, but concurrency is reduced since
- * only a single process can be reading the database at a time.
- *
- * Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off
- */
-#if SQLITE_ENABLE_LOCKING_STYLE
+       if (rc < 0)
+               *piErrno = errno;
+       return rc;
+}
 
 /*
- * Retry flock() calls that fail with EINTR
+ * Seek to the offset in id->offset then read cnt bytes into pBuf.
+ * Return the number of bytes actually read.  Update the offset.
+ *
+ * To avoid stomping the errno value on a failed write the lastErrno value
+ * is set before returning.
  */
-#ifdef EINTR
 static int
-robust_flock(int fd, int op)
+seekAndWrite(unixFile * id, i64 offset, const void *pBuf, int cnt)
 {
-       int rc;
-       do {
-               rc = flock(fd, op);
-       } while (rc < 0 && errno == EINTR);
-       return rc;
+       return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
 }
-#else
-#define robust_flock(a,b) flock(a,b)
-#endif
 
 /*
- * This routine checks if there is a RESERVED lock held on the specified
- * file by this or any other process. If such a lock is held, set *pResOut
- * to a non-zero value otherwise *pResOut is set to zero.  The return value
- * is set to SQLITE_OK unless an I/O error occurs during lock checking.
+ * Write data from a buffer into a file.  Return SQLITE_OK on success
+ * or some other error code on failure.
  */
 static int
-flockCheckReservedLock(sqlite3_file * id, int *pResOut)
+unixWrite(sqlite3_file * id, const void *pBuf, int amt, sqlite3_int64 offset)
 {
-       int rc = SQLITE_OK;
-       int reserved = 0;
        unixFile *pFile = (unixFile *) id;
+       int wrote = 0;
+       assert(id);
+       assert(amt > 0);
 
-       SimulateIOError(return SQLITE_IOERR_CHECKRESERVEDLOCK;
-           );
-
-       assert(pFile);
-
-       /* Check if a thread in this process holds such a lock */
-       if (pFile->eFileLock > SHARED_LOCK) {
-               reserved = 1;
+       while ((wrote = seekAndWrite(pFile, offset, pBuf, amt)) < amt
+              && wrote > 0) {
+               amt -= wrote;
+               offset += wrote;
+               pBuf = &((char *)pBuf)[wrote];
        }
+       SimulateIOError((wrote = (-1), amt = 1));
+       SimulateDiskfullError((wrote = 0, amt = 1));
 
-       /* Otherwise see if some other process holds it. */
-       if (!reserved) {
-               /* attempt to get the lock */
-               int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
-               if (!lrc) {
-                       /* got the lock, unlock it */
-                       lrc = robust_flock(pFile->h, LOCK_UN);
-                       if (lrc) {
-                               int tErrno = errno;
-                               /* unlock failed with an error */
-                               lrc = SQLITE_IOERR_UNLOCK;
-                               storeLastErrno(pFile, tErrno);
-                               rc = lrc;
-                       }
+       if (amt > wrote) {
+               if (wrote < 0 && pFile->lastErrno != ENOSPC) {
+                       /* lastErrno set by seekAndWrite */
+                       return SQLITE_IOERR_WRITE;
                } else {
-                       int tErrno = errno;
-                       reserved = 1;
-                       /* someone else might have it reserved */
-                       lrc =
-                           sqliteErrorFromPosixError(tErrno,
-                                                     SQLITE_IOERR_LOCK);
-                       if (IS_LOCK_ERROR(lrc)) {
-                               storeLastErrno(pFile, tErrno);
-                               rc = lrc;
-                       }
+                       storeLastErrno(pFile, 0);       /* not a system error */
+                       return SQLITE_FULL;
                }
        }
 
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-       if ((rc & SQLITE_IOERR) == SQLITE_IOERR) {
-               rc = SQLITE_OK;
-               reserved = 1;
-       }
-#endif                         /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-       *pResOut = reserved;
-       return rc;
+       return SQLITE_OK;
 }
 
+#ifdef SQLITE_TEST
 /*
- * Lock the file with the lock specified by parameter eFileLock - one
- * of the following:
- *
- *     (1) SHARED_LOCK
- *     (2) RESERVED_LOCK
- *     (3) PENDING_LOCK
- *     (4) EXCLUSIVE_LOCK
- *
- * Sometimes when requesting one lock state, additional lock states
- * are inserted in between.  The locking might fail on one of the later
- * transitions leaving the lock state different from what it started but
- * still short of its goal.  The following chart shows the allowed
- * transitions and the inserted intermediate states:
- *
- *    UNLOCKED -> SHARED
- *    SHARED -> RESERVED
- *    SHARED -> (PENDING) -> EXCLUSIVE
- *    RESERVED -> (PENDING) -> EXCLUSIVE
- *    PENDING -> EXCLUSIVE
- *
- * flock() only really support EXCLUSIVE locks.  We track intermediate
- * lock states in the sqlite3_file structure, but all locks SHARED or
- * above are really EXCLUSIVE locks and exclude all other processes from
- * access the file.
- *
- * This routine will only increase a lock.  Use the sqlite3OsUnlock()
- * routine to lower a locking level.
+ * Count the number of fullsyncs and normal syncs.  This is used to test
+ * that syncs and fullsyncs are occurring at the right times.
  */
-static int
-flockLock(sqlite3_file * id, int eFileLock)
-{
-       int rc = SQLITE_OK;
-       unixFile *pFile = (unixFile *) id;
-
-       assert(pFile);
-
-       /* if we already have a lock, it is exclusive.
-        * Just adjust level and punt on outta here.
-        */
-       if (pFile->eFileLock > NO_LOCK) {
-               pFile->eFileLock = eFileLock;
-               return SQLITE_OK;
-       }
-
-       /* grab an exclusive lock */
-
-       if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
-               int tErrno = errno;
-               /* didn't get, must be busy */
-               rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
-               if (IS_LOCK_ERROR(rc)) {
-                       storeLastErrno(pFile, tErrno);
-               }
-       } else {
-               /* got it, set the type and return ok */
-               pFile->eFileLock = eFileLock;
-       }
+int sqlite3_sync_count = 0;
+int sqlite3_fullsync_count = 0;
+#endif
 
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-       if ((rc & SQLITE_IOERR) == SQLITE_IOERR) {
-               rc = SQLITE_BUSY;
-       }
-#endif                         /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-       return rc;
-}
 
 /*
- * Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
- * must be either NO_LOCK or SHARED_LOCK.
+ * The fsync() system call does not work as advertised on many
+ * unix systems.  The following procedure is an attempt to make
+ * it work better.
  *
- * If the locking level of the file descriptor is already at or below
- * the requested locking level, this routine is a no-op.
+ * The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful
+ * for testing when we want to run through the test suite quickly.
+ * You are strongly advised *not* to deploy with SQLITE_NO_SYNC
+ * enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
+ * or power failure will likely corrupt the database file.
+ *
+ * SQLite sets the dataOnly flag if the size of the file is unchanged.
+ * The idea behind dataOnly is that it should only write the file content
+ * to disk, not the inode.  We only set dataOnly if the file size is
+ * unchanged since the file size is part of the inode.  However,
+ * Ted Ts'o tells us that fdatasync() will also write the inode if the
+ * file size has changed.  The only real difference between fdatasync()
+ * and fsync(), Ted tells us, is that fdatasync() will not flush the
+ * inode if the mtime or owner or other inode attributes have changed.
+ * We only care about the file size, not the other file attributes, so
+ * as far as SQLite is concerned, an fdatasync() is always adequate.
+ * So, we always use fdatasync() if it is available, regardless of
+ * the value of the dataOnly flag.
  */
 static int
-flockUnlock(sqlite3_file * id, int eFileLock)
+full_fsync(int fd, int fullSync, int dataOnly)
 {
-       unixFile *pFile = (unixFile *) id;
-
-       assert(pFile);
-       assert(eFileLock <= SHARED_LOCK);
-
-       /* no-op if possible */
-       if (pFile->eFileLock == eFileLock) {
-               return SQLITE_OK;
-       }
+       UNUSED_PARAMETER(fd);
+       UNUSED_PARAMETER(fullSync);
+       UNUSED_PARAMETER(dataOnly);
 
-       /* shared can just be set because we always have an exclusive */
-       if (eFileLock == SHARED_LOCK) {
-               pFile->eFileLock = eFileLock;
-               return SQLITE_OK;
-       }
+       /* Record the number of times that we do a normal fsync() and
+        * FULLSYNC.  This is used during testing to verify that this procedure
+        * gets called with the correct arguments.
+        */
+#ifdef SQLITE_TEST
+       if (fullSync)
+               sqlite3_fullsync_count++;
+       sqlite3_sync_count++;
+#endif
 
-       /* no, really, unlock. */
-       if (robust_flock(pFile->h, LOCK_UN)) {
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
-               return SQLITE_OK;
-#endif                         /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
-               return SQLITE_IOERR_UNLOCK;
-       } else {
-               pFile->eFileLock = NO_LOCK;
-               return SQLITE_OK;
-       }
+       struct stat buf;
+       return fstat(fd, &buf);
 }
 
 /*
- * Close a file.
- */
-static int
-flockClose(sqlite3_file * id)
-{
-       assert(id != 0);
-       flockUnlock(id, NO_LOCK);
-       return closeUnixFile(id);
-}
-
-#endif                         /* SQLITE_ENABLE_LOCKING_STYLE */
-
-/******************* End of the flock lock implementation *********************
- *****************************************************************************/
-
-
-/******************************************************************************
- ************************** Begin AFP Locking *********************************
+ * Open a file descriptor to the directory containing file zFilename.
+ * If successful, *pFd is set to the opened file descriptor and
+ * SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
+ * or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
+ * value.
  *
- * AFP is the Apple Filing Protocol.  AFP is a network filesystem found
- * on Apple Macintosh computers - both OS9 and OSX.
+ * The directory file descriptor is used for only one thing - to
+ * fsync() a directory to make sure file creation and deletion events
+ * are flushed to disk.  Such fsyncs are not needed on newer
+ * journaling filesystems, but are required on older filesystems.
  *
- * Third-party implementations of AFP are available.  But this code here
- * only works on OSX.
- */
-
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-/*
- * The afpLockingContext structure contains all afp lock specific state
- */
-typedef struct afpLockingContext afpLockingContext;
-struct afpLockingContext {
-       int reserved;
-       const char *dbPath;     /* Name of the open file */
-};
-
-struct ByteRangeLockPB2 {
-       unsigned long long offset;      /* offset to first byte to lock */
-       unsigned long long length;      /* nbr of bytes to lock */
-       unsigned long long retRangeStart;       /* nbr of 1st byte locked if 
successful */
-       unsigned char unLockFlag;       /* 1 = unlock, 0 = lock */
-       unsigned char startEndFlag;     /* 1=rel to end of fork, 0=rel to start 
*/
-       int fd;                 /* file desc to assoc this lock with */
-};
-
-#define afpfsByteRangeLock2FSCTL        _IOWR('z', 23, struct ByteRangeLockPB2)
-
-/*
- * This is a utility for setting or clearing a bit-range lock on an
- * AFP filesystem.
+ * This routine can be overridden using the xSetSysCall interface.
+ * The ability to override this routine was added in support of the
+ * chromium sandbox.  Opening a directory is a security risk (we are
+ * told) so making it overrideable allows the chromium sandbox to
+ * replace this routine with a harmless no-op.  To make this routine
+ * a no-op, replace it with a stub that returns SQLITE_OK but leaves
+ * *pFd set to a negative number.
  *
- * Return SQLITE_OK on success, SQLITE_BUSY on failure.
+ * If SQLITE_OK is returned, the caller is responsible for closing
+ * the file descriptor *pFd using close().
  */
 static int
-afpSetLock(const char *path,   /* Name of the file to be locked or unlocked */
-          unixFile * pFile,    /* Open file descriptor on path */
-          unsigned long long offset,   /* First byte to be locked */
-          unsigned long long length,   /* Number of bytes to lock */
-          int setLockFlag      /* True to set lock.  False to clear lock */
-    )
+openDirectory(const char *zFilename, int *pFd)
 {
-       struct ByteRangeLockPB2 pb;
-       int err;
-
-       pb.unLockFlag = setLockFlag ? 0 : 1;
-       pb.startEndFlag = 0;
-       pb.offset = offset;
-       pb.length = length;
-       pb.fd = pFile->h;
+       int ii;
+       int fd;
+       char zDirname[MAX_PATHNAME + 1];
 
-       err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
-       if (err == -1) {
-               int rc;
-               int tErrno = errno;
-
-#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
-               rc = SQLITE_BUSY;
-#else
-               rc = sqliteErrorFromPosixError(tErrno,
-                                              setLockFlag ? SQLITE_IOERR_LOCK :
-                                              SQLITE_IOERR_UNLOCK);
-#endif                         /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
-               if (IS_LOCK_ERROR(rc)) {
-                       storeLastErrno(pFile, tErrno);
-               }
-               return rc;
+       sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
+       for (ii = (int)strlen(zDirname); ii > 0 && zDirname[ii] != '/'; ii--) ;
+       if (ii > 0) {
+               zDirname[ii] = '\0';
        } else {
-               return SQLITE_OK;
+               if (zDirname[0] != '/')
+                       zDirname[0] = '.';
+               zDirname[1] = 0;
        }
-}
-
-/*
- * This routine checks if there is a RESERVED lock held on the specified
- * file by this or any other process. If such a lock is held, set *pResOut
- * to a non-zero value otherwise *pResOut is set to zero.  The return value
- * is set to SQLITE_OK unless an I/O error occurs during lock checking.
- */
-static int
-afpCheckReservedLock(sqlite3_file * id, int *pResOut)
-{
-       int rc = SQLITE_OK;
-       int reserved = 0;
-       unixFile *pFile = (unixFile *) id;
-       afpLockingContext *context;
-
-       SimulateIOError(return SQLITE_IOERR_CHECKRESERVEDLOCK;
-           );
+       fd = robust_open(zDirname, O_RDONLY | O_BINARY, 0);
 
-       assert(pFile);
-       context = (afpLockingContext *) pFile->lockingContext;
-       if (context->reserved) {
-               *pResOut = 1;
+       *pFd = fd;
+       if (fd >= 0)
                return SQLITE_OK;
-       }
-
-       /* Check if a thread in this process holds such a lock */
-       if (pFile->pInode->eFileLock > SHARED_LOCK) {
-               reserved = 1;
-       }
-
-       /* Otherwise see if some other process holds it.
-        */
-       if (!reserved) {
-               /* lock the RESERVED byte */
-               int lrc =
-                   afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 1);
-               if (SQLITE_OK == lrc) {
-                       /* if we succeeded in taking the reserved lock, unlock 
it to restore
-                        * the original state
-                        */
-                       lrc =
-                           afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,
-                                      0);
-               } else {
-                       /* if we failed to get the lock then someone else must 
have it */
-                       reserved = 1;
-               }
-               if (IS_LOCK_ERROR(lrc)) {
-                       rc = lrc;
-               }
-       }
-
-       *pResOut = reserved;
-       return rc;
+       return unixLogError(SQLITE_CANTOPEN_BKPT, "openDirectory", zDirname);
 }
 
 /*
- * Lock the file with the lock specified by parameter eFileLock - one
- * of the following:
- *
- *     (1) SHARED_LOCK
- *     (2) RESERVED_LOCK
- *     (3) PENDING_LOCK
- *     (4) EXCLUSIVE_LOCK
- *
- * Sometimes when requesting one lock state, additional lock states
- * are inserted in between.  The locking might fail on one of the later
- * transitions leaving the lock state different from what it started but
- * still short of its goal.  The following chart shows the allowed
- * transitions and the inserted intermediate states:
- *
- *    UNLOCKED -> SHARED
- *    SHARED -> RESERVED
- *    SHARED -> (PENDING) -> EXCLUSIVE
- *    RESERVED -> (PENDING) -> EXCLUSIVE
- *    PENDING -> EXCLUSIVE
- *
- * This routine will only increase a lock.  Use the sqlite3OsUnlock()
- * routine to lower a locking level.
+ * This function is called to handle the SQLITE_FCNTL_SIZE_HINT
+ * file-control operation.  Enlarge the database to nBytes in size
+ * (rounded up to the next chunk-size).  If the database is already
+ * nBytes or larger, this routine is a no-op.
  */
 static int
-afpLock(sqlite3_file * id, int eFileLock)
+fcntlSizeHint(unixFile * pFile, i64 nByte)
 {
-       int rc = SQLITE_OK;
-       unixFile *pFile = (unixFile *) id;
-       unixInodeInfo *pInode = pFile->pInode;
-       afpLockingContext *context =
-           (afpLockingContext *) pFile->lockingContext;
-
-       assert(pFile);
-
-       /* If there is already a lock of this type or more restrictive on the
-        * unixFile, do nothing.
-        */
-       if (pFile->eFileLock >= eFileLock) {
-               return SQLITE_OK;
-       }
-
-       /* Make sure the locking sequence is correct
-        *  (1) We never move from unlocked to anything higher than shared lock.
-        *  (2) SQLite never explicitly requests a pendig lock.
-        *  (3) A shared lock is always held when a reserve lock is requested.
-        */
-       assert(pFile->eFileLock != NO_LOCK || eFileLock == SHARED_LOCK);
-       assert(eFileLock != PENDING_LOCK);
-       assert(eFileLock != RESERVED_LOCK || pFile->eFileLock == SHARED_LOCK);
-
-       pInode = pFile->pInode;
-
-       /* If some thread using this PID has a lock via a different unixFile*
-        * handle that precludes the requested lock, return BUSY.
-        */
-       if ((pFile->eFileLock != pInode->eFileLock &&
-            (pInode->eFileLock >= PENDING_LOCK || eFileLock > SHARED_LOCK))
-           ) {
-               rc = SQLITE_BUSY;
-               goto afp_end_lock;
-       }
+       if (pFile->szChunk > 0) {
+               i64 nSize;      /* Required file size */
+               struct stat buf;        /* Used to hold return values of 
fstat() */
 
-       /* If a SHARED lock is requested, and some thread using this PID already
-        * has a SHARED or RESERVED lock, then increment reference counts and
-        * return SQLITE_OK.
-        */
-       if (eFileLock == SHARED_LOCK &&
-           (pInode->eFileLock == SHARED_LOCK
-            || pInode->eFileLock == RESERVED_LOCK)) {
-               assert(eFileLock == SHARED_LOCK);
-               assert(pFile->eFileLock == 0);
-               assert(pInode->nShared > 0);
-               pFile->eFileLock = SHARED_LOCK;
-               pInode->nShared++;
-               pInode->nLock++;
-               goto afp_end_lock;
-       }
+               if (fstat(pFile->h, &buf))
+                       return SQLITE_IOERR_FSTAT;
 
-       /* A PENDING lock is needed before acquiring a SHARED lock and before
-        * acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
-        * be released.
-        */
-       if (eFileLock == SHARED_LOCK
-           || (eFileLock == EXCLUSIVE_LOCK && pFile->eFileLock < PENDING_LOCK)
-           ) {
-               int failed;
-               failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
-               if (failed) {
-                       rc = failed;
-                       goto afp_end_lock;
-               }
-       }
+               nSize =
+                   ((nByte + pFile->szChunk -
+                     1) / pFile->szChunk) * pFile->szChunk;
+               if (nSize > (i64) buf.st_size) {
+                       int nBlk = buf.st_blksize;      /* File-system block 
size */
+                       int nWrite = 0; /* Number of bytes written by 
seekAndWrite */
+                       i64 iWrite;     /* Next offset to write to */
 
-       /* If control gets to this point, then actually go ahead and make
-        * operating system calls for the specified lock.
-        */
-       if (eFileLock == SHARED_LOCK) {
-               int lrc1, lrc2, lrc1Errno = 0;
-               long lk, mask;
-
-               assert(pInode->nShared == 0);
-               assert(pInode->eFileLock == 0);
-
-               mask = (sizeof(long) == 8) ? LARGEST_INT64 : 0x7fffffff;
-               /* Now get the read-lock SHARED_LOCK */
-               /* note that the quality of the randomness doesn't matter that 
much */
-               lk = random();
-               pInode->sharedByte = (lk & mask) % (SHARED_SIZE - 1);
-               lrc1 = afpSetLock(context->dbPath, pFile,
-                                 SHARED_FIRST + pInode->sharedByte, 1, 1);
-               if (IS_LOCK_ERROR(lrc1)) {
-                       lrc1Errno = pFile->lastErrno;
-               }
-               /* Drop the temporary PENDING lock */
-               lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
-
-               if (IS_LOCK_ERROR(lrc1)) {
-                       storeLastErrno(pFile, lrc1Errno);
-                       rc = lrc1;
-                       goto afp_end_lock;
-               } else if (IS_LOCK_ERROR(lrc2)) {
-                       rc = lrc2;
-                       goto afp_end_lock;
-               } else if (lrc1 != SQLITE_OK) {
-                       rc = lrc1;
-               } else {
-                       pFile->eFileLock = SHARED_LOCK;
-                       pInode->nLock++;
-                       pInode->nShared = 1;
-               }
-       } else if (eFileLock == EXCLUSIVE_LOCK && pInode->nShared > 1) {
-               /* We are trying for an exclusive lock but another thread in 
this
-                * same process is still holding a shared lock.
-                */
-               rc = SQLITE_BUSY;
-       } else {
-               /* The request was for a RESERVED or EXCLUSIVE lock.  It is
-                * assumed that there is a SHARED or greater lock on the file
-                * already.
-                */
-               int failed = 0;
-               assert(0 != pFile->eFileLock);
-               if (eFileLock >= RESERVED_LOCK
-                   && pFile->eFileLock < RESERVED_LOCK) {
-                       /* Acquire a RESERVED lock */
-                       failed =
-                           afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,
-                                      1);
-                       if (!failed) {
-                               context->reserved = 1;
+                       iWrite = (buf.st_size / nBlk) * nBlk + nBlk - 1;
+                       assert(iWrite >= buf.st_size);
+                       assert(((iWrite + 1) % nBlk) == 0);
+                       for ( /*no-op */ ; iWrite < nSize + nBlk - 1;
+                            iWrite += nBlk) {
+                               if (iWrite >= nSize)
+                                       iWrite = nSize - 1;
+                               nWrite = seekAndWrite(pFile, iWrite, "", 1);
+                               if (nWrite != 1)
+                                       return SQLITE_IOERR_WRITE;
                        }
                }
-               if (!failed && eFileLock == EXCLUSIVE_LOCK) {
-                       /* Acquire an EXCLUSIVE lock */
-
-                       /* Remove the shared lock before trying the range.  
we'll need to
-                        * reestablish the shared lock if we can't get the  
afpUnlock
-                        */
-                       if (!
-                           (failed =
-                            afpSetLock(context->dbPath, pFile,
-                                       SHARED_FIRST + pInode->sharedByte, 1,
-                                       0))) {
-                               int failed2 = SQLITE_OK;
-                               /* now attemmpt to get the exclusive lock range 
*/
-                               failed =
-                                   afpSetLock(context->dbPath, pFile,
-                                              SHARED_FIRST, SHARED_SIZE, 1);
-                               if (failed
-                                   && (failed2 =
-                                       afpSetLock(context->dbPath, pFile,
-                                                  SHARED_FIRST +
-                                                  pInode->sharedByte, 1, 1))) {
-                                       /* Can't reestablish the shared lock.  
Sqlite can't deal, this is
-                                        * a critical I/O error
-                                        */
-                                       rc = ((failed & SQLITE_IOERR) ==
-                                             SQLITE_IOERR) ? failed2 :
-                                           SQLITE_IOERR_LOCK;
-                                       goto afp_end_lock;
-                               }
-                       } else {
-                               rc = failed;
+       }
+       if (pFile->mmapSizeMax > 0 && nByte > pFile->mmapSize) {
+               int rc;
+               if (pFile->szChunk <= 0) {
+                       if (robust_ftruncate(pFile->h, nByte)) {
+                               storeLastErrno(pFile, errno);
+                               return unixLogError(SQLITE_IOERR_TRUNCATE,
+                                                   "ftruncate", pFile->zPath);
                        }
                }
-               if (failed) {
-                       rc = failed;
-               }
-       }
 
-       if (rc == SQLITE_OK) {
-               pFile->eFileLock = eFileLock;
-               pInode->eFileLock = eFileLock;
-       } else if (eFileLock == EXCLUSIVE_LOCK) {
-               pFile->eFileLock = PENDING_LOCK;
-               pInode->eFileLock = PENDING_LOCK;
+               rc = unixMapfile(pFile, nByte);
+               return rc;
        }
 
- afp_end_lock:
-       return rc;
+       return SQLITE_OK;
 }
 
+/* Forward declaration */
+static int unixGetTempname(int nBuf, char *zBuf);
+
 /*
- * Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
- * must be either NO_LOCK or SHARED_LOCK.
- *
- * If the locking level of the file descriptor is already at or below
- * the requested locking level, this routine is a no-op.
+ * Information and control of an open file handle.
  */
 static int
-afpUnlock(sqlite3_file * id, int eFileLock)
+unixFileControl(sqlite3_file * id, int op, void *pArg)
 {
-       int rc = SQLITE_OK;
        unixFile *pFile = (unixFile *) id;
-       unixInodeInfo *pInode;
-       afpLockingContext *context =
-           (afpLockingContext *) pFile->lockingContext;
-       int skipShared = 0;
-#ifdef SQLITE_TEST
-       int h = pFile->h;
-#endif
-
-       assert(pFile);
-
-       assert(eFileLock <= SHARED_LOCK);
-       if (pFile->eFileLock <= eFileLock) {
-               return SQLITE_OK;
-       }
-       pInode = pFile->pInode;
-       assert(pInode->nShared != 0);
-       if (pFile->eFileLock > SHARED_LOCK) {
-               assert(pInode->eFileLock == pFile->eFileLock);
-               SimulateIOErrorBenign(1);
-               SimulateIOError(h = (-1))
-                   SimulateIOErrorBenign(0);
-
-#ifdef SQLITE_DEBUG
-               /* When reducing a lock such that other processes can start
-                * reading the database file again, make sure that the
-                * transaction counter was updated if any part of the database
-                * file changed.  If the transaction counter is not updated,
-                * other connections to the same file might not realize that
-                * the file has changed and hence might not know to flush their
-                * cache.  The use of a stale cache can lead to database 
corruption.
-                */
-               assert(pFile->inNormalWrite == 0
-                      || pFile->dbUpdate == 0 || pFile->transCntrChng == 1);
-               pFile->inNormalWrite = 0;
-#endif
-
-               if (pFile->eFileLock == EXCLUSIVE_LOCK) {
-                       rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
-                                       SHARED_SIZE, 0);
-                       if (rc == SQLITE_OK
-                           && (eFileLock == SHARED_LOCK
-                               || pInode->nShared > 1)) {
-                               /* only re-establish the shared lock if 
necessary */
-                               int sharedLockByte =
-                                   SHARED_FIRST + pInode->sharedByte;
-                               rc = afpSetLock(context->dbPath, pFile,
-                                               sharedLockByte, 1, 1);
-                       } else {
-                               skipShared = 1;
-                       }
-               }
-               if (rc == SQLITE_OK && pFile->eFileLock >= PENDING_LOCK) {
-                       rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1,
-                                       0);
+       switch (op) {
+       case SQLITE_FCNTL_LOCKSTATE:{
+                       *(int *)pArg = pFile->eFileLock;
+                       return SQLITE_OK;
                }
-               if (rc == SQLITE_OK && pFile->eFileLock >= RESERVED_LOCK
-                   && context->reserved) {
-                       rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE,
-                                       1, 0);
-                       if (!rc) {
-                               context->reserved = 0;
-                       }
+       case SQLITE_FCNTL_LAST_ERRNO:{
+                       *(int *)pArg = pFile->lastErrno;
+                       return SQLITE_OK;
                }
-               if (rc == SQLITE_OK
-                   && (eFileLock == SHARED_LOCK || pInode->nShared > 1)) {
-                       pInode->eFileLock = SHARED_LOCK;
+       case SQLITE_FCNTL_CHUNK_SIZE:{
+                       pFile->szChunk = *(int *)pArg;
+                       return SQLITE_OK;
                }
-       }
-       if (rc == SQLITE_OK && eFileLock == NO_LOCK) {
-
-               /* Decrement the shared lock counter.  Release the lock using an
-                * OS call only when all threads in this same process have 
released
-                * the lock.
-                */
-               unsigned long long sharedLockByte =
-                   SHARED_FIRST + pInode->sharedByte;
-               pInode->nShared--;
-               if (pInode->nShared == 0) {
+       case SQLITE_FCNTL_SIZE_HINT:{
+                       int rc;
                        SimulateIOErrorBenign(1);
-                       SimulateIOError(h = (-1))
-                           SimulateIOErrorBenign(0);
-                       if (!skipShared) {
-                               rc = afpSetLock(context->dbPath, pFile,
-                                               sharedLockByte, 1, 0);
-                       }
-                       if (!rc) {
-                               pInode->eFileLock = NO_LOCK;
-                               pFile->eFileLock = NO_LOCK;
+                       rc = fcntlSizeHint(pFile, *(i64 *) pArg);
+                       SimulateIOErrorBenign(0);
+                       return rc;
+               }
+       case SQLITE_FCNTL_VFSNAME:{
+                       *(char **)pArg =
+                           sqlite3_mprintf("%s", pFile->pVfs->zName);
+                       return SQLITE_OK;
+               }
+       case SQLITE_FCNTL_TEMPFILENAME:{
+                       char *zTFile =
+                           sqlite3_malloc64(pFile->pVfs->mxPathname);
+                       if (zTFile) {
+                               unixGetTempname(pFile->pVfs->mxPathname,
+                                               zTFile);
+                               *(char **)pArg = zTFile;
                        }
+                       return SQLITE_OK;
                }
-               if (rc == SQLITE_OK) {
-                       pInode->nLock--;
-                       assert(pInode->nLock >= 0);
-                       if (pInode->nLock == 0) {
-                               closePendingFds(pFile);
+       case SQLITE_FCNTL_HAS_MOVED:{
+                       *(int *)pArg = fileHasMoved(pFile);
+                       return SQLITE_OK;
+               }
+       case SQLITE_FCNTL_MMAP_SIZE:{
+                       i64 newLimit = *(i64 *) pArg;
+                       int rc = SQLITE_OK;
+                       if (newLimit > sqlite3GlobalConfig.mxMmap) {
+                               newLimit = sqlite3GlobalConfig.mxMmap;
+                       }
+                       *(i64 *) pArg = pFile->mmapSizeMax;
+                       if (newLimit >= 0 && newLimit != pFile->mmapSizeMax
+                           && pFile->nFetchOut == 0) {
+                               pFile->mmapSizeMax = newLimit;
+                               if (pFile->mmapSize > 0) {
+                                       unixUnmapfile(pFile);
+                                       rc = unixMapfile(pFile, -1);
+                               }
                        }
+                       return rc;
                }
        }
-
-       if (rc == SQLITE_OK)
-               pFile->eFileLock = eFileLock;
-       return rc;
+       return SQLITE_NOTFOUND;
 }
 
 /*
- * Close a file & cleanup AFP specific locking context
+ * If it is currently memory mapped, unmap file pFd.
  */
-static int
-afpClose(sqlite3_file * id)
+static void
+unixUnmapfile(unixFile * pFd)
 {
-       int rc = SQLITE_OK;
-       unixFile *pFile = (unixFile *) id;
-       assert(id != 0);
-       afpUnlock(id, NO_LOCK);
-       if (pFile->pInode && pFile->pInode->nLock) {
-               /* If there are outstanding locks, do not actually close the 
file just
-                * yet because that would clear those locks.  Instead, add the 
file
-                * descriptor to pInode->aPending.  It will be automatically 
closed when
-                * the last lock is cleared.
-                */
-               setPendingFd(pFile);
+       assert(pFd->nFetchOut == 0);
+       if (pFd->pMapRegion) {
+               munmap(pFd->pMapRegion, pFd->mmapSizeActual);
+               pFd->pMapRegion = 0;
+               pFd->mmapSize = 0;
+               pFd->mmapSizeActual = 0;
        }
-       releaseInodeInfo(pFile);
-       sqlite3_free(pFile->lockingContext);
-       rc = closeUnixFile(id);
-       return rc;
 }
 
-#endif                         /* defined(__APPLE__) && 
SQLITE_ENABLE_LOCKING_STYLE */
 /*
- * The code above is the AFP lock implementation.  The code is specific
- * to MacOSX and does not work on other unix platforms.  No alternative
- * is available.  If you don't compile for a mac, then the "unix-afp"
- * VFS is not available.
+ * Attempt to set the size of the memory mapping maintained by file
+ * descriptor pFd to nNew bytes. Any existing mapping is discarded.
  *
- ******************** End of the AFP lock implementation **********************
- *****************************************************************************/
-
-/******************************************************************************
- ************************** Begin NFS Locking *******************************
- */
-
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-/*
- ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
- ** must be either NO_LOCK or SHARED_LOCK.
- **
- ** If the locking level of the file descriptor is already at or below
- ** the requested locking level, this routine is a no-op.
+ * If successful, this function sets the following variables:
+ *
+ *       unixFile.pMapRegion
+ *       unixFile.mmapSize
+ *       unixFile.mmapSizeActual
+ *
+ * If unsuccessful, an error message is logged via sqlite3_log() and
+ * the three variables above are zeroed. In this case SQLite should
+ * continue accessing the database using the xRead() and xWrite()
+ * methods.
  */
-static int
-nfsUnlock(sqlite3_file * id, int eFileLock)
+static void
+unixRemapfile(unixFile * pFd,  /* File descriptor object */
+             i64 nNew          /* Required mapping size */
+    )
 {
-       return posixUnlock(id, eFileLock, 1);
+       const char *zErr = "mmap";
+       int h = pFd->h;         /* File descriptor open on db file */
+       u8 *pOrig = (u8 *) pFd->pMapRegion;     /* Pointer to current file 
mapping */
+       i64 nOrig = pFd->mmapSizeActual;        /* Size of pOrig region in 
bytes */
+       u8 *pNew = 0;           /* Location of new mapping */
+       int flags = PROT_READ;  /* Flags to pass to mmap() */
+
+       assert(pFd->nFetchOut == 0);
+       assert(nNew > pFd->mmapSize);
+       assert(nNew <= pFd->mmapSizeMax);
+       assert(nNew > 0);
+       assert(pFd->mmapSizeActual >= pFd->mmapSize);
+       assert(MAP_FAILED != 0);
+
+       if (pOrig) {
+               i64 nReuse = pFd->mmapSize;
+               u8 *pReq = &pOrig[nReuse];
+
+               /* Unmap any pages of the existing mapping that cannot be 
reused. */
+               if (nReuse != nOrig)
+                       munmap(pReq, nOrig - nReuse);
+               #if !defined(__APPLE__) && !defined(__FreeBSD__)
+               pNew = mremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
+               zErr = "mremap";
+               #else
+               pNew = mmap(pReq, nNew - nReuse, flags, MAP_SHARED, h, nReuse);
+               if (pNew != MAP_FAILED) {
+                       if (pNew != pReq) {
+                               munmap(pNew, nNew - nReuse);
+                               pNew = NULL;
+                       } else {
+                               pNew = pOrig;
+                       }
+               }
+               #endif
+
+               /* The attempt to extend the existing mapping failed. Free it. 
*/
+               if (pNew == MAP_FAILED || pNew == NULL)
+                       munmap(pOrig, nReuse);
+       }
+
+       /* If pNew is still NULL, try to create an entirely new mapping. */
+       if (pNew == NULL)
+               pNew = mmap(0, nNew, flags, MAP_SHARED, h, 0);
+
+       if (pNew == MAP_FAILED) {
+               pNew = 0;
+               nNew = 0;
+               unixLogError(SQLITE_OK, zErr, pFd->zPath);
+
+               /* If the mmap() above failed, assume that all subsequent 
mmap() calls
+                * will probably fail too. Fall back to using xRead/xWrite 
exclusively
+                * in this case.
+                */
+               pFd->mmapSizeMax = 0;
+       }
+       pFd->pMapRegion = (void *)pNew;
+       pFd->mmapSize = pFd->mmapSizeActual = nNew;
 }
 
-#endif                         /* defined(__APPLE__) && 
SQLITE_ENABLE_LOCKING_STYLE */
 /*
- * The code above is the NFS lock implementation.  The code is specific
- * to MacOSX and does not work on other unix platforms.  No alternative
- * is available.
+ * Memory map or remap the file opened by file-descriptor pFd (if the file
+ * is already mapped, the existing mapping is replaced by the new). Or, if
+ * there already exists a mapping for this file, and there are still
+ * outstanding xFetch() references to it, this function is a no-op.
  *
- ******************** End of the NFS lock implementation **********************
- *****************************************************************************/
-
-/******************************************************************************
- *************** Non-locking sqlite3_file methods *****************************
+ * If parameter nByte is non-negative, then it is the requested size of
+ * the mapping to create. Otherwise, if nByte is less than zero, then the
+ * requested size is the size of the file on disk. The actual size of the
+ * created mapping is either the requested size or the value configured
+ * using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
  *
- * The next division contains implementations for all methods of the
- * sqlite3_file object other than the locking methods.  The locking
- * methods were defined in divisions above (one locking method per
- * division).  Those methods that are common to all locking modes
- * are gather together into this division.
+ * SQLITE_OK is returned if no error occurs (even if the mapping is not
+ * recreated as a result of outstanding references) or an SQLite error
+ * code otherwise.
  */
+static int
+unixMapfile(unixFile * pFd, i64 nMap)
+{
+       assert(nMap >= 0 || pFd->nFetchOut == 0);
+       assert(nMap > 0 || (pFd->mmapSize == 0 && pFd->pMapRegion == 0));
+       if (pFd->nFetchOut > 0)
+               return SQLITE_OK;
+
+       if (nMap < 0) {
+               struct stat statbuf;    /* Low-level file information */
+               if (fstat(pFd->h, &statbuf))
+                       return SQLITE_IOERR_FSTAT;
+               nMap = statbuf.st_size;
+       }
+       if (nMap > pFd->mmapSizeMax) {
+               nMap = pFd->mmapSizeMax;
+       }
+
+       assert(nMap > 0 || (pFd->mmapSize == 0 && pFd->pMapRegion == 0));
+       if (nMap != pFd->mmapSize) {
+               unixRemapfile(pFd, nMap);
+       }
+
+       return SQLITE_OK;
+}
 
 /*
- * Seek to the offset passed as the second argument, then read cnt
- * bytes into pBuf. Return the number of bytes actually read.
+ * If possible, return a pointer to a mapping of file fd starting at offset
+ * iOff. The mapping must be valid for at least nAmt bytes.
  *
- * NB:  If you define USE_PREAD or USE_PREAD64, then it might also
- * be necessary to define _XOPEN_SOURCE to be 500.  This varies from
- * one system to another.  Since SQLite does not define USE_PREAD
- * in any form by default, we will not attempt to define _XOPEN_SOURCE.
- * See tickets #2741 and #2681.
+ * If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
+ * Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
+ * Finally, if an error does occur, return an SQLite error code. The final
+ * value of *pp is undefined in this case.
  *
- * To avoid stomping the errno value on a failed read the lastErrno value
- * is set before returning.
+ * If this function does return a pointer, the caller must eventually
+ * release the reference by calling unixUnfetch().
  */
 static int
-seekAndRead(unixFile * id, sqlite3_int64 offset, void *pBuf, int cnt)
+unixFetch(sqlite3_file * fd MAYBE_UNUSED,
+         i64 iOff MAYBE_UNUSED,
+         int nAmt MAYBE_UNUSED, void **pp)
 {
-       int got;
-       int prior = 0;
-#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
-       i64 newOffset;
-#endif
-       TIMER_START;
-       assert(cnt == (cnt & 0x1ffff));
-       assert(id->h > 2);
-       do {
-#if defined(USE_PREAD)
-               got = osPread(id->h, pBuf, cnt, offset);
-               SimulateIOError(got = -1);
-#elif defined(USE_PREAD64)
-               got = osPread64(id->h, pBuf, cnt, offset);
-               SimulateIOError(got = -1);
-#else
-               newOffset = lseek(id->h, offset, SEEK_SET);
-               SimulateIOError(newOffset = -1);
-               if (newOffset < 0) {
-                       storeLastErrno((unixFile *) id, errno);
-                       return -1;
-               }
-               got = osRead(id->h, pBuf, cnt);
+#if SQLITE_MAX_MMAP_SIZE>0
+       unixFile *pFd = (unixFile *) fd;        /* The underlying database file 
*/
 #endif
-               if (got == cnt)
-                       break;
-               if (got < 0) {
-                       if (errno == EINTR) {
-                               got = 1;
-                               continue;
-                       }
-                       prior = 0;
-                       storeLastErrno((unixFile *) id, errno);
-                       break;
-               } else if (got > 0) {
-                       cnt -= got;
-                       offset += got;
-                       prior += got;
-                       pBuf = (void *)(got + (char *)pBuf);
-               }
-       } while (got > 0);
-       TIMER_END;
-       return got + prior;
-}
-
-/*
- * Read data from a file into a buffer.  Return SQLITE_OK if all
- * bytes were read successfully and SQLITE_IOERR if anything goes
- * wrong.
- */
-static int
-unixRead(sqlite3_file * id, void *pBuf, int amt, sqlite3_int64 offset)
-{
-       unixFile *pFile = (unixFile *) id;
-       int got;
-       assert(id);
-       assert(offset >= 0);
-       assert(amt > 0);
-
-#if SQLITE_MAX_MMAP_SIZE>0
-       /* Deal with as much of this read request as possible by transfering
-        * data from the memory mapping using memcpy().
-        */
-       if (offset < pFile->mmapSize) {
-               if (offset + amt <= pFile->mmapSize) {
-                       memcpy(pBuf, &((u8 *) (pFile->pMapRegion))[offset],
-                              amt);
-                       return SQLITE_OK;
-               } else {
-                       int nCopy = pFile->mmapSize - offset;
-                       memcpy(pBuf, &((u8 *) (pFile->pMapRegion))[offset],
-                              nCopy);
-                       pBuf = &((u8 *) pBuf)[nCopy];
-                       amt -= nCopy;
-                       offset += nCopy;
-               }
-       }
-#endif
-
-       got = seekAndRead(pFile, offset, pBuf, amt);
-       if (got == amt) {
-               return SQLITE_OK;
-       } else if (got < 0) {
-               /* lastErrno set by seekAndRead */
-               return SQLITE_IOERR_READ;
-       } else {
-               storeLastErrno(pFile, 0);       /* not a system error */
-               /* Unread parts of the buffer must be zero-filled */
-               memset(&((char *)pBuf)[got], 0, amt - got);
-               return SQLITE_IOERR_SHORT_READ;
-       }
-}
-
-/*
- * Attempt to seek the file-descriptor passed as the first argument to
- * absolute offset iOff, then attempt to write nBuf bytes of data from
- * pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
- * return the actual number of bytes written (which may be less than
- * nBuf).
- */
-static int
-seekAndWriteFd(int fd,         /* File descriptor to write to */
-              i64 iOff,        /* File offset to begin writing at */
-              const void *pBuf,        /* Copy data from this buffer to the 
file */
-              int nBuf,        /* Size of buffer pBuf in bytes */
-              int *piErrno     /* OUT: Error number if error occurs */
-    )
-{
-       int rc = 0;             /* Value returned by system call */
-
-       assert(nBuf == (nBuf & 0x1ffff));
-       assert(fd > 2);
-       assert(piErrno != 0);
-       nBuf &= 0x1ffff;
-       TIMER_START;
-
-#if defined(USE_PREAD)
-       do {
-               rc = (int)osPwrite(fd, pBuf, nBuf, iOff);
-       } while (rc < 0 && errno == EINTR);
-#elif defined(USE_PREAD64)
-       do {
-               rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);
-       } while (rc < 0 && errno == EINTR);
-#else
-       do {
-               i64 iSeek = lseek(fd, iOff, SEEK_SET);
-               SimulateIOError(iSeek = -1);
-               if (iSeek < 0) {
-                       rc = -1;
-                       break;
-               }
-               rc = osWrite(fd, pBuf, nBuf);
-       } while (rc < 0 && errno == EINTR);
-#endif
-
-       TIMER_END;
-
-       if (rc < 0)
-               *piErrno = errno;
-       return rc;
-}
-
-/*
- * Seek to the offset in id->offset then read cnt bytes into pBuf.
- * Return the number of bytes actually read.  Update the offset.
- *
- * To avoid stomping the errno value on a failed write the lastErrno value
- * is set before returning.
- */
-static int
-seekAndWrite(unixFile * id, i64 offset, const void *pBuf, int cnt)
-{
-       return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
-}
-
-/*
- * Write data from a buffer into a file.  Return SQLITE_OK on success
- * or some other error code on failure.
- */
-static int
-unixWrite(sqlite3_file * id, const void *pBuf, int amt, sqlite3_int64 offset)
-{
-       unixFile *pFile = (unixFile *) id;
-       int wrote = 0;
-       assert(id);
-       assert(amt > 0);
-
-#ifdef SQLITE_DEBUG
-       /* If we are doing a normal write to a database file,
-        * then record the fact that the database
-        * has changed.  If the transaction counter is modified, record that
-        * fact too.
-        */
-       if (pFile->inNormalWrite) {
-               pFile->dbUpdate = 1;    /* The database has been modified */
-               if (offset <= 24 && offset + amt >= 27) {
-                       int rc;
-                       char oldCntr[4];
-                       SimulateIOErrorBenign(1);
-                       rc = seekAndRead(pFile, 24, oldCntr, 4);
-                       SimulateIOErrorBenign(0);
-                       if (rc != 4
-                           || memcmp(oldCntr, &((char *)pBuf)[24 - offset],
-                                     4) != 0) {
-                               pFile->transCntrChng = 1;       /* The 
transaction counter has changed */
-                       }
-               }
-       }
-#endif
-
-#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
-       /* Deal with as much of this write request as possible by transfering
-        * data from the memory mapping using memcpy().
-        */
-       if (offset < pFile->mmapSize) {
-               if (offset + amt <= pFile->mmapSize) {
-                       memcpy(&((u8 *) (pFile->pMapRegion))[offset], pBuf,
-                              amt);
-                       return SQLITE_OK;
-               } else {
-                       int nCopy = pFile->mmapSize - offset;
-                       memcpy(&((u8 *) (pFile->pMapRegion))[offset], pBuf,
-                              nCopy);
-                       pBuf = &((u8 *) pBuf)[nCopy];
-                       amt -= nCopy;
-                       offset += nCopy;
-               }
-       }
-#endif
-
-       while ((wrote = seekAndWrite(pFile, offset, pBuf, amt)) < amt
-              && wrote > 0) {
-               amt -= wrote;
-               offset += wrote;
-               pBuf = &((char *)pBuf)[wrote];
-       }
-       SimulateIOError((wrote = (-1), amt = 1));
-       SimulateDiskfullError((wrote = 0, amt = 1));
-
-       if (amt > wrote) {
-               if (wrote < 0 && pFile->lastErrno != ENOSPC) {
-                       /* lastErrno set by seekAndWrite */
-                       return SQLITE_IOERR_WRITE;
-               } else {
-                       storeLastErrno(pFile, 0);       /* not a system error */
-                       return SQLITE_FULL;
-               }
-       }
-
-       return SQLITE_OK;
-}
-
-#ifdef SQLITE_TEST
-/*
- * Count the number of fullsyncs and normal syncs.  This is used to test
- * that syncs and fullsyncs are occurring at the right times.
- */
-int sqlite3_sync_count = 0;
-int sqlite3_fullsync_count = 0;
-#endif
-
-/*
- * We do not trust systems to provide a working fdatasync().  Some do.
- * Others do no.  To be safe, we will stick with the (slightly slower)
- * fsync(). If you know that your system does support fdatasync() correctly,
- * then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC
- */
-#if !defined(fdatasync) && !HAVE_FDATASYNC
-#define fdatasync fsync
-#endif
-
-/*
- * The fsync() system call does not work as advertised on many
- * unix systems.  The following procedure is an attempt to make
- * it work better.
- *
- * The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful
- * for testing when we want to run through the test suite quickly.
- * You are strongly advised *not* to deploy with SQLITE_NO_SYNC
- * enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
- * or power failure will likely corrupt the database file.
- *
- * SQLite sets the dataOnly flag if the size of the file is unchanged.
- * The idea behind dataOnly is that it should only write the file content
- * to disk, not the inode.  We only set dataOnly if the file size is
- * unchanged since the file size is part of the inode.  However,
- * Ted Ts'o tells us that fdatasync() will also write the inode if the
- * file size has changed.  The only real difference between fdatasync()
- * and fsync(), Ted tells us, is that fdatasync() will not flush the
- * inode if the mtime or owner or other inode attributes have changed.
- * We only care about the file size, not the other file attributes, so
- * as far as SQLite is concerned, an fdatasync() is always adequate.
- * So, we always use fdatasync() if it is available, regardless of
- * the value of the dataOnly flag.
- */
-static int
-full_fsync(int fd, int fullSync, int dataOnly)
-{
-       int rc;
-
-       /* The following "ifdef/elif/else/" block has the same structure as
-        * the one below. It is replicated here solely to avoid cluttering
-        * up the real code with the UNUSED_PARAMETER() macros.
-        */
-#ifdef SQLITE_NO_SYNC
-       UNUSED_PARAMETER(fd);
-       UNUSED_PARAMETER(fullSync);
-       UNUSED_PARAMETER(dataOnly);
-#else
-       UNUSED_PARAMETER(fullSync);
-       UNUSED_PARAMETER(dataOnly);
-#endif
-
-       /* Record the number of times that we do a normal fsync() and
-        * FULLSYNC.  This is used during testing to verify that this procedure
-        * gets called with the correct arguments.
-        */
-#ifdef SQLITE_TEST
-       if (fullSync)
-               sqlite3_fullsync_count++;
-       sqlite3_sync_count++;
-#endif
-
-       /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
-        * no-op.  But go ahead and call fstat() to validate the file
-        * descriptor as we need a method to provoke a failure during
-        * coverate testing.
-        */
-#ifdef SQLITE_NO_SYNC
-       {
-               struct stat buf;
-               rc = osFstat(fd, &buf);
-       }
-#elif defined(__APPLE__)
-       /* fdatasync() on HFS+ doesn't yet flush the file size if it changed 
correctly
-        * so currently we default to the macro that redefines fdatasync to 
fsync
-        */
-       rc = fsync(fd);
-#else
-       rc = fdatasync(fd);
-#endif                         /* ifdef SQLITE_NO_SYNC */
-
-       return rc;
-}
-
-/*
- * Open a file descriptor to the directory containing file zFilename.
- * If successful, *pFd is set to the opened file descriptor and
- * SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
- * or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
- * value.
- *
- * The directory file descriptor is used for only one thing - to
- * fsync() a directory to make sure file creation and deletion events
- * are flushed to disk.  Such fsyncs are not needed on newer
- * journaling filesystems, but are required on older filesystems.
- *
- * This routine can be overridden using the xSetSysCall interface.
- * The ability to override this routine was added in support of the
- * chromium sandbox.  Opening a directory is a security risk (we are
- * told) so making it overrideable allows the chromium sandbox to
- * replace this routine with a harmless no-op.  To make this routine
- * a no-op, replace it with a stub that returns SQLITE_OK but leaves
- * *pFd set to a negative number.
- *
- * If SQLITE_OK is returned, the caller is responsible for closing
- * the file descriptor *pFd using close().
- */
-static int
-openDirectory(const char *zFilename, int *pFd)
-{
-       int ii;
-       int fd;
-       char zDirname[MAX_PATHNAME + 1];
-
-       sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
-       for (ii = (int)strlen(zDirname); ii > 0 && zDirname[ii] != '/'; ii--) ;
-       if (ii > 0) {
-               zDirname[ii] = '\0';
-       } else {
-               if (zDirname[0] != '/')
-                       zDirname[0] = '.';
-               zDirname[1] = 0;
-       }
-       fd = robust_open(zDirname, O_RDONLY | O_BINARY, 0);
-
-       *pFd = fd;
-       if (fd >= 0)
-               return SQLITE_OK;
-       return unixLogError(SQLITE_CANTOPEN_BKPT, "openDirectory", zDirname);
-}
-
-/*
- * Make sure all writes to a particular file are committed to disk.
- *
- * If dataOnly==0 then both the file itself and its metadata (file
- * size, access time, etc) are synced.  If dataOnly!=0 then only the
- * file data is synced.
- *
- * Under Unix, also make sure that the directory entry for the file
- * has been created by fsync-ing the directory that contains the file.
- * If we do not do this and we encounter a power failure, the directory
- * entry for the journal might not exist after we reboot.  The next
- * SQLite to access the file will not know that the journal exists (because
- * the directory entry for the journal was never created) and the transaction
- * will not roll back - possibly leading to database corruption.
- */
-static int
-unixSync(sqlite3_file * id, int flags)
-{
-       int rc;
-       unixFile *pFile = (unixFile *) id;
-
-       int isDataOnly = (flags & SQLITE_SYNC_DATAONLY);
-       int isFullsync = (flags & 0x0F) == SQLITE_SYNC_FULL;
-
-       /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
-       assert((flags & 0x0F) == SQLITE_SYNC_NORMAL
-              || (flags & 0x0F) == SQLITE_SYNC_FULL);
-
-       /* Unix cannot, but some systems may return SQLITE_FULL from here. This
-        * line is to test that doing so does not cause any problems.
-        */
-       SimulateDiskfullError(return SQLITE_FULL);
-
-       assert(pFile);
-       rc = full_fsync(pFile->h, isFullsync, isDataOnly);
-       SimulateIOError(rc = 1);
-       if (rc) {
-               storeLastErrno(pFile, errno);
-               return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync",
-                                   pFile->zPath);
-       }
-
-       return rc;
-}
-
-/*
- * Truncate an open file to a specified size
- */
-static int
-unixTruncate(sqlite3_file * id, i64 nByte)
-{
-       unixFile *pFile = (unixFile *) id;
-       int rc;
-       assert(pFile);
-       SimulateIOError(return SQLITE_IOERR_TRUNCATE);
-
-       /* If the user has configured a chunk-size for this file, truncate the
-        * file so that it consists of an integer number of chunks (i.e. the
-        * actual file size after the operation may be larger than the requested
-        * size).
-        */
-       if (pFile->szChunk > 0) {
-               nByte =
-                   ((nByte + pFile->szChunk -
-                     1) / pFile->szChunk) * pFile->szChunk;
-       }
-
-       rc = robust_ftruncate(pFile->h, nByte);
-       if (rc) {
-               storeLastErrno(pFile, errno);
-               return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate",
-                                   pFile->zPath);
-       } else {
-#ifdef SQLITE_DEBUG
-               /* If we are doing a normal write to a database file (as 
opposed to
-                * doing a hot-journal rollback or a write to some file other 
than a
-                * normal database file) and we truncate the file to zero 
length,
-                * that effectively updates the change counter.
-                */
-               if (pFile->inNormalWrite && nByte == 0) {
-                       pFile->transCntrChng = 1;
-               }
-#endif
-
-#if SQLITE_MAX_MMAP_SIZE>0
-               /* If the file was just truncated to a size smaller than the 
currently
-                * mapped region, reduce the effective mapping size as well. 
SQLite will
-                * use read() and write() to access data beyond this point from 
now on.
-                */
-               if (nByte < pFile->mmapSize) {
-                       pFile->mmapSize = nByte;
-               }
-#endif
-
-               return SQLITE_OK;
-       }
-}
-
-/*
- * Determine the current size of a file in bytes
- */
-static int
-unixFileSize(sqlite3_file * id, i64 * pSize)
-{
-       int rc;
-       struct stat buf;
-       assert(id);
-       rc = osFstat(((unixFile *) id)->h, &buf);
-       SimulateIOError(rc = 1);
-       if (rc != 0) {
-               storeLastErrno((unixFile *) id, errno);
-               return SQLITE_IOERR_FSTAT;
-       }
-       *pSize = buf.st_size;
-
-       /* When opening a zero-size database, the findInodeInfo() procedure
-        * writes a single byte into that file in order to work around a bug
-        * in the OS-X msdos filesystem.  In order to avoid problems with upper
-        * layers, we need to report this file size as zero even though it is
-        * really 1.   Ticket #3260.
-        */
-       if (*pSize == 1)
-               *pSize = 0;
-
-       return SQLITE_OK;
-}
-
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-/*
- * Handler for proxy-locking file-control verbs.  Defined below in the
- * proxying locking division.
- */
-static int proxyFileControl(sqlite3_file *, int, void *);
-#endif
-
-/*
- * This function is called to handle the SQLITE_FCNTL_SIZE_HINT
- * file-control operation.  Enlarge the database to nBytes in size
- * (rounded up to the next chunk-size).  If the database is already
- * nBytes or larger, this routine is a no-op.
- */
-static int
-fcntlSizeHint(unixFile * pFile, i64 nByte)
-{
-       if (pFile->szChunk > 0) {
-               i64 nSize;      /* Required file size */
-               struct stat buf;        /* Used to hold return values of 
fstat() */
-
-               if (osFstat(pFile->h, &buf)) {
-                       return SQLITE_IOERR_FSTAT;
-               }
-
-               nSize =
-                   ((nByte + pFile->szChunk -
-                     1) / pFile->szChunk) * pFile->szChunk;
-               if (nSize > (i64) buf.st_size) {
-
-#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
-                       /* The code below is handling the return value of 
osFallocate()
-                        * correctly. posix_fallocate() is defined to "returns 
zero on success,
-                        * or an error number on  failure". See the manpage for 
details.
-                        */
-                       int err;
-                       do {
-                               err =
-                                   osFallocate(pFile->h, buf.st_size,
-                                               nSize - buf.st_size);
-                       } while (err == EINTR);
-                       if (err)
-                               return SQLITE_IOERR_WRITE;
-#else
-                       /* If the OS does not have posix_fallocate(), fake it. 
Write a
-                        * single byte to the last byte in each block that 
falls entirely
-                        * within the extended region. Then, if required, a 
single byte
-                        * at offset (nSize-1), to set the size of the file 
correctly.
-                        * This is a similar technique to that used by glibc on 
systems
-                        * that do not have a real fallocate() call.
-                        */
-                       int nBlk = buf.st_blksize;      /* File-system block 
size */
-                       int nWrite = 0; /* Number of bytes written by 
seekAndWrite */
-                       i64 iWrite;     /* Next offset to write to */
-
-                       iWrite = (buf.st_size / nBlk) * nBlk + nBlk - 1;
-                       assert(iWrite >= buf.st_size);
-                       assert(((iWrite + 1) % nBlk) == 0);
-                       for ( /*no-op */ ; iWrite < nSize + nBlk - 1;
-                            iWrite += nBlk) {
-                               if (iWrite >= nSize)
-                                       iWrite = nSize - 1;
-                               nWrite = seekAndWrite(pFile, iWrite, "", 1);
-                               if (nWrite != 1)
-                                       return SQLITE_IOERR_WRITE;
-                       }
-#endif
-               }
-       }
-#if SQLITE_MAX_MMAP_SIZE>0
-       if (pFile->mmapSizeMax > 0 && nByte > pFile->mmapSize) {
-               int rc;
-               if (pFile->szChunk <= 0) {
-                       if (robust_ftruncate(pFile->h, nByte)) {
-                               storeLastErrno(pFile, errno);
-                               return unixLogError(SQLITE_IOERR_TRUNCATE,
-                                                   "ftruncate", pFile->zPath);
-                       }
-               }
-
-               rc = unixMapfile(pFile, nByte);
-               return rc;
-       }
-#endif
-
-       return SQLITE_OK;
-}
-
-/* Forward declaration */
-static int unixGetTempname(int nBuf, char *zBuf);
-
-/*
- * Information and control of an open file handle.
- */
-static int
-unixFileControl(sqlite3_file * id, int op, void *pArg)
-{
-       unixFile *pFile = (unixFile *) id;
-       switch (op) {
-       case SQLITE_FCNTL_LOCKSTATE:{
-                       *(int *)pArg = pFile->eFileLock;
-                       return SQLITE_OK;
-               }
-       case SQLITE_FCNTL_LAST_ERRNO:{
-                       *(int *)pArg = pFile->lastErrno;
-                       return SQLITE_OK;
-               }
-       case SQLITE_FCNTL_CHUNK_SIZE:{
-                       pFile->szChunk = *(int *)pArg;
-                       return SQLITE_OK;
-               }
-       case SQLITE_FCNTL_SIZE_HINT:{
-                       int rc;
-                       SimulateIOErrorBenign(1);
-                       rc = fcntlSizeHint(pFile, *(i64 *) pArg);
-                       SimulateIOErrorBenign(0);
-                       return rc;
-               }
-       case SQLITE_FCNTL_VFSNAME:{
-                       *(char **)pArg =
-                           sqlite3_mprintf("%s", pFile->pVfs->zName);
-                       return SQLITE_OK;
-               }
-       case SQLITE_FCNTL_TEMPFILENAME:{
-                       char *zTFile =
-                           sqlite3_malloc64(pFile->pVfs->mxPathname);
-                       if (zTFile) {
-                               unixGetTempname(pFile->pVfs->mxPathname,
-                                               zTFile);
-                               *(char **)pArg = zTFile;
-                       }
-                       return SQLITE_OK;
-               }
-       case SQLITE_FCNTL_HAS_MOVED:{
-                       *(int *)pArg = fileHasMoved(pFile);
-                       return SQLITE_OK;
-               }
-#if SQLITE_MAX_MMAP_SIZE>0
-       case SQLITE_FCNTL_MMAP_SIZE:{
-                       i64 newLimit = *(i64 *) pArg;
-                       int rc = SQLITE_OK;
-                       if (newLimit > sqlite3GlobalConfig.mxMmap) {
-                               newLimit = sqlite3GlobalConfig.mxMmap;
-                       }
-                       *(i64 *) pArg = pFile->mmapSizeMax;
-                       if (newLimit >= 0 && newLimit != pFile->mmapSizeMax
-                           && pFile->nFetchOut == 0) {
-                               pFile->mmapSizeMax = newLimit;
-                               if (pFile->mmapSize > 0) {
-                                       unixUnmapfile(pFile);
-                                       rc = unixMapfile(pFile, -1);
-                               }
-                       }
-                       return rc;
-               }
-#endif
-#ifdef SQLITE_DEBUG
-               /* The pager calls this method to signal that it has done
-                * a rollback and that the database is therefore unchanged and
-                * it hence it is OK for the transaction change counter to be
-                * unchanged.
-                */
-       case SQLITE_FCNTL_DB_UNCHANGED:{
-                       ((unixFile *) id)->dbUpdate = 0;
-                       return SQLITE_OK;
-               }
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-       case SQLITE_FCNTL_SET_LOCKPROXYFILE:
-       case SQLITE_FCNTL_GET_LOCKPROXYFILE:{
-                       return proxyFileControl(id, op, pArg);
-               }
-#endif                         /* SQLITE_ENABLE_LOCKING_STYLE && 
defined(__APPLE__) */
-       }
-       return SQLITE_NOTFOUND;
-}
-
-/*
- * Return the sector size in bytes of the underlying block device for
- * the specified file. This is almost always 512 bytes, but may be
- * larger for some devices.
- *
- * SQLite code assumes this function cannot fail. It also assumes that
- * if two files are created in the same file-system directory (i.e.
- * a database and its journal file) that the sector size will be the
- * same for both.
- */
-static int
-unixSectorSize(sqlite3_file * NotUsed)
-{
-       UNUSED_PARAMETER(NotUsed);
-       return SQLITE_DEFAULT_SECTOR_SIZE;
-}
-
-/*
- * Return the device characteristics for the file.
- *
- * This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
- * However, that choice is controversial since technically the underlying
- * file system does not always provide powersafe overwrites.  (In other
- * words, after a power-loss event, parts of the file that were never
- * written might end up being altered.)  However, non-PSOW behavior is very,
- * very rare.  And asserting PSOW makes a large reduction in the amount
- * of required I/O for journaling, since a lot of padding is eliminated.
- *  Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
- * available to turn it off and URI query parameter available to turn it off.
- */
-static int
-unixDeviceCharacteristics(sqlite3_file * pNotUsed)
-{
-       UNUSED_PARAMETER(pNotUsed);
-       return SQLITE_OK;
-}
-
-#if SQLITE_MAX_MMAP_SIZE>0
-
-/*
- * Return the system page size.
- *
- * This function should not be called directly by other code in this file.
- * Instead, it should be called via macro osGetpagesize().
- */
-static int
-unixGetpagesize(void)
-{
-       return (int)sysconf(_SC_PAGESIZE);
-}
-
-#endif                         /* SQLITE_MAX_MMAP_SIZE>0 */
-
-#define unixShmMap     0
-#define unixShmLock    0
-#define unixShmBarrier 0
-#define unixShmUnmap   0
-
-#if SQLITE_MAX_MMAP_SIZE>0
-/*
- * If it is currently memory mapped, unmap file pFd.
- */
-static void
-unixUnmapfile(unixFile * pFd)
-{
-       assert(pFd->nFetchOut == 0);
-       if (pFd->pMapRegion) {
-               osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
-               pFd->pMapRegion = 0;
-               pFd->mmapSize = 0;
-               pFd->mmapSizeActual = 0;
-       }
-}
-
-/*
- * Attempt to set the size of the memory mapping maintained by file
- * descriptor pFd to nNew bytes. Any existing mapping is discarded.
- *
- * If successful, this function sets the following variables:
- *
- *       unixFile.pMapRegion
- *       unixFile.mmapSize
- *       unixFile.mmapSizeActual
- *
- * If unsuccessful, an error message is logged via sqlite3_log() and
- * the three variables above are zeroed. In this case SQLite should
- * continue accessing the database using the xRead() and xWrite()
- * methods.
- */
-static void
-unixRemapfile(unixFile * pFd,  /* File descriptor object */
-             i64 nNew          /* Required mapping size */
-    )
-{
-       const char *zErr = "mmap";
-       int h = pFd->h;         /* File descriptor open on db file */
-       u8 *pOrig = (u8 *) pFd->pMapRegion;     /* Pointer to current file 
mapping */
-       i64 nOrig = pFd->mmapSizeActual;        /* Size of pOrig region in 
bytes */
-       u8 *pNew = 0;           /* Location of new mapping */
-       int flags = PROT_READ;  /* Flags to pass to mmap() */
-
-       assert(pFd->nFetchOut == 0);
-       assert(nNew > pFd->mmapSize);
-       assert(nNew <= pFd->mmapSizeMax);
-       assert(nNew > 0);
-       assert(pFd->mmapSizeActual >= pFd->mmapSize);
-       assert(MAP_FAILED != 0);
-
-#ifdef SQLITE_MMAP_READWRITE
-       if ((pFd->ctrlFlags & UNIXFILE_RDONLY) == 0)
-               flags |= PROT_WRITE;
-#endif
-
-       if (pOrig) {
-#if HAVE_MREMAP
-               i64 nReuse = pFd->mmapSize;
-#else
-               const int szSyspage = osGetpagesize();
-               i64 nReuse = (pFd->mmapSize & ~(szSyspage - 1));
-#endif
-               u8 *pReq = &pOrig[nReuse];
-
-               /* Unmap any pages of the existing mapping that cannot be 
reused. */
-               if (nReuse != nOrig) {
-                       osMunmap(pReq, nOrig - nReuse);
-               }
-#if HAVE_MREMAP
-               pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
-               zErr = "mremap";
-#else
-               pNew =
-                   osMmap(pReq, nNew - nReuse, flags, MAP_SHARED, h, nReuse);
-               if (pNew != MAP_FAILED) {
-                       if (pNew != pReq) {
-                               osMunmap(pNew, nNew - nReuse);
-                               pNew = 0;
-                       } else {
-                               pNew = pOrig;
-                       }
-               }
-#endif
-
-               /* The attempt to extend the existing mapping failed. Free it. 
*/
-               if (pNew == MAP_FAILED || pNew == 0) {
-                       osMunmap(pOrig, nReuse);
-               }
-       }
-
-       /* If pNew is still NULL, try to create an entirely new mapping. */
-       if (pNew == 0) {
-               pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
-       }
-
-       if (pNew == MAP_FAILED) {
-               pNew = 0;
-               nNew = 0;
-               unixLogError(SQLITE_OK, zErr, pFd->zPath);
-
-               /* If the mmap() above failed, assume that all subsequent 
mmap() calls
-                * will probably fail too. Fall back to using xRead/xWrite 
exclusively
-                * in this case.
-                */
-               pFd->mmapSizeMax = 0;
-       }
-       pFd->pMapRegion = (void *)pNew;
-       pFd->mmapSize = pFd->mmapSizeActual = nNew;
-}
-
-/*
- * Memory map or remap the file opened by file-descriptor pFd (if the file
- * is already mapped, the existing mapping is replaced by the new). Or, if
- * there already exists a mapping for this file, and there are still
- * outstanding xFetch() references to it, this function is a no-op.
- *
- * If parameter nByte is non-negative, then it is the requested size of
- * the mapping to create. Otherwise, if nByte is less than zero, then the
- * requested size is the size of the file on disk. The actual size of the
- * created mapping is either the requested size or the value configured
- * using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
- *
- * SQLITE_OK is returned if no error occurs (even if the mapping is not
- * recreated as a result of outstanding references) or an SQLite error
- * code otherwise.
- */
-static int
-unixMapfile(unixFile * pFd, i64 nMap)
-{
-       assert(nMap >= 0 || pFd->nFetchOut == 0);
-       assert(nMap > 0 || (pFd->mmapSize == 0 && pFd->pMapRegion == 0));
-       if (pFd->nFetchOut > 0)
-               return SQLITE_OK;
-
-       if (nMap < 0) {
-               struct stat statbuf;    /* Low-level file information */
-               if (osFstat(pFd->h, &statbuf)) {
-                       return SQLITE_IOERR_FSTAT;
-               }
-               nMap = statbuf.st_size;
-       }
-       if (nMap > pFd->mmapSizeMax) {
-               nMap = pFd->mmapSizeMax;
-       }
-
-       assert(nMap > 0 || (pFd->mmapSize == 0 && pFd->pMapRegion == 0));
-       if (nMap != pFd->mmapSize) {
-               unixRemapfile(pFd, nMap);
-       }
-
-       return SQLITE_OK;
-}
-#endif                         /* SQLITE_MAX_MMAP_SIZE>0 */
-
-/*
- * If possible, return a pointer to a mapping of file fd starting at offset
- * iOff. The mapping must be valid for at least nAmt bytes.
- *
- * If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
- * Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
- * Finally, if an error does occur, return an SQLite error code. The final
- * value of *pp is undefined in this case.
- *
- * If this function does return a pointer, the caller must eventually
- * release the reference by calling unixUnfetch().
- */
-static int
-unixFetch(sqlite3_file * fd MAYBE_UNUSED,
-         i64 iOff MAYBE_UNUSED,
-         int nAmt MAYBE_UNUSED, void **pp)
-{
-#if SQLITE_MAX_MMAP_SIZE>0
-       unixFile *pFd = (unixFile *) fd;        /* The underlying database file 
*/
-#endif
-       *pp = 0;
-
-#if SQLITE_MAX_MMAP_SIZE>0
-       if (pFd->mmapSizeMax > 0) {
-               if (pFd->pMapRegion == 0) {
-                       int rc = unixMapfile(pFd, -1);
-                       if (rc != SQLITE_OK)
-                               return rc;
-               }
-               if (pFd->mmapSize >= iOff + nAmt) {
-                       *pp = &((u8 *) pFd->pMapRegion)[iOff];
-                       pFd->nFetchOut++;
-               }
-       }
-#endif
-       return SQLITE_OK;
-}
-
-/*
- * If the third argument is non-NULL, then this function releases a
- * reference obtained by an earlier call to unixFetch(). The second
- * argument passed to this function must be the same as the corresponding
- * argument that was passed to the unixFetch() invocation.
- *
- * Or, if the third argument is NULL, then this function is being called
- * to inform the VFS layer that, according to POSIX, any existing mapping
- * may now be invalid and should be unmapped.
- */
-static int
-unixUnfetch(sqlite3_file * fd, i64 iOff, void *p)
-{
-#if SQLITE_MAX_MMAP_SIZE>0
-       unixFile *pFd = (unixFile *) fd;        /* The underlying database file 
*/
-       UNUSED_PARAMETER(iOff);
-
-       /* If p==0 (unmap the entire file) then there must be no outstanding
-        * xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
-        * then there must be at least one outstanding.
-        */
-       assert((p == 0) == (pFd->nFetchOut == 0));
-
-       /* If p!=0, it must match the iOff value. */
-       assert(p == 0 || p == &((u8 *) pFd->pMapRegion)[iOff]);
-
-       if (p) {
-               pFd->nFetchOut--;
-       } else {
-               unixUnmapfile(pFd);
-       }
-
-       assert(pFd->nFetchOut >= 0);
-#else
-       UNUSED_PARAMETER(fd);
-       UNUSED_PARAMETER(p);
-       UNUSED_PARAMETER(iOff);
-#endif
-       return SQLITE_OK;
-}
-
-/*
- * Here ends the implementation of all sqlite3_file methods.
- *
- ********************* End sqlite3_file Methods *******************************
- *****************************************************************************/
-
-/*
- * This division contains definitions of sqlite3_io_methods objects that
- * implement various file locking strategies.  It also contains definitions
- * of "finder" functions.  A finder-function is used to locate the appropriate
- * sqlite3_io_methods object for a particular database file.  The pAppData
- * field of the sqlite3_vfs VFS objects are initialized to be pointers to
- * the correct finder-function for that VFS.
- *
- * Most finder functions return a pointer to a fixed sqlite3_io_methods
- * object.  The only interesting finder-function is autolockIoFinder, which
- * looks at the filesystem type and tries to guess the best locking
- * strategy from that.
- *
- * For finder-function F, two objects are created:
- *
- *    (1) The real finder-function named "FImpt()".
- *
- *    (2) A constant pointer to this function named just "F".
- *
- *
- * A pointer to the F pointer is used as the pAppData value for VFS
- * objects.  We have to do this instead of letting pAppData point
- * directly at the finder-function since C90 rules prevent a void*
- * from be cast into a function pointer.
- *
- *
- * Each instance of this macro generates two objects:
- *
- *   *  A constant sqlite3_io_methods object call METHOD that has locking
- *      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
- *
- *   *  An I/O method finder function called FINDER that returns a pointer
- *      to the METHOD object in the previous bullet.
- */
-#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP)     \
-static const sqlite3_io_methods METHOD = {                                   \
-   VERSION,                    /* iVersion */                                \
-   CLOSE,                      /* xClose */                                  \
-   unixRead,                   /* xRead */                                   \
-   unixWrite,                  /* xWrite */                                  \
-   unixTruncate,               /* xTruncate */                               \
-   unixSync,                   /* xSync */                                   \
-   unixFileSize,               /* xFileSize */                               \
-   LOCK,                       /* xLock */                                   \
-   UNLOCK,                     /* xUnlock */                                 \
-   CKLOCK,                     /* xCheckReservedLock */                      \
-   unixFileControl,            /* xFileControl */                            \
-   unixSectorSize,             /* xSectorSize */                             \
-   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
-   SHMMAP,                     /* xShmMap */                                 \
-   unixShmLock,                /* xShmLock */                                \
-   unixShmBarrier,             /* xShmBarrier */                             \
-   unixShmUnmap,               /* xShmUnmap */                               \
-   unixFetch,                  /* xFetch */                                  \
-   unixUnfetch,                /* xUnfetch */                                \
-};                                                                           \
-static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
-  UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
-  return &METHOD;                                                            \
-}                                                                            \
-static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
-    = FINDER##Impl;
-
-/*
- * Here are all of the sqlite3_io_methods objects for each of the
- * locking strategies.  Functions that return pointers to these methods
- * are also created.
- */
-IOMETHODS(posixIoFinder,       /* Finder function name */
-         posixIoMethods,       /* sqlite3_io_methods object name */
-         3,                    /* shared memory and mmap are enabled */
-         unixClose,            /* xClose method */
-         unixLock,             /* xLock method */
-         unixUnlock,           /* xUnlock method */
-         unixCheckReservedLock,        /* xCheckReservedLock method */
-         unixShmMap            /* xShmMap method */
-    )
-    IOMETHODS(nolockIoFinder,  /* Finder function name */
-             nolockIoMethods,  /* sqlite3_io_methods object name */
-             3,                /* shared memory is disabled */
-             nolockClose,      /* xClose method */
-             nolockLock,       /* xLock method */
-             nolockUnlock,     /* xUnlock method */
-             nolockCheckReservedLock,  /* xCheckReservedLock method */
-             0                 /* xShmMap method */
-    )
-    IOMETHODS(dotlockIoFinder, /* Finder function name */
-             dotlockIoMethods, /* sqlite3_io_methods object name */
-             1,                /* shared memory is disabled */
-             dotlockClose,     /* xClose method */
-             dotlockLock,      /* xLock method */
-             dotlockUnlock,    /* xUnlock method */
-             dotlockCheckReservedLock, /* xCheckReservedLock method */
-             0                 /* xShmMap method */
-    )
-#if SQLITE_ENABLE_LOCKING_STYLE
-    IOMETHODS(flockIoFinder,   /* Finder function name */
-             flockIoMethods,   /* sqlite3_io_methods object name */
-             1,                /* shared memory is disabled */
-             flockClose,       /* xClose method */
-             flockLock,        /* xLock method */
-             flockUnlock,      /* xUnlock method */
-             flockCheckReservedLock,   /* xCheckReservedLock method */
-             0                 /* xShmMap method */
-    )
-#endif
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-    IOMETHODS(afpIoFinder,     /* Finder function name */
-             afpIoMethods,     /* sqlite3_io_methods object name */
-             1,                /* shared memory is disabled */
-             afpClose,         /* xClose method */
-             afpLock,          /* xLock method */
-             afpUnlock,        /* xUnlock method */
-             afpCheckReservedLock,     /* xCheckReservedLock method */
-             0                 /* xShmMap method */
-    )
-#endif
-/*
- * The proxy locking method is a "super-method" in the sense that it
- * opens secondary file descriptors for the conch and lock files and
- * it uses proxy, dot-file, AFP, and flock() locking methods on those
- * secondary files.  For this reason, the division that implements
- * proxy locking is located much further down in the file.  But we need
- * to go ahead and define the sqlite3_io_methods and finder function
- * for proxy locking here.  So we forward declare the I/O methods.
- */
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-static int
-proxyClose(sqlite3_file *);
-static int
-proxyLock(sqlite3_file *, int);
-static int
-proxyUnlock(sqlite3_file *, int);
-static int
-proxyCheckReservedLock(sqlite3_file *, int *);
-IOMETHODS(proxyIoFinder,       /* Finder function name */
-         proxyIoMethods,       /* sqlite3_io_methods object name */
-         1,                    /* shared memory is disabled */
-         proxyClose,           /* xClose method */
-         proxyLock,            /* xLock method */
-         proxyUnlock,          /* xUnlock method */
-         proxyCheckReservedLock,       /* xCheckReservedLock method */
-         0                     /* xShmMap method */
-    )
-#endif
-/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-    IOMETHODS(nfsIoFinder,     /* Finder function name */
-             nfsIoMethods,     /* sqlite3_io_methods object name */
-             1,                /* shared memory is disabled */
-             unixClose,        /* xClose method */
-             unixLock,         /* xLock method */
-             nfsUnlock,        /* xUnlock method */
-             unixCheckReservedLock,    /* xCheckReservedLock method */
-             0                 /* xShmMap method */
-    )
-#endif
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-/*
- * This "finder" function attempts to determine the best locking strategy
- * for the database file "filePath".  It then returns the sqlite3_io_methods
- * object that implements that strategy.
- *
- * This is for MacOSX only.
- */
-static const sqlite3_io_methods *
-autolockIoFinderImpl(const char *filePath,     /* name of the database file */
-                    unixFile * pNew    /* open file object for the database 
file */
-    )
-{
-       static const struct Mapping {
-               const char *zFilesystem;        /* Filesystem type name */
-               const sqlite3_io_methods *pMethods;     /* Appropriate locking 
method */
-       } aMap[] = {
-               {
-               "hfs", &posixIoMethods}, {
-               "ufs", &posixIoMethods}, {
-               "afpfs", &afpIoMethods}, {
-               "smbfs", &afpIoMethods}, {
-               "webdav", &nolockIoMethods}, {
-               0, 0}
-       };
-       int i;
-       struct statfs fsInfo;
-       struct flock lockInfo;
-
-       if (!filePath) {
-               /* If filePath==NULL that means we are dealing with a transient 
file
-                * that does not need to be locked.
-                */
-               return &nolockIoMethods;
-       }
-       if (statfs(filePath, &fsInfo) != -1) {
-               if (fsInfo.f_flags & MNT_RDONLY) {
-                       return &nolockIoMethods;
-               }
-               for (i = 0; aMap[i].zFilesystem; i++) {
-                       if (strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem) ==
-                           0) {
-                               return aMap[i].pMethods;
-                       }
-               }
-       }
-
-       /* Default case. Handles, amongst others, "nfs".
-        * Test byte-range lock using fcntl(). If the call succeeds,
-        * assume that the file-system supports POSIX style locks.
-        */
-       lockInfo.l_len = 1;
-       lockInfo.l_start = 0;
-       lockInfo.l_whence = SEEK_SET;
-       lockInfo.l_type = F_RDLCK;
-       if (osFcntl(pNew->h, F_GETLK, &lockInfo) != -1) {
-               if (strcmp(fsInfo.f_fstypename, "nfs") == 0) {
-                       return &nfsIoMethods;
-               } else {
-                       return &posixIoMethods;
-               }
-       } else {
-               return &dotlockIoMethods;
-       }
-}
-
-static const sqlite3_io_methods
-    * (*const autolockIoFinder)(const char *, unixFile *) =
-    autolockIoFinderImpl;
-
-#endif                         /* defined(__APPLE__) && 
SQLITE_ENABLE_LOCKING_STYLE */
-
-/*
- * An abstract type for a pointer to an IO method finder function:
- */
-typedef const sqlite3_io_methods *(*finder_type) (const char *, unixFile *);
-
-/****************************************************************************
- *************************** sqlite3_vfs methods ****************************
- *
- * This division contains the implementation of methods on the
- * sqlite3_vfs object.
- */
-
-/*
- * Initialize the contents of the unixFile structure pointed to by pId.
- */
-static int
-fillInUnixFile(sqlite3_vfs * pVfs,     /* Pointer to vfs object */
-              int h,           /* Open file descriptor of file being opened */
-              sqlite3_file * pId,      /* Write to the unixFile structure here 
*/
-              const char *zFilename,   /* Name of the file being opened */
-              int ctrlFlags    /* Zero or more UNIXFILE_* values */
-    )
-{
-       const sqlite3_io_methods *pLockingStyle;
-       unixFile *pNew = (unixFile *) pId;
-       int rc = SQLITE_OK;
-
-       assert(pNew->pInode == NULL);
-
-       /* Usually the path zFilename should not be a relative pathname. The
-        * exception is when opening the proxy "conch" file in builds that
-        * include the special Apple locking styles.
-        */
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-       assert(zFilename == 0 || zFilename[0] == '/'
-              || pVfs->pAppData == (void *)&autolockIoFinder);
-#else
-       assert(zFilename == 0 || zFilename[0] == '/');
-#endif
-
-       /* No locking occurs in temporary files */
-       assert(zFilename != 0 || (ctrlFlags & UNIXFILE_NOLOCK) != 0);
-
-       pNew->h = h;
-       pNew->pVfs = pVfs;
-       pNew->zPath = zFilename;
-       pNew->ctrlFlags = (u8) ctrlFlags;
-#if SQLITE_MAX_MMAP_SIZE>0
-       pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
-#endif
-       if (strcmp(pVfs->zName, "unix-excl") == 0) {
-               pNew->ctrlFlags |= UNIXFILE_EXCL;
-       }
-       if (ctrlFlags & UNIXFILE_NOLOCK) {
-               pLockingStyle = &nolockIoMethods;
-       } else {
-               pLockingStyle =
-                   (**(finder_type *) pVfs->pAppData) (zFilename, pNew);
-#if SQLITE_ENABLE_LOCKING_STYLE
-               /* Cache zFilename in the locking context (AFP and dotlock 
override) for
-                * proxyLock activation is possible (remote proxy is based on 
db name)
-                * zFilename remains valid until file is closed, to support
-                */
-               pNew->lockingContext = (void *)zFilename;
-#endif
-       }
-
-       if (pLockingStyle == &posixIoMethods
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
-           || pLockingStyle == &nfsIoMethods
-#endif
-           ) {
-               rc = findInodeInfo(pNew, &pNew->pInode);
-               if (rc != SQLITE_OK) {
-                       /* If an error occurred in findInodeInfo(), close the 
file descriptor
-                        * immediately. findInodeInfo() may fail
-                        * in two scenarios:
-                        *
-                        *   (a) A call to fstat() failed.
-                        *   (b) A malloc failed.
-                        *
-                        * Scenario (b) may only occur if the process is 
holding no other
-                        * file descriptors open on the same file. If there 
were other file
-                        * descriptors on this file, then no malloc would be 
required by
-                        * findInodeInfo(). If this is the case, it is quite 
safe to close
-                        * handle h - as it is guaranteed that no posix locks 
will be released
-                        * by doing so.
-                        *
-                        * If scenario (a) caused the error then things are not 
so safe. The
-                        * implicit assumption here is that if fstat() fails, 
things are in
-                        * such bad shape that dropping a lock or two doesn't 
matter much.
-                        */
-                       robust_close(pNew, h, __LINE__);
-                       h = -1;
-               }
-       }
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-       else if (pLockingStyle == &afpIoMethods) {
-               /* AFP locking uses the file path so it needs to be included in
-                * the afpLockingContext.
-                */
-               afpLockingContext *pCtx;
-               pNew->lockingContext = pCtx = sqlite3_malloc64(sizeof(*pCtx));
-               if (pCtx == 0) {
-                       rc = SQLITE_NOMEM_BKPT;
-               } else {
-                       /* NB: zFilename exists and remains valid until the 
file is closed
-                        * according to requirement F11141.  So we do not need 
to make a
-                        * copy of the filename.
-                        */
-                       pCtx->dbPath = zFilename;
-                       pCtx->reserved = 0;
-                       srandomdev();
-                       rc = findInodeInfo(pNew, &pNew->pInode);
-                       if (rc != SQLITE_OK) {
-                               sqlite3_free(pNew->lockingContext);
-                               robust_close(pNew, h, __LINE__);
-                               h = -1;
-                       }
-               }
-       }
-#endif
-
-       else if (pLockingStyle == &dotlockIoMethods) {
-               /* Dotfile locking uses the file path so it needs to be 
included in
-                * the dotlockLockingContext
-                */
-               char *zLockFile;
-               int nFilename;
-               assert(zFilename != 0);
-               nFilename = (int)strlen(zFilename) + 6;
-               zLockFile = (char *)sqlite3_malloc64(nFilename);
-               if (zLockFile == 0) {
-                       rc = SQLITE_NOMEM_BKPT;
-               } else {
-                       sqlite3_snprintf(nFilename, zLockFile,
-                                        "%s" DOTLOCK_SUFFIX, zFilename);
-               }
-               pNew->lockingContext = zLockFile;
-       }
-       storeLastErrno(pNew, 0);
-       if (rc != SQLITE_OK) {
-               if (h >= 0)
-                       robust_close(pNew, h, __LINE__);
-       } else {
-               pNew->pMethod = pLockingStyle;
-               OpenCounter(+1);
-               verifyDbFile(pNew);
-       }
-       return rc;
-}
-
-/*
- * Return the name of a directory in which to put temporary files.
- * If no suitable temporary file directory can be found, return NULL.
- */
-static const char *
-unixTempFileDir(void)
-{
-       static const char *azDirs[] = {
-               0,
-               0,
-               "/var/tmp",
-               "/usr/tmp",
-               "/tmp",
-               "."
-       };
-       unsigned int i = 0;
-       struct stat buf;
-       const char *zDir = sqlite3_temp_directory;
-
-       if (!azDirs[0])
-               azDirs[0] = getenv("SQLITE_TMPDIR");
-       if (!azDirs[1])
-               azDirs[1] = getenv("TMPDIR");
-       while (1) {
-               if (zDir != 0 && osStat(zDir, &buf) == 0 && S_ISDIR(buf.st_mode)
-                   && osAccess(zDir, 03) == 0) {
-                       return zDir;
-               }
-               if (i >= sizeof(azDirs) / sizeof(azDirs[0]))
-                       break;
-               zDir = azDirs[i++];
-       }
-       return 0;
-}
-
-/*
- * Create a temporary file name in zBuf.  zBuf must be allocated
- * by the calling process and must be big enough to hold at least
- * pVfs->mxPathname bytes.
- */
-static int
-unixGetTempname(int nBuf, char *zBuf)
-{
-       const char *zDir;
-       int iLimit = 0;
-
-       /* It's odd to simulate an io-error here, but really this is just
-        * using the io-error infrastructure to test that SQLite handles this
-        * function failing.
-        */
-       zBuf[0] = 0;
-       SimulateIOError(return SQLITE_IOERR);
-
-       zDir = unixTempFileDir();
-       if (zDir == 0)
-               return SQLITE_IOERR_GETTEMPPATH;
-       do {
-               u64 r;
-               sqlite3_randomness(sizeof(r), &r);
-               assert(nBuf > 2);
-               zBuf[nBuf - 2] = 0;
-               sqlite3_snprintf(nBuf, zBuf,
-                                "%s/" SQLITE_TEMP_FILE_PREFIX "%llx%c", zDir,
-                                r, 0);
-               if (zBuf[nBuf - 2] != 0 || (iLimit++) > 10)
-                       return SQLITE_ERROR;
-       } while (osAccess(zBuf, 0) == 0);
-       return SQLITE_OK;
-}
-
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-/*
- * Routine to transform a unixFile into a proxy-locking unixFile.
- * Implementation in the proxy-lock division, but used by unixOpen()
- * if SQLITE_PREFER_PROXY_LOCKING is defined.
- */
-static int proxyTransformUnixFile(unixFile *, const char *);
-#endif
-
-/*
- * Search for an unused file descriptor that was opened on the database
- * file (not a journal or master-journal file) identified by pathname
- * zPath with SQLITE_OPEN_XXX flags matching those passed as the second
- * argument to this function.
- *
- * Such a file descriptor may exist if a database connection was closed
- * but the associated file descriptor could not be closed because some
- * other file descriptor open on the same file is holding a file-lock.
- * Refer to comments in the unixClose() function and the lengthy comment
- * describing "Posix Advisory Locking" at the start of this file for
- * further details. Also, ticket #4018.
- *
- * If a suitable file descriptor is found, then it is returned. If no
- * such file descriptor is located, -1 is returned.
- */
-static UnixUnusedFd *
-findReusableFd(const char *zPath, int flags)
-{
-       UnixUnusedFd *pUnused = 0;
-       
-       struct stat sStat;      /* Results of stat() call */
-
-       /* A stat() call may fail for various reasons. If this happens, it is
-        * almost certain that an open() call on the same path will also fail.
-        * For this reason, if an error occurs in the stat() call here, it is
-        * ignored and -1 is returned. The caller will try to open a new file
-        * descriptor on the same path, fail, and return an error to SQLite.
-        *
-        * Even if a subsequent open() call does succeed, the consequences of
-        * not searching for a reusable file descriptor are not dire.
-        */
-       if (0 == osStat(zPath, &sStat)) {
-               unixInodeInfo *pInode;
-
-               pInode = inodeList;
-               while (pInode && (pInode->fileId.dev != sStat.st_dev
-                                 || pInode->fileId.ino !=
-                                 (u64) sStat.st_ino)) {
-                       pInode = pInode->pNext;
-               }
-               if (pInode) {
-                       UnixUnusedFd **pp;
-                       for (pp = &pInode->pUnused;
-                            *pp && (*pp)->flags != flags;
-                            pp = &((*pp)->pNext)) ;
-                       pUnused = *pp;
-                       if (pUnused) {
-                               *pp = pUnused->pNext;
-                       }
-               }
-       }
-       return pUnused;
-}
-
-/*
- * Find the mode, uid and gid of file zFile.
- */
-static int
-getFileMode(const char *zFile, /* File name */
-           mode_t * pMode,     /* OUT: Permissions of zFile */
-           uid_t * pUid,       /* OUT: uid of zFile. */
-           gid_t * pGid        /* OUT: gid of zFile. */
-    )
-{
-       struct stat sStat;      /* Output of stat() on database file */
-       int rc = SQLITE_OK;
-       if (0 == osStat(zFile, &sStat)) {
-               *pMode = sStat.st_mode & 0777;
-               *pUid = sStat.st_uid;
-               *pGid = sStat.st_gid;
-       } else {
-               rc = SQLITE_IOERR_FSTAT;
-       }
-       return rc;
-}
-
-/*
- * This function is called by unixOpen() to determine the unix permissions
- * to create new files with. If no error occurs, then SQLITE_OK is returned
- * and a value suitable for passing as the third argument to open(2) is
- * written to *pMode. If an IO error occurs, an SQLite error code is
- * returned and the value of *pMode is not modified.
- *
- * In most cases, this routine sets *pMode to 0, which will become
- * an indication to robust_open() to create the file using
- * SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
- * But if the file being opened is a regular journal file, then
- * this function queries the file-system for the permissions on the
- * corresponding database file and sets *pMode to this value. Whenever
- * possible, journal files are created using the same permissions
- * as the associated database file.
- *
- * If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
- * original filename is unavailable.  But 8_3_NAMES is only used for
- * FAT filesystems and permissions do not matter there, so just use
- * the default permissions.
- */
-static int
-findCreateFileMode(const char *zPath,  /* Path of file (possibly) being 
created */
-                  int flags,   /* Flags passed as 4th argument to xOpen() */
-                  mode_t * pMode,      /* OUT: Permissions to open file with */
-                  uid_t * pUid,        /* OUT: uid to set on the file */
-                  gid_t * pGid /* OUT: gid to set on the file */
-    )
-{
-       int rc = SQLITE_OK;     /* Return Code */
-       *pMode = 0;
-       *pUid = 0;
-       *pGid = 0;
-       if (flags & SQLITE_OPEN_DELETEONCLOSE) {
-               *pMode = 0600;
-       } else if (flags & SQLITE_OPEN_URI) {
-               /* If this is a main database file and the file was opened 
using a URI
-                * filename, check for the "modeof" parameter. If present, 
interpret
-                * its value as a filename and try to copy the mode, uid and 
gid from
-                * that file.
-                */
-               const char *z = sqlite3_uri_parameter(zPath, "modeof");
-               if (z) {
-                       rc = getFileMode(z, pMode, pUid, pGid);
-               }
-       }
-       return rc;
-}
-
-/*
- * Open the file zPath.
- *
- * Previously, the SQLite OS layer used three functions in place of this
- * one:
- *
- *     sqlite3OsOpenReadWrite();
- *     sqlite3OsOpenReadOnly();
- *     sqlite3OsOpenExclusive();
- *
- * These calls correspond to the following combinations of flags:
- *
- *     ReadWrite() ->     (READWRITE | CREATE)
- *     ReadOnly()  ->     (READONLY)
- *     OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
- *
- * The old OpenExclusive() accepted a boolean argument - "delFlag". If
- * true, the file was configured to be automatically deleted when the
- * file handle closed. To achieve the same effect using this new
- * interface, add the DELETEONCLOSE flag to those specified above for
- * OpenExclusive().
- */
-static int
-unixOpen(sqlite3_vfs * pVfs,   /* The VFS for which this is the xOpen method */
-        const char *zPath,     /* Pathname of file to be opened */
-        sqlite3_file * pFile,  /* The file descriptor to be filled in */
-        int flags,             /* Input flags to control the opening */
-        int *pOutFlags         /* Output flags returned to SQLite core */
-    )
-{
-       unixFile *p = (unixFile *) pFile;
-       int fd = -1;            /* File descriptor returned by open() */
-       int openFlags = 0;      /* Flags to pass to open() */
-       int eType = flags & 0xFFFFFF00; /* Type of file to open */
-       int noLock;             /* True to omit locking primitives */
-       int rc;                 /* Function Return Code */
-       int ctrlFlags = 0;      /* UNIXFILE_* flags */
-
-       int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
-       int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
-       int isCreate = (flags & SQLITE_OPEN_CREATE);
-       int isReadonly = (flags & SQLITE_OPEN_READONLY);
-       int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
-#if SQLITE_ENABLE_LOCKING_STYLE
-       int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
-#endif
-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-       struct statfs fsInfo;
-#endif
-
-       /* If creating a master or main-file journal, this function will open
-        * a file-descriptor on the directory too. The first time unixSync()
-        * is called the directory file descriptor will be fsync()ed and 
close()d.
-        */
-       int syncDir = isCreate;
-
-       /* If argument zPath is a NULL pointer, this function is required to 
open
-        * a temporary file. Use this buffer to store the file name in.
-        */
-       char zTmpname[MAX_PATHNAME + 2];
-       const char *zName = zPath;
-
-       /* Check the following statements are true:
-        *
-        *   (a) Exactly one of the READWRITE and READONLY flags must be set, 
and
-        *   (b) if CREATE is set, then READWRITE must also be set, and
-        *   (c) if EXCLUSIVE is set, then CREATE must also be set.
-        *   (d) if DELETEONCLOSE is set, then CREATE must also be set.
-        */
-       assert((isReadonly == 0 || isReadWrite == 0)
-              && (isReadWrite || isReadonly));
-       assert(isCreate == 0 || isReadWrite);
-       assert(isExclusive == 0 || isCreate);
-       assert(isDelete == 0 || isCreate);
-
-       /* Detect a pid change and reset the PRNG.  There is a race condition
-        * here such that two or more threads all trying to open databases at
-        * the same instant might all reset the PRNG.  But multiple resets
-        * are harmless.
-        */
-       if (randomnessPid != getpid()) {
-               randomnessPid = getpid();
-               sqlite3_randomness(0, 0);
-       }
-
-       memset(p, 0, sizeof(unixFile));
-
-       if (eType == SQLITE_OPEN_MAIN_DB) {
-               UnixUnusedFd *pUnused;
-               pUnused = findReusableFd(zName, flags);
-               if (pUnused) {
-                       fd = pUnused->fd;
-               } else {
-                       pUnused = sqlite3_malloc64(sizeof(*pUnused));
-                       if (!pUnused) {
-                               return SQLITE_NOMEM_BKPT;
-                       }
-               }
-               p->pUnused = pUnused;
-
-               /* Database filenames are double-zero terminated if they are not
-                * URIs with parameters.  Hence, they can always be passed into
-                * sqlite3_uri_parameter().
-                */
-               assert((flags & SQLITE_OPEN_URI)
-                      || zName[strlen(zName) + 1] == 0);
-
-       } else if (!zName) {
-               /* If zName is NULL, the upper layer is requesting a temp file. 
*/
-               assert(isDelete);
-               rc = unixGetTempname(pVfs->mxPathname, zTmpname);
-               if (rc != SQLITE_OK) {
-                       return rc;
-               }
-               zName = zTmpname;
-
-               /* Generated temporary filenames are always double-zero 
terminated
-                * for use by sqlite3_uri_parameter().
-                */
-               assert(zName[strlen(zName) + 1] == 0);
-       }
-
-       /* Determine the value of the flags parameter passed to POSIX function
-        * open(). These must be calculated even if open() is not called, as
-        * they may be stored as part of the file handle and used by the
-        * 'conch file' locking functions later on.
-        */
-       if (isReadonly)
-               openFlags |= O_RDONLY;
-       if (isReadWrite)
-               openFlags |= O_RDWR;
-       if (isCreate)
-               openFlags |= O_CREAT;
-       if (isExclusive)
-               openFlags |= (O_EXCL | O_NOFOLLOW);
-       openFlags |= (O_LARGEFILE | O_BINARY);
-
-       if (fd < 0) {
-               mode_t openMode;        /* Permissions to create file with */
-               uid_t uid;      /* Userid for the file */
-               gid_t gid;      /* Groupid for the file */
-               rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
-               if (rc != SQLITE_OK) {
-                       assert(!p->pUnused);
-                       return rc;
-               }
-               fd = robust_open(zName, openFlags, openMode);
-               assert(!isExclusive || (openFlags & O_CREAT) != 0);
-               if (fd < 0 && errno != EISDIR && isReadWrite) {
-                       /* Failed to open the file for read/write access. Try 
read-only. */
-                       flags &= ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
-                       openFlags &= ~(O_RDWR | O_CREAT);
-                       flags |= SQLITE_OPEN_READONLY;
-                       openFlags |= O_RDONLY;
-                       isReadonly = 1;
-                       fd = robust_open(zName, openFlags, openMode);
-               }
-               if (fd < 0) {
-                       rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
-                       goto open_finished;
-               }
-               
-       }
-       assert(fd >= 0);
-       if (pOutFlags) {
-               *pOutFlags = flags;
-       }
-
-       if (p->pUnused) {
-               p->pUnused->fd = fd;
-               p->pUnused->flags = flags;
-       }
-
-       if (isDelete) {
-
-#if defined(SQLITE_UNLINK_AFTER_CLOSE)
-               zPath = sqlite3_mprintf("%s", zName);
-               if (zPath == 0) {
-                       robust_close(p, fd, __LINE__);
-                       return SQLITE_NOMEM_BKPT;
-               }
-#else
-               osUnlink(zName);
-#endif
-       }
-#if SQLITE_ENABLE_LOCKING_STYLE
-       else {
-               p->openFlags = openFlags;
-       }
-#endif
-
-#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
-       if (fstatfs(fd, &fsInfo) == -1) {
-               storeLastErrno(p, errno);
-               robust_close(p, fd, __LINE__);
-               return SQLITE_IOERR_ACCESS;
-       }
-       if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
-               ((unixFile *) pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
-       }
-       if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
-               ((unixFile *) pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
-       }
-#endif
-
-       /* Set up appropriate ctrlFlags */
-       if (isDelete)
-               ctrlFlags |= UNIXFILE_DELETE;
-       if (isReadonly)
-               ctrlFlags |= UNIXFILE_RDONLY;
-       noLock = eType != SQLITE_OPEN_MAIN_DB;
-       if (noLock)
-               ctrlFlags |= UNIXFILE_NOLOCK;
-       if (syncDir)
-               ctrlFlags |= UNIXFILE_DIRSYNC;
-       if (flags & SQLITE_OPEN_URI)
-               ctrlFlags |= UNIXFILE_URI;
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-#if SQLITE_PREFER_PROXY_LOCKING
-       isAutoProxy = 1;
-#endif
-       if (isAutoProxy && (zPath != NULL) && (!noLock) && pVfs->xOpen) {
-               char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
-               int useProxy = 0;
-
-               /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 
0 means
-                * never use proxy, NULL means use proxy for non-local files 
only.
-                */
-               if (envforce != NULL) {
-                       useProxy = atoi(envforce) > 0;
-               } else {
-                       useProxy = !(fsInfo.f_flags & MNT_LOCAL);
-               }
-               if (useProxy) {
-                       rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
-                       if (rc == SQLITE_OK) {
-                               rc = proxyTransformUnixFile((unixFile *) pFile,
-                                                           ":auto:");
-                               if (rc != SQLITE_OK) {
-                                       /* Use unixClose to clean up the 
resources added in fillInUnixFile
-                                        * and clear all the structure's 
references.  Specifically,
-                                        * pFile->pMethods will be NULL so 
sqlite3OsClose will be a no-op
-                                        */
-                                       unixClose(pFile);
-                                       return rc;
-                               }
-                       }
-                       goto open_finished;
-               }
-       }
-#endif
-
-       rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
-
- open_finished:
-       if (rc != SQLITE_OK) {
-               sqlite3_free(p->pUnused);
-       }
-       return rc;
-}
-
-/*
- * Delete the file at zPath. If the dirSync argument is true, fsync()
- * the directory after deleting the file.
- */
-static int
-unixDelete(sqlite3_vfs * NotUsed,      /* VFS containing this as the xDelete 
method */
-          const char *zPath,   /* Name of file to be deleted */
-          int dirSync          /* If true, fsync() directory after deleting 
file */
-    )
-{
-       int rc = SQLITE_OK;
-       UNUSED_PARAMETER(NotUsed);
-       SimulateIOError(return SQLITE_IOERR_DELETE);
-       if (osUnlink(zPath) == (-1)) {
-               if (errno == ENOENT) {
-                       rc = SQLITE_IOERR_DELETE_NOENT;
-               } else {
-                       rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+       *pp = 0;
+
+#if SQLITE_MAX_MMAP_SIZE>0
+       if (pFd->mmapSizeMax > 0) {
+               if (pFd->pMapRegion == 0) {
+                       int rc = unixMapfile(pFd, -1);
+                       if (rc != SQLITE_OK)
+                               return rc;
                }
-               return rc;
-       }
-#ifndef SQLITE_DISABLE_DIRSYNC
-       if ((dirSync & 1) != 0) {
-               int fd;
-               rc = osOpenDirectory(zPath, &fd);
-               if (rc == SQLITE_OK) {
-                       if (full_fsync(fd, 0, 0)) {
-                               rc = unixLogError(SQLITE_IOERR_DIR_FSYNC,
-                                                 "fsync", zPath);
-                       }
-                       robust_close(0, fd, __LINE__);
-               } else {
-                       assert(rc == SQLITE_CANTOPEN);
-                       rc = SQLITE_OK;
+               if (pFd->mmapSize >= iOff + nAmt) {
+                       *pp = &((u8 *) pFd->pMapRegion)[iOff];
+                       pFd->nFetchOut++;
                }
        }
 #endif
-       return rc;
-}
-
-/*
- * Test the existence of or access permissions of file zPath. The
- * test performed depends on the value of flags:
- *
- *     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
- *     SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
- *     SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
- *
- * Otherwise return 0.
- */
-static int
-unixAccess(sqlite3_vfs * NotUsed,      /* The VFS containing this xAccess 
method */
-          const char *zPath,   /* Path of the file to examine */
-          int flags,           /* What do we want to learn about the zPath 
file? */
-          int *pResOut         /* Write result boolean here */
-    )
-{
-       UNUSED_PARAMETER(NotUsed);
-       SimulateIOError(return SQLITE_IOERR_ACCESS;
-           );
-       assert(pResOut != 0);
-
-       /* The spec says there are three possible values for flags.  But only
-        * two of them are actually used
-        */
-       assert(flags == SQLITE_ACCESS_EXISTS
-              || flags == SQLITE_ACCESS_READWRITE);
-
-       if (flags == SQLITE_ACCESS_EXISTS) {
-               struct stat buf;
-               *pResOut = (0 == osStat(zPath, &buf) && buf.st_size > 0);
-       } else {
-               *pResOut = osAccess(zPath, W_OK | R_OK) == 0;
-       }
-       return SQLITE_OK;
-}
-
-/*
- *
- */
-static int
-mkFullPathname(const char *zPath,      /* Input path */
-              char *zOut,      /* Output buffer */
-              int nOut         /* Allocated size of buffer zOut */
-    )
-{
-       int nPath = sqlite3Strlen30(zPath);
-       int iOff = 0;
-       if (zPath[0] != '/') {
-               if (osGetcwd(zOut, nOut - 2) == 0) {
-                       return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd",
-                                           zPath);
-               }
-               iOff = sqlite3Strlen30(zOut);
-               zOut[iOff++] = '/';
-       }
-       if ((iOff + nPath + 1) > nOut) {
-               /* SQLite assumes that xFullPathname() nul-terminates the 
output buffer
-                * even if it returns an error.
-                */
-               zOut[iOff] = '\0';
-               return SQLITE_CANTOPEN_BKPT;
-       }
-       sqlite3_snprintf(nOut - iOff, &zOut[iOff], "%s", zPath);
        return SQLITE_OK;
 }
 
 /*
- * Turn a relative pathname into a full pathname. The relative path
- * is stored as a nul-terminated string in the buffer pointed to by
- * zPath.
+ * If the third argument is non-NULL, then this function releases a
+ * reference obtained by an earlier call to unixFetch(). The second
+ * argument passed to this function must be the same as the corresponding
+ * argument that was passed to the unixFetch() invocation.
  *
- * zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
- * (in this case, MAX_PATHNAME bytes). The full-path is written to
- * this buffer before returning.
+ * Or, if the third argument is NULL, then this function is being called
+ * to inform the VFS layer that, according to POSIX, any existing mapping
+ * may now be invalid and should be unmapped.
  */
 static int
-unixFullPathname(sqlite3_vfs * pVfs,   /* Pointer to vfs object */
-                const char *zPath,     /* Possibly relative input path */
-                int nOut,      /* Size of output buffer in bytes */
-                char *zOut     /* Output buffer */
-    )
+unixUnfetch(sqlite3_file * fd, i64 iOff, void *p)
 {
-       (void)pVfs;
-#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
-       return mkFullPathname(zPath, zOut, nOut);
-#else
-       int rc = SQLITE_OK;
-       int nByte;
-       int nLink = 1;          /* Number of symbolic links followed so far */
-       const char *zIn = zPath;        /* Input path for each iteration of 
loop */
-       char *zDel = 0;
-
-       assert(pVfs->mxPathname == MAX_PATHNAME);
-       UNUSED_PARAMETER(pVfs);
+       unixFile *pFd = (unixFile *) fd;        /* The underlying database file 
*/
+       UNUSED_PARAMETER(iOff);
 
-       /* It's odd to simulate an io-error here, but really this is just
-        * using the io-error infrastructure to test that SQLite handles this
-        * function failing. This function could fail if, for example, the
-        * current working directory has been unlinked.
+       /* If p==0 (unmap the entire file) then there must be no outstanding
+        * xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
+        * then there must be at least one outstanding.
         */
-       SimulateIOError(return SQLITE_ERROR);
-
-       do {
-
-               /* Call stat() on path zIn. Set bLink to true if the path is a 
symbolic
-                * link, or false otherwise.
-                */
-               int bLink = 0;
-               struct stat buf;
-               if (osLstat(zIn, &buf) != 0) {
-                       if (errno != ENOENT) {
-                               rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat",
-                                                 zIn);
-                       }
-               } else {
-                       bLink = S_ISLNK(buf.st_mode);
-               }
-
-               if (bLink) {
-                       if (zDel == 0) {
-                               zDel = sqlite3_malloc(nOut);
-                               if (zDel == 0)
-                                       rc = SQLITE_NOMEM_BKPT;
-                       } else if (++nLink > SQLITE_MAX_SYMLINKS) {
-                               rc = SQLITE_CANTOPEN_BKPT;
-                       }
-
-                       if (rc == SQLITE_OK) {
-                               nByte = osReadlink(zIn, zDel, nOut - 1);
-                               if (nByte < 0) {
-                                       rc = unixLogError(SQLITE_CANTOPEN_BKPT,
-                                                         "readlink", zIn);
-                               } else {
-                                       if (zDel[0] != '/') {
-                                               int n;
-                                               for (n = sqlite3Strlen30(zIn);
-                                                    n > 0 && zIn[n - 1] != '/';
-                                                    n--) ;
-                                               if (nByte + n + 1 > nOut) {
-                                                       rc = 
SQLITE_CANTOPEN_BKPT;
-                                               } else {
-                                                       memmove(&zDel[n], zDel,
-                                                               nByte + 1);
-                                                       memcpy(zDel, zIn, n);
-                                                       nByte += n;
-                                               }
-                                       }
-                                       zDel[nByte] = '\0';
-                               }
-                       }
-
-                       zIn = zDel;
-               }
-
-               assert(rc != SQLITE_OK || zIn != zOut || zIn[0] == '/');
-               if (rc == SQLITE_OK && zIn != zOut) {
-                       rc = mkFullPathname(zIn, zOut, nOut);
-               }
-               if (bLink == 0)
-                       break;
-               zIn = zOut;
-       } while (rc == SQLITE_OK);
-
-       sqlite3_free(zDel);
-       return rc;
-#endif                         /* HAVE_READLINK && HAVE_LSTAT */
-}
+       assert((p == 0) == (pFd->nFetchOut == 0));
 
-/*
- * Write nBuf bytes of random data to the supplied buffer zBuf.
- */
-static int
-unixRandomness(sqlite3_vfs * NotUsed, int nBuf, char *zBuf)
-{
-       UNUSED_PARAMETER(NotUsed);
-       assert((size_t) nBuf >= (sizeof(time_t) + sizeof(int)));
+       /* If p!=0, it must match the iOff value. */
+       assert(p == 0 || p == &((u8 *) pFd->pMapRegion)[iOff]);
 
-       /* We have to initialize zBuf to prevent valgrind from reporting
-        * errors.  The reports issued by valgrind are incorrect - we would
-        * prefer that the randomness be increased by making use of the
-        * uninitialized space in zBuf - but valgrind errors tend to worry
-        * some users.  Rather than argue, it seems easier just to initialize
-        * the whole array and silence valgrind, even if that means less 
randomness
-        * in the random seed.
-        *
-        * When testing, initializing zBuf[] to zero is all we do.  That means
-        * that we always use the same random number sequence.  This makes the
-        * tests repeatable.
-        */
-       memset(zBuf, 0, nBuf);
-       randomnessPid = getpid();
-#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
-       {
-               int fd, got;
-               fd = robust_open("/dev/urandom", O_RDONLY, 0);
-               if (fd < 0) {
-                       time_t t;
-                       time(&t);
-                       memcpy(zBuf, &t, sizeof(t));
-                       memcpy(&zBuf[sizeof(t)], &randomnessPid,
-                              sizeof(randomnessPid));
-                       assert(sizeof(t) + sizeof(randomnessPid) <=
-                              (size_t) nBuf);
-                       nBuf = sizeof(t) + sizeof(randomnessPid);
-               } else {
-                       do {
-                               got = osRead(fd, zBuf, nBuf);
-                       } while (got < 0 && errno == EINTR);
-                       robust_close(0, fd, __LINE__);
-               }
+       if (p) {
+               pFd->nFetchOut--;
+       } else {
+               unixUnmapfile(pFd);
        }
-#endif
-       return nBuf;
-}
 
-/*
- * Sleep for a little while.  Return the amount of time slept.
- * The argument is the number of microseconds we want to sleep.
- * The return value is the number of microseconds of sleep actually
- * requested from the underlying operating system, a number which
- * might be greater than or equal to the argument, but not less
- * than the argument.
- */
-static int
-unixSleep(sqlite3_vfs * NotUsed, int microseconds)
-{
-#if defined(HAVE_USLEEP) && HAVE_USLEEP
-       usleep(microseconds);
-       UNUSED_PARAMETER(NotUsed);
-       return microseconds;
-#else
-       int seconds = (microseconds + 999999) / 1000000;
-       sleep(seconds);
-       UNUSED_PARAMETER(NotUsed);
-       return seconds * 1000000;
-#endif
+       assert(pFd->nFetchOut >= 0);
+       return SQLITE_OK;
 }
 
 /*
- * The following variable, if set to a non-zero value, is interpreted as
- * the number of seconds since 1970 and is used to set the result of
- * sqlite3OsCurrentTime() during testing.
- */
-#ifdef SQLITE_TEST
-int sql_current_time = 0;      /* Fake system time in seconds since 1970. */
-#endif
-
-/*
- * Find the current time (in Universal Coordinated Time).  Write into *piNow
- * the current time and date as a Julian Day number times 86_400_000.  In
- * other words, write into *piNow the number of milliseconds since the Julian
- * epoch of noon in Greenwich on November 24, 4714 B.C according to the
- * proleptic Gregorian calendar.
+ * Here ends the implementation of all sqlite3_file methods.
  *
- * On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date
- * cannot be found.
- */
-static int
-unixCurrentTimeInt64(sqlite3_vfs * NotUsed, sqlite3_int64 * piNow)
-{
-       static const sqlite3_int64 unixEpoch =
-           24405875 * (sqlite3_int64) 8640000;
-       int rc = SQLITE_OK;
-#if defined(NO_GETTOD)
-       time_t t;
-       time(&t);
-       *piNow = ((sqlite3_int64) t) * 1000 + unixEpoch;
-#else
-       struct timeval sNow;
-       (void)gettimeofday(&sNow, 0);   /* Cannot fail given valid arguments */
-       *piNow =
-           unixEpoch + 1000 * (sqlite3_int64) sNow.tv_sec +
-           sNow.tv_usec / 1000;
-#endif
-
-#ifdef SQLITE_TEST
-       if (sql_current_time) {
-               *piNow =
-                   1000 * (sqlite3_int64) sql_current_time + unixEpoch;
-       }
-#endif
-       UNUSED_PARAMETER(NotUsed);
-       return rc;
-}
-
-/*
- * The xGetLastError() method is designed to return a better
- * low-level error message when operating-system problems come up
- * during SQLite operation.  Only the integer return code is currently
- * used.
- */
-static int
-unixGetLastError(sqlite3_vfs * NotUsed, int NotUsed2, char *NotUsed3)
-{
-       UNUSED_PARAMETER(NotUsed);
-       UNUSED_PARAMETER(NotUsed2);
-       UNUSED_PARAMETER(NotUsed3);
-       return errno;
-}
-
-/*
- *********************** End of sqlite3_vfs methods ***************************
+ ********************* End sqlite3_file Methods *******************************
  *****************************************************************************/
 
-/******************************************************************************
- ************************* Begin Proxy Locking ********************************
- *
- * Proxy locking is a "uber-locking-method" in this sense:  It uses the
- * other locking methods on secondary lock files.  Proxy locking is a
- * meta-layer over top of the primitive locking implemented above.  For
- * this reason, the division that implements of proxy locking is deferred
- * until late in the file (here) after all of the other I/O methods have
- * been defined - so that the primitive locking methods are available
- * as services to help with the implementation of proxy locking.
- *
- ***
- *
- * The default locking schemes in SQLite use byte-range locks on the
- * database file to coordinate safe, concurrent access by multiple readers
- * and writers [http://sqlite.org/lockingv3.html].  The five file locking
- * states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
- * as POSIX read & write locks over fixed set of locations (via fsctl),
- * on AFP and SMB only exclusive byte-range locks are available via fsctl
- * with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
- * To simulate a F_RDLCK on the shared range, on AFP a randomly selected
- * address in the shared range is taken for a SHARED lock, the entire
- * shared range is taken for an EXCLUSIVE lock):
- *
- *      PENDING_BYTE        0x40000000
- *      RESERVED_BYTE       0x40000001
- *      SHARED_RANGE        0x40000002 -> 0x40000200
- *
- * This works well on the local file system, but shows a nearly 100x
- * slowdown in read performance on AFP because the AFP client disables
- * the read cache when byte-range locks are present.  Enabling the read
- * cache exposes a cache coherency problem that is present on all OS X
- * supported network file systems.  NFS and AFP both observe the
- * close-to-open semantics for ensuring cache coherency
- * [http://nfs.sourceforge.net/#faq_a8], which does not effectively
- * address the requirements for concurrent database access by multiple
- * readers and writers
- * [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
- *
- * To address the performance and cache coherency issues, proxy file locking
- * changes the way database access is controlled by limiting access to a
- * single host at a time and moving file locks off of the database file
- * and onto a proxy file on the local file system.
- *
- *
- * Using proxy locks
- * -----------------
- *
- * C APIs
- *
- *  sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE,
- *                       <proxy_path> | ":auto:");
- *  sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE,
- *                       &<proxy_path>);
- *
- *
- * SQL pragmas
- *
- *  PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
- *  PRAGMA [database.]lock_proxy_file
- *
- * Specifying ":auto:" means that if there is a conch file with a matching
- * host ID in it, the proxy path in the conch file will be used, otherwise
- * a proxy path based on the user's temp dir
- * (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
- * actual proxy file name is generated from the name and path of the
- * database file.  For example:
- *
- *       For database path "/Users/me/foo.db"
- *       The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
- *
- * Once a lock proxy is configured for a database connection, it can not
- * be removed, however it may be switched to a different proxy path via
- * the above APIs (assuming the conch file is not being held by another
- * connection or process).
- *
- *
- * How proxy locking works
- * -----------------------
- *
- * Proxy file locking relies primarily on two new supporting files:
- *
- *   *  conch file to limit access to the database file to a single host
- *      at a time
- *
- *   *  proxy file to act as a proxy for the advisory locks normally
- *      taken on the database
- *
- * The conch file - to use a proxy file, sqlite must first "hold the conch"
- * by taking an sqlite-style shared lock on the conch file, reading the
- * contents and comparing the host's unique host ID (see below) and lock
- * proxy path against the values stored in the conch.  The conch file is
- * stored in the same directory as the database file and the file name
- * is patterned after the database file name as ".<databasename>-conch".
- * If the conch file does not exist, or its contents do not match the
- * host ID and/or proxy path, then the lock is escalated to an exclusive
- * lock and the conch file contents is updated with the host ID and proxy
- * path and the lock is downgraded to a shared lock again.  If the conch
- * is held by another process (with a shared lock), the exclusive lock
- * will fail and SQLITE_BUSY is returned.
- *
- * The proxy file - a single-byte file used for all advisory file locks
- * normally taken on the database file.   This allows for safe sharing
- * of the database file for multiple readers and writers on the same
- * host (the conch ensures that they all use the same local lock file).
- *
- * Requesting the lock proxy does not immediately take the conch, it is
- * only taken when the first request to lock database file is made.
- * This matches the semantics of the traditional locking behavior, where
- * opening a connection to a database file does not take a lock on it.
- * The shared lock and an open file descriptor are maintained until
- * the connection to the database is closed.
- *
- * The proxy file and the lock file are never deleted so they only need
- * to be created the first time they are used.
- *
- * Configuration options
- * ---------------------
+/*
+ * This division contains definitions of sqlite3_io_methods objects that
+ * implement various file locking strategies.  It also contains definitions
+ * of "finder" functions.  A finder-function is used to locate the appropriate
+ * sqlite3_io_methods object for a particular database file.  The pAppData
+ * field of the sqlite3_vfs VFS objects are initialized to be pointers to
+ * the correct finder-function for that VFS.
  *
- *  SQLITE_PREFER_PROXY_LOCKING
+ * Most finder functions return a pointer to a fixed sqlite3_io_methods
+ * object.  The only interesting finder-function is autolockIoFinder, which
+ * looks at the filesystem type and tries to guess the best locking
+ * strategy from that.
  *
- *       Database files accessed on non-local file systems are
- *       automatically configured for proxy locking, lock files are
- *       named automatically using the same logic as
- *       PRAGMA lock_proxy_file=":auto:"
+ * For finder-function F, two objects are created:
  *
- *  SQLITE_PROXY_DEBUG
+ *    (1) The real finder-function named "FImpt()".
  *
- *       Enables the logging of error messages during host id file
- *       retrieval and creation
+ *    (2) A constant pointer to this function named just "F".
  *
- *  LOCKPROXYDIR
  *
- *       Overrides the default directory used for lock proxy files that
- *       are named automatically via the ":auto:" setting
+ * A pointer to the F pointer is used as the pAppData value for VFS
+ * objects.  We have to do this instead of letting pAppData point
+ * directly at the finder-function since C90 rules prevent a void*
+ * from be cast into a function pointer.
  *
- *  SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
  *
- *       Permissions to use when creating a directory for storing the
- *       lock proxy files, only used when LOCKPROXYDIR is not set.
+ * Each instance of this macro generates two objects:
  *
+ *   *  A constant sqlite3_io_methods object call METHOD that has locking
+ *      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
  *
- * As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
- * setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
- * force proxy locking to be used for every database file opened, and 0
- * will force automatic proxy locking to be disabled for all database
- * files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or
- * sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
+ *   *  An I/O method finder function called FINDER that returns a pointer
+ *      to the METHOD object in the previous bullet.
  */
+#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE)     \
+static const sqlite3_io_methods METHOD = {                                   \
+   VERSION,                    /* iVersion */                                \
+   CLOSE,                      /* xClose */                                  \
+   unixRead,                   /* xRead */                                   \
+   unixWrite,                  /* xWrite */                                  \
+   unixFileControl,            /* xFileControl */                            \
+   unixFetch,                  /* xFetch */                                  \
+   unixUnfetch,                /* xUnfetch */                                \
+};                                                                           \
+static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
+  UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
+  return &METHOD;                                                            \
+}                                                                            \
+static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
+    = FINDER##Impl;
 
 /*
- * Proxy locking is only available on MacOSX
+ * Here are all of the sqlite3_io_methods objects for each of the
+ * locking strategies.  Functions that return pointers to these methods
+ * are also created.
  */
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
+IOMETHODS(posixIoFinder,       /* Finder function name */
+         posixIoMethods,       /* sqlite3_io_methods object name */
+         3,                    /* shared memory and mmap are enabled */
+         unixClose             /* xClose method */
+    )
+    IOMETHODS(nolockIoFinder,  /* Finder function name */
+             nolockIoMethods,  /* sqlite3_io_methods object name */
+             3,                /* shared memory is disabled */
+             nolockClose       /* xClose method */
+    )
 
 /*
- * The proxyLockingContext has the path and file structures for the remote
- * and local proxy files in it
+ * An abstract type for a pointer to an IO method finder function:
+ */
+typedef const sqlite3_io_methods *(*finder_type) (const char *, unixFile *);
+
+/****************************************************************************
+ *************************** sqlite3_vfs methods ****************************
+ *
+ * This division contains the implementation of methods on the
+ * sqlite3_vfs object.
  */
-typedef struct proxyLockingContext proxyLockingContext;
-struct proxyLockingContext {
-       unixFile *conchFile;    /* Open conch file */
-       char *conchFilePath;    /* Name of the conch file */
-       unixFile *lockProxy;    /* Open proxy lock file */
-       char *lockProxyPath;    /* Name of the proxy lock file */
-       char *dbPath;           /* Name of the open file */
-       int conchHeld;          /* 1 if the conch is held, -1 if lockless */
-       int nFails;             /* Number of conch taking failures */
-       void *oldLockingContext;        /* Original lockingcontext to restore 
on close */
-       sqlite3_io_methods const *pOldMethod;   /* Original I/O methods for 
close */
-};
 
 /*
- * The proxy lock file path for the database at dbPath is written into lPath,
- * which must point to valid, writable memory large enough for a maxLen length
- * file path.
+ * Initialize the contents of the unixFile structure pointed to by pId.
  */
 static int
-proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen)
+fillInUnixFile(sqlite3_vfs * pVfs,     /* Pointer to vfs object */
+              int h,           /* Open file descriptor of file being opened */
+              sqlite3_file * pId,      /* Write to the unixFile structure here 
*/
+              const char *zFilename,   /* Name of the file being opened */
+              int ctrlFlags    /* Zero or more UNIXFILE_* values */
+    )
 {
-       int len;
-       int dbLen;
-       int i;
-
-#ifdef LOCKPROXYDIR
-       len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
-#else
-#ifdef _CS_DARWIN_USER_TEMP_DIR
-       {
-               if (!confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen)) {
-                       return SQLITE_IOERR_LOCK;
-               }
-               len = strlcat(lPath, "sqliteplocks", maxLen);
-       }
-#else
-       len = strlcpy(lPath, "/tmp/", maxLen);
-#endif
+       const sqlite3_io_methods *pLockingStyle;
+       unixFile *pNew = (unixFile *) pId;
+       int rc = SQLITE_OK;
+
+       assert(pNew->pInode == NULL);
+
+       /* Usually the path zFilename should not be a relative pathname. The
+        * exception is when opening the proxy "conch" file in builds that
+        * include the special Apple locking styles.
+        */
+       assert(zFilename == 0 || zFilename[0] == '/');
+
+       /* No locking occurs in temporary files */
+       assert(zFilename != 0 || (ctrlFlags & UNIXFILE_NOLOCK) != 0);
+
+       pNew->h = h;
+       pNew->pVfs = pVfs;
+       pNew->zPath = zFilename;
+       pNew->ctrlFlags = (u8) ctrlFlags;
+#if SQLITE_MAX_MMAP_SIZE>0
+       pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
 #endif
+       if (strcmp(pVfs->zName, "unix-excl") == 0) {
+               pNew->ctrlFlags |= UNIXFILE_EXCL;
+       }
+       if (ctrlFlags & UNIXFILE_NOLOCK) {
+               pLockingStyle = &nolockIoMethods;
+       } else {
+               pLockingStyle =
+                   (**(finder_type *) pVfs->pAppData) (zFilename, pNew);
+               assert(pLockingStyle == &posixIoMethods);
+       }
 
-       if (lPath[len - 1] != '/') {
-               len = strlcat(lPath, "/", maxLen);
+       if (pLockingStyle == &posixIoMethods) {
+               rc = findInodeInfo(pNew, &pNew->pInode);
+               if (rc != SQLITE_OK) {
+                       /* If an error occurred in findInodeInfo(), close the 
file descriptor
+                        * immediately. findInodeInfo() may fail
+                        * in two scenarios:
+                        *
+                        *   (a) A call to fstat() failed.
+                        *   (b) A malloc failed.
+                        *
+                        * Scenario (b) may only occur if the process is 
holding no other
+                        * file descriptors open on the same file. If there 
were other file
+                        * descriptors on this file, then no malloc would be 
required by
+                        * findInodeInfo(). If this is the case, it is quite 
safe to close
+                        * handle h - as it is guaranteed that no posix locks 
will be released
+                        * by doing so.
+                        *
+                        * If scenario (a) caused the error then things are not 
so safe. The
+                        * implicit assumption here is that if fstat() fails, 
things are in
+                        * such bad shape that dropping a lock or two doesn't 
matter much.
+                        */
+                       robust_close(pNew, h, __LINE__);
+                       h = -1;
+               }
+       }
+       storeLastErrno(pNew, 0);
+       if (rc != SQLITE_OK) {
+               if (h >= 0)
+                       robust_close(pNew, h, __LINE__);
+       } else {
+               pNew->pMethod = pLockingStyle;
+               OpenCounter(+1);
+               verifyDbFile(pNew);
        }
+       return rc;
+}
+
+/*
+ * Return the name of a directory in which to put temporary files.
+ * If no suitable temporary file directory can be found, return NULL.
+ */
+static const char *
+unixTempFileDir(void)
+{
+       static const char *azDirs[] = {
+               0,
+               0,
+               "/var/tmp",
+               "/usr/tmp",
+               "/tmp",
+               "."
+       };
+       unsigned int i = 0;
+       struct stat buf;
+       const char *zDir = sqlite3_temp_directory;
 
-       /* transform the db path to a unique cache name */
-       dbLen = (int)strlen(dbPath);
-       for (i = 0; i < dbLen && (i + len + 7) < (int)maxLen; i++) {
-               char c = dbPath[i];
-               lPath[i + len] = (c == '/') ? '_' : c;
+       if (!azDirs[0])
+               azDirs[0] = getenv("SQLITE_TMPDIR");
+       if (!azDirs[1])
+               azDirs[1] = getenv("TMPDIR");
+       while (1) {
+               if (zDir != 0 && stat(zDir, &buf) == 0 &&
+                   S_ISDIR(buf.st_mode) && access(zDir, 03) == 0)
+                       return zDir;
+               if (i >= sizeof(azDirs) / sizeof(azDirs[0]))
+                       break;
+               zDir = azDirs[i++];
        }
-       lPath[i + len] = '\0';
-       strlcat(lPath, ":auto:", maxLen);
-       return SQLITE_OK;
+       return 0;
 }
 
 /*
- ** Creates the lock file and any missing directories in lockPath
+ * Create a temporary file name in zBuf.  zBuf must be allocated
+ * by the calling process and must be big enough to hold at least
+ * pVfs->mxPathname bytes.
  */
 static int
-proxyCreateLockPath(const char *lockPath)
+unixGetTempname(int nBuf, char *zBuf)
 {
-       int i, len;
-       char buf[MAXPATHLEN];
-       int start = 0;
-
-       assert(lockPath != NULL);
-       /* try to create all the intermediate directories */
-       len = (int)strlen(lockPath);
-       buf[0] = lockPath[0];
-       for (i = 1; i < len; i++) {
-               if (lockPath[i] == '/' && (i - start > 0)) {
-                       /* only mkdir if leaf dir != "." or "/" or ".." */
-                       if (i - start > 2
-                           || (i - start == 1 && buf[start] != '.'
-                               && buf[start] != '/')
-                           || (i - start == 2 && buf[start] != '.'
-                               && buf[start + 1] != '.')) {
-                               buf[i] = '\0';
-                               if (osMkdir
-                                   (buf,
-                                    SQLITE_DEFAULT_PROXYDIR_PERMISSIONS)) {
-                                       int err = errno;
-                                       if (err != EEXIST) {
-                                               return err;
-                                       }
-                               }
-                       }
-                       start = i + 1;
-               }
-               buf[i] = lockPath[i];
-       }
+       const char *zDir;
+       int iLimit = 0;
 
-       return 0;
+       /* It's odd to simulate an io-error here, but really this is just
+        * using the io-error infrastructure to test that SQLite handles this
+        * function failing.
+        */
+       zBuf[0] = 0;
+       SimulateIOError(return SQLITE_IOERR);
+
+       zDir = unixTempFileDir();
+       if (zDir == 0)
+               return SQLITE_IOERR_GETTEMPPATH;
+       do {
+               u64 r;
+               sqlite3_randomness(sizeof(r), &r);
+               assert(nBuf > 2);
+               zBuf[nBuf - 2] = 0;
+               sqlite3_snprintf(nBuf, zBuf,
+                                "%s/" SQLITE_TEMP_FILE_PREFIX "%llx%c", zDir,
+                                r, 0);
+               if (zBuf[nBuf - 2] != 0 || (iLimit++) > 10)
+                       return SQLITE_ERROR;
+       } while (access(zBuf, 0) == 0);
+       return SQLITE_OK;
 }
 
 /*
- * Create a new VFS file descriptor (stored in memory obtained from
- * sqlite3_malloc) and open the file named "path" in the file descriptor.
+ * Search for an unused file descriptor that was opened on the database
+ * file (not a journal or master-journal file) identified by pathname
+ * zPath with SQLITE_OPEN_XXX flags matching those passed as the second
+ * argument to this function.
+ *
+ * Such a file descriptor may exist if a database connection was closed
+ * but the associated file descriptor could not be closed because some
+ * other file descriptor open on the same file is holding a file-lock.
+ * Refer to comments in the unixClose() function and the lengthy comment
+ * describing "Posix Advisory Locking" at the start of this file for
+ * further details. Also, ticket #4018.
  *
- * The caller is responsible not only for closing the file descriptor
- * but also for freeing the memory associated with the file descriptor.
+ * If a suitable file descriptor is found, then it is returned. If no
+ * such file descriptor is located, -1 is returned.
  */
-static int
-proxyCreateUnixFile(const char *path,  /* path for the new unixFile */
-                   unixFile ** ppFile, /* unixFile created and returned by ref 
*/
-                   int islockfile      /* if non zero missing dirs will be 
created */
-    )
+static UnixUnusedFd *
+findReusableFd(const char *zPath, int flags)
 {
-       int fd = -1;
-       unixFile *pNew;
-       int rc = SQLITE_OK;
-       int openFlags = O_RDWR | O_CREAT;
-       sqlite3_vfs dummyVfs;
-       int terrno = 0;
-       UnixUnusedFd *pUnused = NULL;
-
-       /* 1. first try to open/create the file
-        * 2. if that fails, and this is a lock file (not-conch), try creating
-        * the parent directories and then try again.
-        * 3. if that fails, try to open the file read-only
-        * otherwise return BUSY (if lock file) or CANTOPEN for the conch file
+       UnixUnusedFd *pUnused = 0;
+
+       struct stat sStat;      /* Results of stat() call */
+
+       /* A stat() call may fail for various reasons. If this happens, it is
+        * almost certain that an open() call on the same path will also fail.
+        * For this reason, if an error occurs in the stat() call here, it is
+        * ignored and -1 is returned. The caller will try to open a new file
+        * descriptor on the same path, fail, and return an error to SQLite.
+        *
+        * Even if a subsequent open() call does succeed, the consequences of
+        * not searching for a reusable file descriptor are not dire.
         */
-       pUnused = findReusableFd(path, openFlags);
-       if (pUnused) {
-               fd = pUnused->fd;
-       } else {
-               pUnused = sqlite3_malloc64(sizeof(*pUnused));
-               if (!pUnused) {
-                       return SQLITE_NOMEM_BKPT;
+       if (0 == stat(zPath, &sStat)) {
+               unixInodeInfo *pInode;
+
+               pInode = inodeList;
+               while (pInode && (pInode->fileId.dev != sStat.st_dev
+                                 || pInode->fileId.ino !=
+                                 (u64) sStat.st_ino)) {
+                       pInode = pInode->pNext;
                }
-       }
-       if (fd < 0) {
-               fd = robust_open(path, openFlags, 0);
-               terrno = errno;
-               if (fd < 0 && errno == ENOENT && islockfile) {
-                       if (proxyCreateLockPath(path) == SQLITE_OK) {
-                               fd = robust_open(path, openFlags, 0);
+               if (pInode) {
+                       UnixUnusedFd **pp;
+                       for (pp = &pInode->pUnused;
+                            *pp && (*pp)->flags != flags;
+                            pp = &((*pp)->pNext)) ;
+                       pUnused = *pp;
+                       if (pUnused) {
+                               *pp = pUnused->pNext;
                        }
                }
        }
-       if (fd < 0) {
-               openFlags = O_RDONLY;
-               fd = robust_open(path, openFlags, 0);
-               terrno = errno;
-       }
-       if (fd < 0) {
-               if (islockfile) {
-                       return SQLITE_BUSY;
-               }
-               switch (terrno) {
-               case EACCES:
-                       return SQLITE_PERM;
-               case EIO:
-                       return SQLITE_IOERR_LOCK;       /* even though it is 
the conch */
-               default:
-                       return SQLITE_CANTOPEN_BKPT;
-               }
-       }
-
-       pNew = (unixFile *) sqlite3_malloc64(sizeof(*pNew));
-       if (pNew == NULL) {
-               rc = SQLITE_NOMEM_BKPT;
-               goto end_create_proxy;
-       }
-       memset(pNew, 0, sizeof(unixFile));
-       pNew->openFlags = openFlags;
-       memset(&dummyVfs, 0, sizeof(dummyVfs));
-       dummyVfs.pAppData = (void *)&autolockIoFinder;
-       dummyVfs.zName = "dummy";
-       pUnused->fd = fd;
-       pUnused->flags = openFlags;
-       pNew->pUnused = pUnused;
-
-       rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file *) pNew, path, 0);
-       if (rc == SQLITE_OK) {
-               *ppFile = pNew;
-               return SQLITE_OK;
-       }
- end_create_proxy:
-       robust_close(pNew, fd, __LINE__);
-       sqlite3_free(pNew);
-       sqlite3_free(pUnused);
-       return rc;
+       return pUnused;
 }
 
-#ifdef SQLITE_TEST
-/* simulate multiple hosts by creating unique hostid file paths */
-int sqlite3_hostid_num = 0;
-#endif
-
-#define PROXY_HOSTIDLEN    16  /* conch file host id length */
-
-#ifdef HAVE_GETHOSTUUID
-/* Not always defined in the headers as it ought to be */
-extern int gethostuuid(uuid_t id, const struct timespec *wait);
-#endif
-
-/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
- * bytes of writable memory.
+/*
+ * Find the mode, uid and gid of file zFile.
  */
 static int
-proxyGetHostID(unsigned char *pHostID, int *pError)
+getFileMode(const char *zFile, /* File name */
+           mode_t * pMode,     /* OUT: Permissions of zFile */
+           uid_t * pUid,       /* OUT: uid of zFile. */
+           gid_t * pGid        /* OUT: gid of zFile. */
+    )
 {
-       assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
-       memset(pHostID, 0, PROXY_HOSTIDLEN);
-#ifdef HAVE_GETHOSTUUID
-       {
-               struct timespec timeout = { 1, 0 };     /* 1 sec timeout */
-               if (gethostuuid(pHostID, &timeout)) {
-                       int err = errno;
-                       if (pError) {
-                               *pError = err;
-                       }
-                       return SQLITE_IOERR;
-               }
-       }
-#else
-       UNUSED_PARAMETER(pError);
-#endif
-#ifdef SQLITE_TEST
-       /* simulate multiple hosts by creating unique hostid file paths */
-       if (sqlite3_hostid_num != 0) {
-               pHostID[0] =
-                   (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
+       struct stat sStat;      /* Output of stat() on database file */
+       int rc = SQLITE_OK;
+       if (0 == stat(zFile, &sStat)) {
+               *pMode = sStat.st_mode & 0777;
+               *pUid = sStat.st_uid;
+               *pGid = sStat.st_gid;
+       } else {
+               rc = SQLITE_IOERR_FSTAT;
        }
-#endif
-
-       return SQLITE_OK;
+       return rc;
 }
 
-/* The conch file contains the header, host id and lock file path
- */
-#define PROXY_CONCHVERSION 2   /* 1-byte header, 16-byte host id, path */
-#define PROXY_HEADERLEN    1   /* conch file header length */
-#define PROXY_PATHINDEX    (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
-#define PROXY_MAXCONCHLEN  (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
-
 /*
- * Takes an open conch file, copies the contents to a new path and then moves
- * it back.  The newly created file's file descriptor is assigned to the
- * conch file structure and finally the original conch file descriptor is
- * closed.  Returns zero if successful.
+ * This function is called by unixOpen() to determine the unix permissions
+ * to create new files with. If no error occurs, then SQLITE_OK is returned
+ * and a value suitable for passing as the third argument to open(2) is
+ * written to *pMode. If an IO error occurs, an SQLite error code is
+ * returned and the value of *pMode is not modified.
+ *
+ * In most cases, this routine sets *pMode to 0, which will become
+ * an indication to robust_open() to create the file using
+ * SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
+ * But if the file being opened is a regular journal file, then
+ * this function queries the file-system for the permissions on the
+ * corresponding database file and sets *pMode to this value. Whenever
+ * possible, journal files are created using the same permissions
+ * as the associated database file.
+ *
+ * If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
+ * original filename is unavailable.  But 8_3_NAMES is only used for
+ * FAT filesystems and permissions do not matter there, so just use
+ * the default permissions.
  */
 static int
-proxyBreakConchLock(unixFile * pFile, uuid_t myHostID)
+findCreateFileMode(const char *zPath,  /* Path of file (possibly) being 
created */
+                  int flags,   /* Flags passed as 4th argument to xOpen() */
+                  mode_t * pMode,      /* OUT: Permissions to open file with */
+                  uid_t * pUid,        /* OUT: uid to set on the file */
+                  gid_t * pGid /* OUT: gid to set on the file */
+    )
 {
-       proxyLockingContext *pCtx =
-           (proxyLockingContext *) pFile->lockingContext;
-       unixFile *conchFile = pCtx->conchFile;
-       char tPath[MAXPATHLEN];
-       char buf[PROXY_MAXCONCHLEN];
-       char *cPath = pCtx->conchFilePath;
-       size_t readLen = 0;
-       size_t pathLen = 0;
-       char errmsg[64] = "";
-       int fd = -1;
-       int rc = -1;
-       UNUSED_PARAMETER(myHostID);
-
-       /* create a new path by replace the trailing '-conch' with '-break' */
-       pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
-       if (pathLen > MAXPATHLEN || pathLen < 6 ||
-           (strlcpy(&tPath[pathLen - 5], "break", 6) != 5)) {
-               sqlite3_snprintf(sizeof(errmsg), errmsg, "path error (len %d)",
-                                (int)pathLen);
-               goto end_breaklock;
-       }
-       /* read the conch content */
-       readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
-       if (readLen < PROXY_PATHINDEX) {
-               sqlite3_snprintf(sizeof(errmsg), errmsg, "read error (len %d)",
-                                (int)readLen);
-               goto end_breaklock;
-       }
-       /* write it out to the temporary break file */
-       fd = robust_open(tPath, (O_RDWR | O_CREAT | O_EXCL), 0);
-       if (fd < 0) {
-               sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)",
-                                errno);
-               goto end_breaklock;
-       }
-       if (osPwrite(fd, buf, readLen, 0) != (ssize_t) readLen) {
-               sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)",
-                                errno);
-               goto end_breaklock;
-       }
-       if (rename(tPath, cPath)) {
-               sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)",
-                                errno);
-               goto end_breaklock;
-       }
-       rc = 0;
-       fprintf(stderr, "broke stale lock on %s\n", cPath);
-       robust_close(pFile, conchFile->h, __LINE__);
-       conchFile->h = fd;
-       conchFile->openFlags = O_RDWR | O_CREAT;
-
- end_breaklock:
-       if (rc) {
-               if (fd >= 0) {
-                       osUnlink(tPath);
-                       robust_close(pFile, fd, __LINE__);
+       int rc = SQLITE_OK;     /* Return Code */
+       *pMode = 0;
+       *pUid = 0;
+       *pGid = 0;
+       if (flags & SQLITE_OPEN_DELETEONCLOSE) {
+               *pMode = 0600;
+       } else if (flags & SQLITE_OPEN_URI) {
+               /* If this is a main database file and the file was opened 
using a URI
+                * filename, check for the "modeof" parameter. If present, 
interpret
+                * its value as a filename and try to copy the mode, uid and 
gid from
+                * that file.
+                */
+               const char *z = sqlite3_uri_parameter(zPath, "modeof");
+               if (z) {
+                       rc = getFileMode(z, pMode, pUid, pGid);
                }
-               fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath,
-                       errmsg);
        }
        return rc;
 }
 
-/* Take the requested lock on the conch file and break a stale lock if the
- * host id matches.
+/*
+ * Open the file zPath.
+ *
+ * Previously, the SQLite OS layer used three functions in place of this
+ * one:
+ *
+ *     sqlite3OsOpenReadWrite();
+ *     sqlite3OsOpenReadOnly();
+ *     sqlite3OsOpenExclusive();
+ *
+ * These calls correspond to the following combinations of flags:
+ *
+ *     ReadWrite() ->     (READWRITE | CREATE)
+ *     ReadOnly()  ->     (READONLY)
+ *     OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
+ *
+ * The old OpenExclusive() accepted a boolean argument - "delFlag". If
+ * true, the file was configured to be automatically deleted when the
+ * file handle closed. To achieve the same effect using this new
+ * interface, add the DELETEONCLOSE flag to those specified above for
+ * OpenExclusive().
  */
 static int
-proxyConchLock(unixFile * pFile, uuid_t myHostID, int lockType)
+unixOpen(sqlite3_vfs * pVfs,   /* The VFS for which this is the xOpen method */
+        const char *zPath,     /* Pathname of file to be opened */
+        sqlite3_file * pFile,  /* The file descriptor to be filled in */
+        int flags,             /* Input flags to control the opening */
+        int *pOutFlags         /* Output flags returned to SQLite core */
+    )
 {
-       proxyLockingContext *pCtx =
-           (proxyLockingContext *) pFile->lockingContext;
-       unixFile *conchFile = pCtx->conchFile;
-       int rc = SQLITE_OK;
-       int nTries = 0;
-       struct timespec conchModTime;
-
-       memset(&conchModTime, 0, sizeof(conchModTime));
-       do {
-               rc = conchFile->pMethod->xLock((sqlite3_file *) conchFile,
-                                              lockType);
-               nTries++;
-               if (rc == SQLITE_BUSY) {
-                       /* If the lock failed (busy):
-                        * 1st try: get the mod time of the conch, wait 0.5s 
and try again.
-                        * 2nd try: fail if the mod time changed or host id is 
different, wait
-                        *           10 sec and try again
-                        * 3rd try: break the lock unless the mod time has 
changed.
-                        */
-                       struct stat buf;
-                       if (osFstat(conchFile->h, &buf)) {
-                               storeLastErrno(pFile, errno);
-                               return SQLITE_IOERR_LOCK;
-                       }
-
-                       if (nTries == 1) {
-                               conchModTime = buf.st_mtimespec;
-                               usleep(500000); /* wait 0.5 sec and try the 
lock again */
-                               continue;
-                       }
+       unixFile *p = (unixFile *) pFile;
+       int fd = -1;            /* File descriptor returned by open() */
+       int openFlags = 0;      /* Flags to pass to open() */
+       int eType = flags & 0xFFFFFF00; /* Type of file to open */
+       int noLock;             /* True to omit locking primitives */
+       int rc;                 /* Function Return Code */
+       int ctrlFlags = 0;      /* UNIXFILE_* flags */
 
-                       assert(nTries > 1);
-                       if (conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
-                           conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec) {
-                               return SQLITE_BUSY;
-                       }
+       int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
+       int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
+       int isCreate = (flags & SQLITE_OPEN_CREATE);
+       int isReadonly = (flags & SQLITE_OPEN_READONLY);
+       int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
 
-                       if (nTries == 2) {
-                               char tBuf[PROXY_MAXCONCHLEN];
-                               int len =
-                                   osPread(conchFile->h, tBuf,
-                                           PROXY_MAXCONCHLEN, 0);
-                               if (len < 0) {
-                                       storeLastErrno(pFile, errno);
-                                       return SQLITE_IOERR_LOCK;
-                               }
-                               if (len > PROXY_PATHINDEX
-                                   && tBuf[0] == (char)PROXY_CONCHVERSION) {
-                                       /* don't break the lock if the host id 
doesn't match */
-                                       if (0 !=
-                                           memcmp(&tBuf[PROXY_HEADERLEN],
-                                                  myHostID, PROXY_HOSTIDLEN)) {
-                                               return SQLITE_BUSY;
-                                       }
-                               } else {
-                                       /* don't break the lock on short read 
or a version mismatch */
-                                       return SQLITE_BUSY;
-                               }
-                               usleep(10000000);       /* wait 10 sec and try 
the lock again */
-                               continue;
-                       }
+       /* If creating a master or main-file journal, this function will open
+        * a file-descriptor on the directory too. The first time unixSync()
+        * is called the directory file descriptor will be fsync()ed and 
close()d.
+        */
+       int syncDir = isCreate;
 
-                       assert(nTries == 3);
-                       if (0 == proxyBreakConchLock(pFile, myHostID)) {
-                               rc = SQLITE_OK;
-                               if (lockType == EXCLUSIVE_LOCK) {
-                                       rc = conchFile->pMethod->
-                                           xLock((sqlite3_file *) conchFile,
-                                                 SHARED_LOCK);
-                               }
-                               if (!rc) {
-                                       rc = conchFile->pMethod->
-                                           xLock((sqlite3_file *) conchFile,
-                                                 lockType);
-                               }
-                       }
-               }
-       } while (rc == SQLITE_BUSY && nTries < 3);
+       /* If argument zPath is a NULL pointer, this function is required to 
open
+        * a temporary file. Use this buffer to store the file name in.
+        */
+       char zTmpname[MAX_PATHNAME + 2];
+       const char *zName = zPath;
 
-       return rc;
-}
+       /* Check the following statements are true:
+        *
+        *   (a) Exactly one of the READWRITE and READONLY flags must be set, 
and
+        *   (b) if CREATE is set, then READWRITE must also be set, and
+        *   (c) if EXCLUSIVE is set, then CREATE must also be set.
+        *   (d) if DELETEONCLOSE is set, then CREATE must also be set.
+        */
+       assert((isReadonly == 0 || isReadWrite == 0)
+              && (isReadWrite || isReadonly));
+       assert(isCreate == 0 || isReadWrite);
+       assert(isExclusive == 0 || isCreate);
+       assert(isDelete == 0 || isCreate);
 
-/* Takes the conch by taking a shared lock and read the contents conch, if
- * lockPath is non-NULL, the host ID and lock file path must match.  A NULL
- * lockPath means that the lockPath in the conch file will be used if the
- * host IDs match, or a new lock path will be generated automatically
- * and written to the conch file.
- */
-static int
-proxyTakeConch(unixFile * pFile)
-{
-       proxyLockingContext *pCtx =
-           (proxyLockingContext *) pFile->lockingContext;
+       /* Detect a pid change and reset the PRNG.  There is a race condition
+        * here such that two or more threads all trying to open databases at
+        * the same instant might all reset the PRNG.  But multiple resets
+        * are harmless.
+        */
+       if (randomnessPid != getpid()) {
+               randomnessPid = getpid();
+               sqlite3_randomness(0, 0);
+       }
 
-       if (pCtx->conchHeld != 0) {
-               return SQLITE_OK;
-       } else {
-               unixFile *conchFile = pCtx->conchFile;
-               uuid_t myHostID;
-               int pError = 0;
-               char readBuf[PROXY_MAXCONCHLEN];
-               char lockPath[MAXPATHLEN];
-               char *tempLockPath = NULL;
-               int rc = SQLITE_OK;
-               int createConch = 0;
-               int hostIdMatch = 0;
-               int readLen = 0;
-               int tryOldLockPath = 0;
-               int forceNewLockPath = 0;
-
-               rc = proxyGetHostID(myHostID, &pError);
-               if ((rc & 0xff) == SQLITE_IOERR) {
-                       storeLastErrno(pFile, pError);
-                       goto end_takeconch;
-               }
-               rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
-               if (rc != SQLITE_OK) {
-                       goto end_takeconch;
-               }
-               /* read the existing conch file */
-               readLen =
-                   seekAndRead((unixFile *) conchFile, 0, readBuf,
-                               PROXY_MAXCONCHLEN);
-               if (readLen < 0) {
-                       /* I/O error: lastErrno set by seekAndRead */
-                       storeLastErrno(pFile, conchFile->lastErrno);
-                       rc = SQLITE_IOERR_READ;
-                       goto end_takeconch;
-               } else if (readLen <= (PROXY_HEADERLEN + PROXY_HOSTIDLEN) ||
-                          readBuf[0] != (char)PROXY_CONCHVERSION) {
-                       /* a short read or version format mismatch means we 
need to create a new
-                        * conch file.
-                        */
-                       createConch = 1;
-               }
-               /* if the host id matches and the lock path already exists in 
the conch
-                * we'll try to use the path there, if we can't open that path, 
we'll
-                * retry with a new auto-generated path
-                */
-               do {            /* in case we need to try again for an :auto: 
named lock file */
-
-                       if (!createConch && !forceNewLockPath) {
-                               hostIdMatch =
-                                   !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
-                                           PROXY_HOSTIDLEN);
-                               /* if the conch has data compare the contents */
-                               if (!pCtx->lockProxyPath) {
-                                       /* for auto-named local lock file, just 
check the host ID and we'll
-                                        * use the local lock file path that's 
already in there
-                                        */
-                                       if (hostIdMatch) {
-                                               size_t pathLen =
-                                                   (readLen - PROXY_PATHINDEX);
-
-                                               if (pathLen >= MAXPATHLEN) {
-                                                       pathLen =
-                                                           MAXPATHLEN - 1;
-                                               }
-                                               memcpy(lockPath,
-                                                      &readBuf
-                                                      [PROXY_PATHINDEX],
-                                                      pathLen);
-                                               lockPath[pathLen] = 0;
-                                               tempLockPath = lockPath;
-                                               tryOldLockPath = 1;
-                                               /* create a copy of the lock 
path if the conch is taken */
-                                               goto end_takeconch;
-                                       }
-                               } else if (hostIdMatch
-                                          && !strncmp(pCtx->lockProxyPath,
-                                                      &readBuf
-                                                      [PROXY_PATHINDEX],
-                                                      readLen -
-                                                      PROXY_PATHINDEX)
-                                   ) {
-                                       /* conch host and lock path match */
-                                       goto end_takeconch;
-                               }
-                       }
+       memset(p, 0, sizeof(unixFile));
 
-                       /* if the conch isn't writable and doesn't match, we 
can't take it */
-                       if ((conchFile->openFlags & O_RDWR) == 0) {
-                               rc = SQLITE_BUSY;
-                               goto end_takeconch;
+       if (eType == SQLITE_OPEN_MAIN_DB) {
+               UnixUnusedFd *pUnused;
+               pUnused = findReusableFd(zName, flags);
+               if (pUnused) {
+                       fd = pUnused->fd;
+               } else {
+                       pUnused = sqlite3_malloc64(sizeof(*pUnused));
+                       if (!pUnused) {
+                               return SQLITE_NOMEM_BKPT;
                        }
+               }
+               p->pUnused = pUnused;
 
-                       /* either the conch didn't match or we need to create a 
new one */
-                       if (!pCtx->lockProxyPath) {
-                               proxyGetLockPath(pCtx->dbPath, lockPath,
-                                                MAXPATHLEN);
-                               tempLockPath = lockPath;
-                               /* create a copy of the lock path _only_ if the 
conch is taken */
-                       }
+               /* Database filenames are double-zero terminated if they are not
+                * URIs with parameters.  Hence, they can always be passed into
+                * sqlite3_uri_parameter().
+                */
+               assert((flags & SQLITE_OPEN_URI)
+                      || zName[strlen(zName) + 1] == 0);
 
-                       /* update conch with host and path (this will fail if 
other process
-                        * has a shared lock already), if the host id matches, 
use the big
-                        * stick.
-                        */
-                       futimes(conchFile->h, NULL);
-                       if (hostIdMatch && !createConch) {
-                               if (conchFile->pInode
-                                   && conchFile->pInode->nShared > 1) {
-                                       /* We are trying for an exclusive lock 
but another thread in this
-                                        * same process is still holding a 
shared lock.
-                                        */
-                                       rc = SQLITE_BUSY;
-                               } else {
-                                       rc = proxyConchLock(pFile, myHostID,
-                                                           EXCLUSIVE_LOCK);
-                               }
-                       } else {
-                               rc = proxyConchLock(pFile, myHostID,
-                                                   EXCLUSIVE_LOCK);
-                       }
-                       if (rc == SQLITE_OK) {
-                               char writeBuffer[PROXY_MAXCONCHLEN];
-                               int writeSize = 0;
-
-                               writeBuffer[0] = (char)PROXY_CONCHVERSION;
-                               memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID,
-                                      PROXY_HOSTIDLEN);
-                               if (pCtx->lockProxyPath != NULL) {
-                                       strlcpy(&writeBuffer[PROXY_PATHINDEX],
-                                               pCtx->lockProxyPath,
-                                               MAXPATHLEN);
-                               } else {
-                                       strlcpy(&writeBuffer[PROXY_PATHINDEX],
-                                               tempLockPath, MAXPATHLEN);
-                               }
-                               writeSize =
-                                   PROXY_PATHINDEX +
-                                   strlen(&writeBuffer[PROXY_PATHINDEX]);
-                               robust_ftruncate(conchFile->h, writeSize);
-                               rc = unixWrite((sqlite3_file *) conchFile,
-                                              writeBuffer, writeSize, 0);
-                               full_fsync(conchFile->h, 0, 0);
-                               /* If we created a new conch file (not just 
updated the contents of a
-                                * valid conch file), try to match the 
permissions of the database
-                                */
-                               if (rc == SQLITE_OK && createConch) {
-                                       struct stat buf;
-                                       int err = osFstat(pFile->h, &buf);
-                                       if (err == 0) {
-                                               mode_t cmode =
-                                                   buf.
-                                                   st_mode & (S_IRUSR | S_IWUSR
-                                                              | S_IRGRP |
-                                                              S_IWGRP | S_IROTH
-                                                              | S_IWOTH);
-                                               /* try to match the database 
file R/W permissions, ignore failure */
-#ifndef SQLITE_PROXY_DEBUG
-                                               osFchmod(conchFile->h, cmode);
-#else
-                                               do {
-                                                       rc = osFchmod
-                                                           (conchFile->h,
-                                                            cmode);
-                                               } while (rc == (-1)
-                                                        && errno == EINTR);
-                                               if (rc != 0) {
-                                                       int code = errno;
-                                                       fprintf(stderr,
-                                                               "fchmod %o 
FAILED with %d %s\n",
-                                                               cmode, code,
-                                                               strerror(code));
-                                               } else {
-                                                       fprintf(stderr,
-                                                               "fchmod %o 
SUCCEDED\n",
-                                                               cmode);
-                                               }
-                                       } else {
-                                               int code = errno;
-                                               fprintf(stderr,
-                                                       "STAT FAILED[%d] with 
%d %s\n",
-                                                       err, code,
-                                                       strerror(code));
-#endif
-                                       }
-                               }
-                       }
-                       conchFile->pMethod->xUnlock((sqlite3_file *) conchFile,
-                                                   SHARED_LOCK);
-
- end_takeconch:
-                       if (rc == SQLITE_OK && pFile->openFlags) {
-                               int fd;
-                               if (pFile->h >= 0) {
-                                       robust_close(pFile, pFile->h, __LINE__);
-                               }
-                               pFile->h = -1;
-                               fd = robust_open(pCtx->dbPath, pFile->openFlags,
-                                                0);
-                               if (fd >= 0) {
-                                       pFile->h = fd;
-                               } else {
-                                       rc = SQLITE_CANTOPEN_BKPT;      /* 
SQLITE_BUSY? proxyTakeConch called
-                                                                          
during locking */
-                               }
-                       }
-                       if (rc == SQLITE_OK && !pCtx->lockProxy) {
-                               char *path =
-                                   tempLockPath ? tempLockPath : pCtx->
-                                   lockProxyPath;
-                               rc = proxyCreateUnixFile(path, &pCtx->lockProxy,
-                                                        1);
-                               if (rc != SQLITE_OK && rc != SQLITE_NOMEM
-                                   && tryOldLockPath) {
-                                       /* we couldn't create the proxy lock 
file with the old lock file path
-                                        * so try again via auto-naming
-                                        */
-                                       forceNewLockPath = 1;
-                                       tryOldLockPath = 0;
-                                       continue;       /* go back to the do {} 
while start point, try again */
-                               }
-                       }
-                       if (rc == SQLITE_OK) {
-                               /* Need to make a copy of path if we extracted 
the value
-                                * from the conch file or the path was 
allocated on the stack
-                                */
-                               if (tempLockPath) {
-                                       pCtx->lockProxyPath =
-                                           sqlite3DbStrDup(0, tempLockPath);
-                                       if (!pCtx->lockProxyPath) {
-                                               rc = SQLITE_NOMEM_BKPT;
-                                       }
-                               }
-                       }
-                       if (rc == SQLITE_OK) {
-                               pCtx->conchHeld = 1;
-
-                               if (pCtx->lockProxy->pMethod == &afpIoMethods) {
-                                       afpLockingContext *afpCtx;
-                                       afpCtx =
-                                           (afpLockingContext *) pCtx->
-                                           lockProxy->lockingContext;
-                                       afpCtx->dbPath = pCtx->lockProxyPath;
-                               }
-                       } else {
-                               conchFile->pMethod->
-                                   xUnlock((sqlite3_file *) conchFile,
-                                           NO_LOCK);
-                       }
+       } else if (!zName) {
+               /* If zName is NULL, the upper layer is requesting a temp file. 
*/
+               assert(isDelete);
+               rc = unixGetTempname(pVfs->mxPathname, zTmpname);
+               if (rc != SQLITE_OK) {
                        return rc;
-               } while (1);    /* in case we need to retry the :auto: lock 
file -
-                                * we should never get here except via the 
'continue' call.
-                                */
-       }
-}
+               }
+               zName = zTmpname;
 
-/*
- * If pFile holds a lock on a conch file, then release that lock.
- */
-static int
-proxyReleaseConch(unixFile * pFile)
-{
-       int rc = SQLITE_OK;     /* Subroutine return code */
-       proxyLockingContext *pCtx;      /* The locking context for the proxy 
lock */
-       unixFile *conchFile;    /* Name of the conch file */
-
-       pCtx = (proxyLockingContext *) pFile->lockingContext;
-       conchFile = pCtx->conchFile;
-       if (pCtx->conchHeld > 0) {
-               rc = conchFile->pMethod->xUnlock((sqlite3_file *) conchFile,
-                                                NO_LOCK);
+               /* Generated temporary filenames are always double-zero 
terminated
+                * for use by sqlite3_uri_parameter().
+                */
+               assert(zName[strlen(zName) + 1] == 0);
        }
-       pCtx->conchHeld = 0;
-       return rc;
-}
-
-/*
- * Given the name of a database file, compute the name of its conch file.
- * Store the conch filename in memory obtained from sqlite3_malloc64().
- * Make *pConchPath point to the new name.  Return SQLITE_OK on success
- * or SQLITE_NOMEM if unable to obtain memory.
- *
- * The caller is responsible for ensuring that the allocated memory
- * space is eventually freed.
- *
- * *pConchPath is set to NULL if a memory allocation error occurs.
- */
-static int
-proxyCreateConchPathname(char *dbPath, char **pConchPath)
-{
-       int i;                  /* Loop counter */
-       int len = (int)strlen(dbPath);  /* Length of database filename - dbPath 
*/
-       char *conchPath;        /* buffer in which to construct conch name */
 
-       /* Allocate space for the conch filename and initialize the name to
-        * the name of the original database file.
+       /* Determine the value of the flags parameter passed to POSIX function
+        * open(). These must be calculated even if open() is not called, as
+        * they may be stored as part of the file handle and used by the
+        * 'conch file' locking functions later on.
         */
-       *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8);
-       if (conchPath == 0) {
-               return SQLITE_NOMEM_BKPT;
-       }
-       memcpy(conchPath, dbPath, len + 1);
+       if (isReadonly)
+               openFlags |= O_RDONLY;
+       if (isReadWrite)
+               openFlags |= O_RDWR;
+       if (isCreate)
+               openFlags |= O_CREAT;
+       if (isExclusive)
+               openFlags |= (O_EXCL | O_NOFOLLOW);
+       openFlags |= O_BINARY;
+       #ifndef __APPLE__
+       openFlags |= O_LARGEFILE;
+       #endif
 
-       /* now insert a "." before the last / character */
-       for (i = (len - 1); i >= 0; i--) {
-               if (conchPath[i] == '/') {
-                       i++;
-                       break;
+       if (fd < 0) {
+               mode_t openMode;        /* Permissions to create file with */
+               uid_t uid;      /* Userid for the file */
+               gid_t gid;      /* Groupid for the file */
+               rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
+               if (rc != SQLITE_OK) {
+                       assert(!p->pUnused);
+                       return rc;
+               }
+               fd = robust_open(zName, openFlags, openMode);
+               assert(!isExclusive || (openFlags & O_CREAT) != 0);
+               if (fd < 0 && errno != EISDIR && isReadWrite) {
+                       /* Failed to open the file for read/write access. Try 
read-only. */
+                       flags &= ~(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+                       openFlags &= ~(O_RDWR | O_CREAT);
+                       flags |= SQLITE_OPEN_READONLY;
+                       openFlags |= O_RDONLY;
+                       isReadonly = 1;
+                       fd = robust_open(zName, openFlags, openMode);
+               }
+               if (fd < 0) {
+                       rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
+                       goto open_finished;
                }
+               
        }
-       conchPath[i] = '.';
-       while (i < len) {
-               conchPath[i + 1] = dbPath[i];
-               i++;
+       assert(fd >= 0);
+       if (pOutFlags) {
+               *pOutFlags = flags;
        }
 
-       /* append the "-conch" suffix to the file */
-       memcpy(&conchPath[i + 1], "-conch", 7);
-       assert((int)strlen(conchPath) == len + 7);
+       if (p->pUnused) {
+               p->pUnused->fd = fd;
+               p->pUnused->flags = flags;
+       }
 
-       return SQLITE_OK;
-}
+       if (isDelete)
+               unlink(zName);
 
-/* Takes a fully configured proxy locking-style unix file and switches
- * the local lock file path
- */
-static int
-switchLockProxyPath(unixFile * pFile, const char *path)
-{
-       proxyLockingContext *pCtx =
-           (proxyLockingContext *) pFile->lockingContext;
-       char *oldPath = pCtx->lockProxyPath;
-       int rc = SQLITE_OK;
+       /* Set up appropriate ctrlFlags */
+       if (isDelete)
+               ctrlFlags |= UNIXFILE_DELETE;
+       if (isReadonly)
+               ctrlFlags |= UNIXFILE_RDONLY;
+       noLock = eType != SQLITE_OPEN_MAIN_DB;
+       if (noLock)
+               ctrlFlags |= UNIXFILE_NOLOCK;
+       if (syncDir)
+               ctrlFlags |= UNIXFILE_DIRSYNC;
+       if (flags & SQLITE_OPEN_URI)
+               ctrlFlags |= UNIXFILE_URI;
 
-       if (pFile->eFileLock != NO_LOCK) {
-               return SQLITE_BUSY;
-       }
+       rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
 
-       /* nothing to do if the path is NULL, :auto: or matches the existing 
path */
-       if (!path || path[0] == '\0' || !strcmp(path, ":auto:") ||
-           (oldPath && !strncmp(oldPath, path, MAXPATHLEN))) {
-               return SQLITE_OK;
-       } else {
-               unixFile *lockProxy = pCtx->lockProxy;
-               pCtx->lockProxy = NULL;
-               pCtx->conchHeld = 0;
-               if (lockProxy != NULL) {
-                       rc = lockProxy->pMethod->
-                           xClose((sqlite3_file *) lockProxy);
-                       if (rc)
-                               return rc;
-                       sqlite3_free(lockProxy);
-               }
-               sqlite3_free(oldPath);
-               pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
+ open_finished:
+       if (rc != SQLITE_OK) {
+               sqlite3_free(p->pUnused);
        }
-
        return rc;
 }
 
 /*
- * pFile is a file that has been opened by a prior xOpen call.  dbPath
- * is a string buffer at least MAXPATHLEN+1 characters in size.
- *
- * This routine find the filename associated with pFile and writes it
- * int dbPath.
- */
-static int
-proxyGetDbPathForUnixFile(unixFile * pFile, char *dbPath)
-{
-#if defined(__APPLE__)
-       if (pFile->pMethod == &afpIoMethods) {
-               /* afp style keeps a reference to the db path in the filePath 
field
-                * of the struct
-                */
-               assert((int)strlen((char *)pFile->lockingContext) <=
-                      MAXPATHLEN);
-               strlcpy(dbPath,
-                       ((afpLockingContext *) pFile->lockingContext)->dbPath,
-                       MAXPATHLEN);
-       } else
-#endif
-       if (pFile->pMethod == &dotlockIoMethods) {
-               /* dot lock style uses the locking context to store the dot lock
-                * file path
-                */
-               int len =
-                   strlen((char *)pFile->lockingContext) -
-                   strlen(DOTLOCK_SUFFIX);
-               memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
-       } else {
-               /* all other styles use the locking context to store the db 
file path */
-               assert(strlen((char *)pFile->lockingContext) <= MAXPATHLEN);
-               strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
-       }
-       return SQLITE_OK;
-}
-
-/*
- * Takes an already filled in unix file and alters it so all file locking
- * will be performed on the local proxy lock file.  The following fields
- * are preserved in the locking context so that they can be restored and
- * the unix structure properly cleaned up at close time:
- *  ->lockingContext
- *  ->pMethod
+ * Delete the file at zPath. If the dirSync argument is true, fsync()
+ * the directory after deleting the file.
  */
 static int
-proxyTransformUnixFile(unixFile * pFile, const char *path)
+unixDelete(sqlite3_vfs * NotUsed,      /* VFS containing this as the xDelete 
method */
+          const char *zPath,   /* Name of file to be deleted */
+          int dirSync          /* If true, fsync() directory after deleting 
file */
+    )
 {
-       proxyLockingContext *pCtx;
-       char dbPath[MAXPATHLEN + 1];    /* Name of the database file */
-       char *lockPath = NULL;
        int rc = SQLITE_OK;
-
-       if (pFile->eFileLock != NO_LOCK) {
-               return SQLITE_BUSY;
-       }
-       proxyGetDbPathForUnixFile(pFile, dbPath);
-       if (!path || path[0] == '\0' || !strcmp(path, ":auto:")) {
-               lockPath = NULL;
-       } else {
-               lockPath = (char *)path;
-       }
-
-       pCtx = sqlite3_malloc64(sizeof(*pCtx));
-       if (pCtx == 0) {
-               return SQLITE_NOMEM_BKPT;
-       }
-       memset(pCtx, 0, sizeof(*pCtx));
-
-       rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
-       if (rc == SQLITE_OK) {
-               rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile,
-                                        0);
-               if (rc == SQLITE_CANTOPEN && ((pFile->openFlags & O_RDWR) == 
0)) {
-                       /* if (a) the open flags are not O_RDWR, (b) the conch 
isn't there, and
-                        * (c) the file system is read-only, then enable 
no-locking access.
-                        * Ugh, since O_RDONLY==0x0000 we test for !O_RDWR 
since unixOpen asserts
-                        * that openFlags will have only one of O_RDONLY or 
O_RDWR.
-                        */
-                       struct statfs fsInfo;
-                       struct stat conchInfo;
-                       int goLockless = 0;
-
-                       if (osStat(pCtx->conchFilePath, &conchInfo) == -1) {
-                               int err = errno;
-                               if ((err == ENOENT)
-                                   && (statfs(dbPath, &fsInfo) != -1)) {
-                                       goLockless =
-                                           (fsInfo.f_flags & MNT_RDONLY) ==
-                                           MNT_RDONLY;
-                               }
-                       }
-                       if (goLockless) {
-                               pCtx->conchHeld = -1;   /* read only FS/ 
lockless */
-                               rc = SQLITE_OK;
-                       }
-               }
-       }
-       if (rc == SQLITE_OK && lockPath) {
-               pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
-       }
-
-       if (rc == SQLITE_OK) {
-               pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
-               if (pCtx->dbPath == NULL) {
-                       rc = SQLITE_NOMEM_BKPT;
+       UNUSED_PARAMETER(NotUsed);
+       SimulateIOError(return SQLITE_IOERR_DELETE);
+       if (unlink(zPath) == (-1)) {
+               if (errno == ENOENT) {
+                       rc = SQLITE_IOERR_DELETE_NOENT;
+               } else {
+                       rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
                }
+               return rc;
        }
-       if (rc == SQLITE_OK) {
-               /* all memory is allocated, proxys are created and assigned,
-                * switch the locking context and pMethod then return.
-                */
-               pCtx->oldLockingContext = pFile->lockingContext;
-               pFile->lockingContext = pCtx;
-               pCtx->pOldMethod = pFile->pMethod;
-               pFile->pMethod = &proxyIoMethods;
-       } else {
-               if (pCtx->conchFile) {
-                       pCtx->conchFile->pMethod->xClose((sqlite3_file *) pCtx->
-                                                        conchFile);
-                       sqlite3_free(pCtx->conchFile);
+#ifndef SQLITE_DISABLE_DIRSYNC
+       if ((dirSync & 1) != 0) {
+               int fd;
+               rc = openDirectory(zPath, &fd);
+               if (rc == SQLITE_OK) {
+                       if (full_fsync(fd, 0, 0)) {
+                               rc = unixLogError(SQLITE_IOERR_DIR_FSYNC,
+                                                 "fsync", zPath);
+                       }
+                       robust_close(0, fd, __LINE__);
+               } else {
+                       assert(rc == SQLITE_CANTOPEN);
+                       rc = SQLITE_OK;
                }
-               sqlite3DbFree(0, pCtx->lockProxyPath);
-               sqlite3_free(pCtx->conchFilePath);
-               sqlite3_free(pCtx);
        }
+#endif
        return rc;
 }
 
 /*
- * This routine handles sqlite3_file_control() calls that are specific
- * to proxy locking.
+ * Write nBuf bytes of random data to the supplied buffer zBuf.
  */
 static int
-proxyFileControl(sqlite3_file * id, int op, void *pArg)
+unixRandomness(sqlite3_vfs * NotUsed, int nBuf, char *zBuf)
 {
-       switch (op) {
-       case SQLITE_FCNTL_GET_LOCKPROXYFILE:{
-                       unixFile *pFile = (unixFile *) id;
-                       if (pFile->pMethod == &proxyIoMethods) {
-                               proxyLockingContext *pCtx =
-                                   (proxyLockingContext *) pFile->
-                                   lockingContext;
-                               proxyTakeConch(pFile);
-                               if (pCtx->lockProxyPath) {
-                                       *(const char **)pArg =
-                                           pCtx->lockProxyPath;
-                               } else {
-                                       *(const char **)pArg =
-                                           ":auto: (not held)";
-                               }
-                       } else {
-                               *(const char **)pArg = NULL;
-                       }
-                       return SQLITE_OK;
-               }
-       case SQLITE_FCNTL_SET_LOCKPROXYFILE:{
-                       unixFile *pFile = (unixFile *) id;
-                       int rc = SQLITE_OK;
-                       int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
-                       if (pArg == NULL || (const char *)pArg == 0) {
-                               if (isProxyStyle) {
-                                       rc = SQLITE_ERROR;
-                               } else {
-                                       /* turn off proxy locking - already off 
- NOOP */
-                                       rc = SQLITE_OK;
-                               }
-                       } else {
-                               const char *proxyPath = (const char *)pArg;
-                               if (isProxyStyle) {
-                                       proxyLockingContext *pCtx =
-                                           (proxyLockingContext *) pFile->
-                                           lockingContext;
-                                       if (!strcmp(pArg, ":auto:")
-                                           || (pCtx->lockProxyPath &&
-                                               !strncmp(pCtx->lockProxyPath,
-                                                        proxyPath, MAXPATHLEN))
-                                           ) {
-                                               rc = SQLITE_OK;
-                                       } else {
-                                               rc = switchLockProxyPath(pFile,
-                                                                        
proxyPath);
-                                       }
-                               } else {
-                                       /* turn on proxy file locking */
-                                       rc = proxyTransformUnixFile(pFile,
-                                                                   proxyPath);
-                               }
-                       }
-                       return rc;
-               }
-       default:{
-                       assert(0);      /* The call assures that only valid 
opcodes are sent */
-               }
-       }
-        /*NOTREACHED*/ return SQLITE_ERROR;
-}
+       UNUSED_PARAMETER(NotUsed);
+       assert((size_t) nBuf >= (sizeof(time_t) + sizeof(int)));
 
-/*
- * Within this division (the proxying locking implementation) the procedures
- * above this point are all utilities.  The lock-related methods of the
- * proxy-locking sqlite3_io_method object follow.
- */
+       /* We have to initialize zBuf to prevent valgrind from reporting
+        * errors.  The reports issued by valgrind are incorrect - we would
+        * prefer that the randomness be increased by making use of the
+        * uninitialized space in zBuf - but valgrind errors tend to worry
+        * some users.  Rather than argue, it seems easier just to initialize
+        * the whole array and silence valgrind, even if that means less 
randomness
+        * in the random seed.
+        *
+        * When testing, initializing zBuf[] to zero is all we do.  That means
+        * that we always use the same random number sequence.  This makes the
+        * tests repeatable.
+        */
+       memset(zBuf, 0, nBuf);
+       randomnessPid = getpid();
+       return nBuf;
+}
 
 /*
- * This routine checks if there is a RESERVED lock held on the specified
- * file by this or any other process. If such a lock is held, set *pResOut
- * to a non-zero value otherwise *pResOut is set to zero.  The return value
- * is set to SQLITE_OK unless an I/O error occurs during lock checking.
+ * Sleep for a little while.  Return the amount of time slept.
+ * The argument is the number of microseconds we want to sleep.
+ * The return value is the number of microseconds of sleep actually
+ * requested from the underlying operating system, a number which
+ * might be greater than or equal to the argument, but not less
+ * than the argument.
  */
 static int
-proxyCheckReservedLock(sqlite3_file * id, int *pResOut)
+unixSleep(sqlite3_vfs * NotUsed, int microseconds)
 {
-       unixFile *pFile = (unixFile *) id;
-       int rc = proxyTakeConch(pFile);
-       if (rc == SQLITE_OK) {
-               proxyLockingContext *pCtx =
-                   (proxyLockingContext *) pFile->lockingContext;
-               if (pCtx->conchHeld > 0) {
-                       unixFile *proxy = pCtx->lockProxy;
-                       return proxy->pMethod->
-                           xCheckReservedLock((sqlite3_file *) proxy, pResOut);
-               } else {        /* conchHeld < 0 is lockless */
-                       pResOut = 0;
-               }
-       }
-       return rc;
+       int seconds = (microseconds + 999999) / 1000000;
+       sleep(seconds);
+       UNUSED_PARAMETER(NotUsed);
+       return seconds * 1000000;
 }
 
+/* Fake system time in seconds since 1970. */
+int sqlite3_current_time = 0;
+
 /*
- * Lock the file with the lock specified by parameter eFileLock - one
- * of the following:
- *
- *     (1) SHARED_LOCK
- *     (2) RESERVED_LOCK
- *     (3) PENDING_LOCK
- *     (4) EXCLUSIVE_LOCK
- *
- * Sometimes when requesting one lock state, additional lock states
- * are inserted in between.  The locking might fail on one of the later
- * transitions leaving the lock state different from what it started but
- * still short of its goal.  The following chart shows the allowed
- * transitions and the inserted intermediate states:
- *
- *    UNLOCKED -> SHARED
- *    SHARED -> RESERVED
- *    SHARED -> (PENDING) -> EXCLUSIVE
- *    RESERVED -> (PENDING) -> EXCLUSIVE
- *    PENDING -> EXCLUSIVE
+ * Find the current time (in Universal Coordinated Time).  Write into *piNow
+ * the current time and date as a Julian Day number times 86_400_000.  In
+ * other words, write into *piNow the number of milliseconds since the Julian
+ * epoch of noon in Greenwich on November 24, 4714 B.C according to the
+ * proleptic Gregorian calendar.
  *
- * This routine will only increase a lock.  Use the sqlite3OsUnlock()
- * routine to lower a locking level.
+ * On success, return SQLITE_OK.  Return SQLITE_ERROR if the time and date
+ * cannot be found.
  */
 static int
-proxyLock(sqlite3_file * id, int eFileLock)
+unixCurrentTimeInt64(sqlite3_vfs * NotUsed, sqlite3_int64 * piNow)
 {
-       unixFile *pFile = (unixFile *) id;
-       int rc = proxyTakeConch(pFile);
-       if (rc == SQLITE_OK) {
-               proxyLockingContext *pCtx =
-                   (proxyLockingContext *) pFile->lockingContext;
-               if (pCtx->conchHeld > 0) {
-                       unixFile *proxy = pCtx->lockProxy;
-                       rc = proxy->pMethod->xLock((sqlite3_file *) proxy,
-                                                  eFileLock);
-                       pFile->eFileLock = proxy->eFileLock;
-               } else {
-                       /* conchHeld < 0 is lockless */
-               }
+       static const sqlite3_int64 unixEpoch =
+           24405875 * (sqlite3_int64) 8640000;
+       int rc = SQLITE_OK;
+       struct timeval sNow;
+       (void)gettimeofday(&sNow, 0);   /* Cannot fail given valid arguments */
+       *piNow =
+           unixEpoch + 1000 * (sqlite3_int64) sNow.tv_sec +
+           sNow.tv_usec / 1000;
+
+#ifdef SQLITE_TEST
+       if (sqlite3_current_time) {
+               *piNow =
+                   1000 * (sqlite3_int64) sqlite3_current_time + unixEpoch;
        }
+#endif
+       UNUSED_PARAMETER(NotUsed);
        return rc;
 }
 
 /*
- * Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
- * must be either NO_LOCK or SHARED_LOCK.
- *
- * If the locking level of the file descriptor is already at or below
- * the requested locking level, this routine is a no-op.
+ * The xGetLastError() method is designed to return a better
+ * low-level error message when operating-system problems come up
+ * during SQLite operation.  Only the integer return code is currently
+ * used.
  */
 static int
-proxyUnlock(sqlite3_file * id, int eFileLock)
+unixGetLastError(sqlite3_vfs * NotUsed, int NotUsed2, char *NotUsed3)
 {
-       unixFile *pFile = (unixFile *) id;
-       int rc = proxyTakeConch(pFile);
-       if (rc == SQLITE_OK) {
-               proxyLockingContext *pCtx =
-                   (proxyLockingContext *) pFile->lockingContext;
-               if (pCtx->conchHeld > 0) {
-                       unixFile *proxy = pCtx->lockProxy;
-                       rc = proxy->pMethod->xUnlock((sqlite3_file *) proxy,
-                                                    eFileLock);
-                       pFile->eFileLock = proxy->eFileLock;
-               } else {
-                       /* conchHeld < 0 is lockless */
-               }
-       }
-       return rc;
+       UNUSED_PARAMETER(NotUsed);
+       UNUSED_PARAMETER(NotUsed2);
+       UNUSED_PARAMETER(NotUsed3);
+       return errno;
 }
 
 /*
- * Close a file that uses proxy locks.
- */
-static int
-proxyClose(sqlite3_file * id)
-{
-       if (ALWAYS(id)) {
-               unixFile *pFile = (unixFile *) id;
-               proxyLockingContext *pCtx =
-                   (proxyLockingContext *) pFile->lockingContext;
-               unixFile *lockProxy = pCtx->lockProxy;
-               unixFile *conchFile = pCtx->conchFile;
-               int rc = SQLITE_OK;
-
-               if (lockProxy) {
-                       rc = lockProxy->pMethod->
-                           xUnlock((sqlite3_file *) lockProxy, NO_LOCK);
-                       if (rc)
-                               return rc;
-                       rc = lockProxy->pMethod->
-                           xClose((sqlite3_file *) lockProxy);
-                       if (rc)
-                               return rc;
-                       sqlite3_free(lockProxy);
-                       pCtx->lockProxy = 0;
-               }
-               if (conchFile) {
-                       if (pCtx->conchHeld) {
-                               rc = proxyReleaseConch(pFile);
-                               if (rc)
-                                       return rc;
-                       }
-                       rc = conchFile->pMethod->
-                           xClose((sqlite3_file *) conchFile);
-                       if (rc)
-                               return rc;
-                       sqlite3_free(conchFile);
-               }
-               sqlite3DbFree(0, pCtx->lockProxyPath);
-               sqlite3_free(pCtx->conchFilePath);
-               sqlite3DbFree(0, pCtx->dbPath);
-               /* restore the original locking context and pMethod then close 
it */
-               pFile->lockingContext = pCtx->oldLockingContext;
-               pFile->pMethod = pCtx->pOldMethod;
-               sqlite3_free(pCtx);
-               return pFile->pMethod->xClose(id);
-       }
-       return SQLITE_OK;
-}
+ *********************** End of sqlite3_vfs methods ***************************
+ *****************************************************************************/
 
-#endif                         /* defined(__APPLE__) && 
SQLITE_ENABLE_LOCKING_STYLE */
 /*
  * The proxy locking style is intended for use with AFP filesystems.
  * And since AFP is only supported on MacOSX, the proxy locking is also
@@ -6136,6 +2147,22 @@ proxyClose(sqlite3_file * id)
  ****************** End of the proxy lock implementation **********************
  *****************************************************************************/
 
+#define UNIXVFS(VFSNAME, FINDER) {                        \
+    3,                    /* iVersion */                    \
+    sizeof(unixFile),     /* szOsFile */                    \
+    MAX_PATHNAME,         /* mxPathname */                  \
+    NULL,                 /* pNext */                       \
+    VFSNAME,              /* zName */                       \
+    (void*)&FINDER,       /* pAppData */                    \
+    unixOpen,             /* xOpen */                       \
+    unixDelete,           /* xDelete */                     \
+    unixRandomness,       /* xRandomness */                 \
+    unixSleep,            /* xSleep */                      \
+    NULL,                 /* xCurrentTime */                \
+    unixGetLastError,     /* xGetLastError */               \
+    unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
+  }
+
 /*
  * Initialize the operating system interface.
  *
@@ -6153,47 +2180,6 @@ int
 sqlite3_os_init(void)
 {
        /*
-        * The following macro defines an initializer for an sqlite3_vfs object.
-        * The name of the VFS is NAME.  The pAppData is a pointer to a pointer
-        * to the "finder" function.  (pAppData is a pointer to a pointer 
because
-        * silly C90 rules prohibit a void* from being cast to a function 
pointer
-        * and so we have to go through the intermediate pointer to avoid 
problems
-        * when compiling with -pedantic-errors on GCC.)
-        *
-        * The FINDER parameter to this macro is the name of the pointer to the
-        * finder-function.  The finder-function returns a pointer to the
-        * sqlite_io_methods object that implements the desired locking
-        * behaviors.  See the division above that contains the IOMETHODS
-        * macro for addition information on finder-functions.
-        *
-        * Most finders simply return a pointer to a fixed sqlite3_io_methods
-        * object.  But the "autolockIoFinder" available on MacOSX does a little
-        * more than that; it looks at the filesystem type that hosts the
-        * database file and tries to choose an locking method appropriate for
-        * that filesystem time.
-        */
-#define UNIXVFS(VFSNAME, FINDER) {                        \
-    3,                    /* iVersion */                    \
-    sizeof(unixFile),     /* szOsFile */                    \
-    MAX_PATHNAME,         /* mxPathname */                  \
-    0,                    /* pNext */                       \
-    VFSNAME,              /* zName */                       \
-    (void*)&FINDER,       /* pAppData */                    \
-    unixOpen,             /* xOpen */                       \
-    unixDelete,           /* xDelete */                     \
-    unixAccess,           /* xAccess */                     \
-    unixFullPathname,     /* xFullPathname */               \
-    unixRandomness,       /* xRandomness */                 \
-    unixSleep,            /* xSleep */                      \
-    0,                   /* xCurrentTime */                \
-    unixGetLastError,     /* xGetLastError */               \
-    unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
-    unixSetSystemCall,    /* xSetSystemCall */              \
-    unixGetSystemCall,    /* xGetSystemCall */              \
-    unixNextSystemCall,   /* xNextSystemCall */             \
-  }
-
-       /*
         * All default VFSes for unix are contained in the following array.
         *
         * Note that the sqlite3_vfs.pNext field of the VFS object is modified
@@ -6201,36 +2187,13 @@ sqlite3_os_init(void)
         * array cannot be const.
         */
        static sqlite3_vfs aVfs[] = {
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-               UNIXVFS("unix", autolockIoFinder),
-#endif
                UNIXVFS("unix-none", nolockIoFinder),
-               UNIXVFS("unix-dotfile", dotlockIoFinder),
-               UNIXVFS("unix-excl", posixIoFinder),
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-               UNIXVFS("unix-posix", posixIoFinder),
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE
-               UNIXVFS("unix-flock", flockIoFinder),
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
-               UNIXVFS("unix-afp", afpIoFinder),
-               UNIXVFS("unix-nfs", nfsIoFinder),
-               UNIXVFS("unix-proxy", proxyIoFinder),
-#endif
+               UNIXVFS("unix-excl", posixIoFinder)
        };
-       unsigned int i;         /* Loop counter */
-
-       /* Double-check that the aSyscall[] array has been constructed
-        * correctly.  See ticket [bb3a86e890c8e96ab]
-        */
-       assert(ArraySize(aSyscall) == 28);
 
-       /* Register all VFSes defined in the aVfs[] array */
-       for (i = 0; i < (sizeof(aVfs) / sizeof(sqlite3_vfs)); i++) {
+       /* Register all VFSes defined in the aVfs[] array. */
+       for (unsigned int i = 0; i < (sizeof(aVfs) / sizeof(sqlite3_vfs)); i++)
                sqlite3_vfs_register(&aVfs[i], i == 0);
-       }
        return SQLITE_OK;
 }
 
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 31581b1..146b446 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -43,14 +43,6 @@
 #include "box/schema.h"
 #include "box/session.h"
 
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-#if defined(__APPLE__)
-#define SQLITE_ENABLE_LOCKING_STYLE 1
-#else
-#define SQLITE_ENABLE_LOCKING_STYLE 0
-#endif
-#endif
-
 /*
  ************************************************************************
  * pragma.h contains several pragmas, including utf's pragmas.
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 9f6f83b..12fa109 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -342,7 +342,6 @@ struct sqlite3_file {
 typedef int (*sqlite3_callback) (void *, int, char **, char **);
 
 typedef struct sqlite3_vfs sqlite3_vfs;
-typedef void (*sqlite3_syscall_ptr) (void);
 struct sqlite3_vfs {
        int iVersion;   /* Structure version number (currently 3) */
        int szOsFile;   /* Size of subclassed sqlite3_file */
@@ -353,10 +352,6 @@ struct sqlite3_vfs {
        int (*xOpen) (sqlite3_vfs *, const char *zName, sqlite3_file *,
                      int flags, int *pOutFlags);
        int (*xDelete) (sqlite3_vfs *, const char *zName, int syncDir);
-       int (*xAccess) (sqlite3_vfs *, const char *zName, int flags,
-                       int *pResOut);
-       int (*xFullPathname) (sqlite3_vfs *, const char *zName,
-                             int nOut, char *zOut);
        int (*xRandomness) (sqlite3_vfs *, int nByte, char *zOut);
        int (*xSleep) (sqlite3_vfs *, int microseconds);
        int (*xCurrentTime) (sqlite3_vfs *, double *);
@@ -367,16 +362,6 @@ struct sqlite3_vfs {
        */
        int (*xCurrentTimeInt64) (sqlite3_vfs *, sqlite3_int64 *);
        /*
-       ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
-       ** Those below are for version 3 and greater.
-       */
-       int (*xSetSystemCall) (sqlite3_vfs *, const char *zName,
-                              sqlite3_syscall_ptr);
-       sqlite3_syscall_ptr(*xGetSystemCall) (sqlite3_vfs *,
-                                             const char *zName);
-       const char *(*xNextSystemCall) (sqlite3_vfs *,
-                                       const char *zName);
-       /*
        ** The methods above are in versions 1 through 3 of the sqlite_vfs 
object.
        ** New fields may be appended in future versions.  The iVersion
        ** value will increment whenever this happens.
@@ -846,21 +831,7 @@ struct sqlite3_io_methods {
                      sqlite3_int64 iOfst);
        int (*xWrite) (sqlite3_file *, const void *, int iAmt,
                       sqlite3_int64 iOfst);
-       int (*xTruncate) (sqlite3_file *, sqlite3_int64 size);
-       int (*xSync) (sqlite3_file *, int flags);
-       int (*xFileSize) (sqlite3_file *, sqlite3_int64 * pSize);
-       int (*xLock) (sqlite3_file *, int);
-       int (*xUnlock) (sqlite3_file *, int);
-       int (*xCheckReservedLock) (sqlite3_file *, int *pResOut);
        int (*xFileControl) (sqlite3_file *, int op, void *pArg);
-       int (*xSectorSize) (sqlite3_file *);
-       int (*xDeviceCharacteristics) (sqlite3_file *);
-       /* Methods above are valid for version 1 */
-       int (*xShmMap) (sqlite3_file *, int iPg, int pgsz, int,
-                       void volatile **);
-       int (*xShmLock) (sqlite3_file *, int offset, int n, int flags);
-       void (*xShmBarrier) (sqlite3_file *);
-       int (*xShmUnmap) (sqlite3_file *, int deleteFlag);
        /* Methods above are valid for version 2 */
        int (*xFetch) (sqlite3_file *, sqlite3_int64 iOfst, int iAmt,
                       void **pp);
@@ -887,11 +858,6 @@ struct sqlite3_io_methods {
 #define SQLITE_FCNTL_TRACE                  17
 #define SQLITE_FCNTL_HAS_MOVED              18
 #define SQLITE_FCNTL_SYNC                   19
-#define SQLITE_FCNTL_COMMIT_PHASETWO        20
-#define SQLITE_FCNTL_ZIPVFS                 22
-#define SQLITE_FCNTL_RBU                    23
-#define SQLITE_FCNTL_VFS_POINTER            24
-#define SQLITE_FCNTL_PDB                    26
 
 int
 sqlite3_os_init(void);
-- 
2.7.4


Other related posts: