15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2004 May 22
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains the VFS implementation for unix-like operating systems
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** There are actually several different VFS implementations in this file.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The differences are in the way that file locking is done.  The default
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** implementation uses Posix Advisory Locks.  Alternative implementations
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** use flock(), dot-files, various proprietary locking schemas, or simply
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** skip locking all together.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This source file is organized into divisions where the logic for various
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** subfunctions is contained within the appropriate division.  PLEASE
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** KEEP THE STRUCTURE OF THIS FILE INTACT.  New code should be placed
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the correct division and should be clearly labeled.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The layout of divisions is as follows:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  General-purpose declarations and utility functions.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  Unique file ID logic used by VxWorks.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  Various locking primitive implementations (all except proxy locking):
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      + for Posix Advisory Locks
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      + for no-op locks
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      + for dot-file locks
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      + for flock() locking
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      + for named semaphore locks (VxWorks only)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      + for AFP filesystem locks (MacOSX only)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  sqlite3_file methods not associated with locking.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  Definitions of sqlite3_io_methods objects for all locking
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      methods plus "finder" functions for each locking method.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  sqlite3_vfs method implementations.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  Locking primitives for the proxy uber-locking-method. (MacOSX only)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  Definitions of sqlite3_vfs objects for all locking methods
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      plus implementations of sqlite3_os_init() and sqlite3_os_end().
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqliteInt.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_UNIX              /* This file is used on unix only */
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** There are various methods for file locking used for concurrency
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** control:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   1. POSIX locking (the default),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   2. No locking,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   3. Dot-file locking,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   4. flock() locking,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   5. AFP locking (OSX only),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   6. Named POSIX semaphores (VXWorks only),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   7. proxy locking. (OSX only)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is defined to 1.  The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** selection of the appropriate locking style based on the filesystem
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** where the database is located.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  if defined(__APPLE__)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    define SQLITE_ENABLE_LOCKING_STYLE 1
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  else
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    define SQLITE_ENABLE_LOCKING_STYLE 0
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  endif
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Define the OS_VXWORKS pre-processor macro to 1 if building on
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** vxworks, or 0 otherwise.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef OS_VXWORKS
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  if defined(__RTP__) || defined(_WRS_KERNEL)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    define OS_VXWORKS 1
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  else
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#    define OS_VXWORKS 0
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  endif
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** These #defines should enable >2GB file support on Posix if the
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** underlying operating system supports it.  If the OS lacks
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** large file support, these should be no-ops.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on the compiler command line.  This is necessary if you are compiling
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on a recent machine (ex: RedHat 7.2) but you want your code to work
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on an older machine (ex: RedHat 6.0).  If you compile on RedHat 7.2
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** without this option, LFS is enable.  But LFS does not exist in the kernel
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in RedHat 6.0, so the code won't work.  Hence, for maximum binary
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** portability you should omit LFS.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The previous paragraph was written in 2005.  (This paragraph is written
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on 2008-11-28.) These days, all Linux kernels support large files, so
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** you should probably leave LFS enabled.  But some embedded platforms might
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_DISABLE_LFS
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _LARGE_FILE       1
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifndef _FILE_OFFSET_BITS
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   define _FILE_OFFSET_BITS 64
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define _LARGEFILE_SOURCE 1
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** standard include files.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h>
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h>
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_WAL
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h>
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <sys/ioctl.h>
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if OS_VXWORKS
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  include <semaphore.h>
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  include <limits.h>
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# else
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  include <sys/file.h>
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  include <sys/param.h>
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_ENABLE_LOCKING_STYLE */
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <sys/mount.h>
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Allowed values of unixFile.fsFlags
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SQLITE_FSFLAGS_IS_MSDOS     0x1
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If we are to be thread-safe, include the pthreads header and define
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the SQLITE_UNIX_THREADS macro.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_THREADSAFE
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <pthread.h>
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define SQLITE_UNIX_THREADS 1
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Default permissions when creating a new file
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Default permissions when creating auto proxy dir
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Maximum supported path-length.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_PATHNAME 512
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Only set the lastErrno if the error code is a real error and not
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a normal expected return code of SQLITE_BUSY or SQLITE_OK
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Forward references */
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct unixShm unixShm;               /* Connection shared memory */
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct unixShmNode unixShmNode;       /* Shared memory instance */
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct unixInodeInfo unixInodeInfo;   /* An i-node */
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct UnixUnusedFd UnixUnusedFd;     /* An unused file descriptor */
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes, after a file handle is closed by SQLite, the file descriptor
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** cannot be closed immediately. In these cases, instances of the following
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** structure are used to store the file descriptor while waiting for an
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** opportunity to either close or reuse it.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct UnixUnusedFd {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd;                   /* File descriptor to close */
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags;                /* Flags this file descriptor was opened with */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *pNext;      /* Next unused file descriptor on same file */
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The unixFile structure is subclass of sqlite3_file specific to the unix
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** VFS implementations.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct unixFile unixFile;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct unixFile {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_io_methods const *pMethod;  /* Always the first entry */
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode;              /* Info about locks on this inode */
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int h;                              /* The file descriptor */
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char eFileLock;            /* The type of lock held on this fd */
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lastErrno;                      /* The unix errno from last I/O error */
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *lockingContext;               /* Locking style specific state */
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath;                  /* Name of the file */
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm *pShm;                      /* Shared memory segment information */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szChunk;                        /* Configured by FCNTL_CHUNK_SIZE */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int openFlags;                      /* The flags specified at open() */
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned fsFlags;                   /* cached details from statfs() */
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isDelete;                       /* Delete on close if true */
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct vxworksFileId *pId;          /* Unique file ID */
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The next group of variables are used to track whether or not the
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** transaction counter in bytes 24-27 of database files are updated
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** whenever any part of the database changes.  An assertion fault will
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** occur if a file is updated without also updating the transaction
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** counter.  This test is made to avoid new problems similar to the
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** one described by ticket #3584.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char transCntrChng;   /* True if the transaction counter changed */
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char dbUpdate;        /* True if any part of database file changed */
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char inNormalWrite;   /* True if in a normal write operation */
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* In test mode, increase the size of this structure a bit so that
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** it is larger than the struct CrashFile defined in test6.c.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char aPadding[32];
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Allowed values for the unixFile.ctrlFlags bitmask:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNIXFILE_EXCL   0x01     /* Connections from one process only */
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNIXFILE_RDONLY 0x02     /* Connection is read only */
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNIXFILE_DIRSYNC 0x04    /* Directory sync needed */
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Include code that is common to all os_*.c files
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "os_common.h"
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Define various macros that are missing from some systems.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef O_LARGEFILE
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define O_LARGEFILE 0
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DISABLE_LFS
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# undef O_LARGEFILE
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define O_LARGEFILE 0
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef O_NOFOLLOW
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define O_NOFOLLOW 0
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef O_BINARY
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define O_BINARY 0
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The threadid macro resolves to the thread-id or to 0.  Used for
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** testing and debugging only.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_THREADSAFE
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define threadid pthread_self()
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define threadid 0
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Forward reference */
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int openDirectory(const char*, int*);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Many system calls are accessed through pointer-to-functions so that
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** they may be overridden at runtime to facilitate fault injection during
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** testing and sandboxing.  The following array holds the names and pointers
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to all overrideable system calls.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct unix_syscall {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName;            /* Name of the sytem call */
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_syscall_ptr pDefault; /* Default value */
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} aSyscall[] = {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "open",         (sqlite3_syscall_ptr)open,       0  },
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osOpen      ((int(*)(const char*,int,...))aSyscall[0].pCurrent)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "close",        (sqlite3_syscall_ptr)close,      0  },
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osClose     ((int(*)(int))aSyscall[1].pCurrent)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "access",       (sqlite3_syscall_ptr)access,     0  },
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osAccess    ((int(*)(const char*,int))aSyscall[2].pCurrent)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "getcwd",       (sqlite3_syscall_ptr)getcwd,     0  },
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osGetcwd    ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "stat",         (sqlite3_syscall_ptr)stat,       0  },
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osStat      ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The DJGPP compiler environment looks mostly like Unix, but it
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lacks the fcntl() system call.  So redefine fcntl() to be something
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that always succeeds.  This means that locking does not occur under
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** DJGPP.  But it is DOS - what did you expect?
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __DJGPP__
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "fstat",        0,                 0  },
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osFstat(a,b,c)    0
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "fstat",        (sqlite3_syscall_ptr)fstat,      0  },
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osFstat     ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "ftruncate",    (sqlite3_syscall_ptr)ftruncate,  0  },
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "fcntl",        (sqlite3_syscall_ptr)fcntl,      0  },
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osFcntl     ((int(*)(int,int,...))aSyscall[7].pCurrent)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "read",         (sqlite3_syscall_ptr)read,       0  },
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osRead      ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pread",        (sqlite3_syscall_ptr)pread,      0  },
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pread",        (sqlite3_syscall_ptr)0,          0  },
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osPread     ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_PREAD64)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pread64",      (sqlite3_syscall_ptr)pread64,    0  },
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pread64",      (sqlite3_syscall_ptr)0,          0  },
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osPread64   ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "write",        (sqlite3_syscall_ptr)write,      0  },
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osWrite     ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_PREAD) || defined(SQLITE_ENABLE_LOCKING_STYLE)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pwrite",       (sqlite3_syscall_ptr)pwrite,     0  },
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pwrite",       (sqlite3_syscall_ptr)0,          0  },
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osPwrite    ((ssize_t(*)(int,const void*,size_t,off_t))\
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    aSyscall[12].pCurrent)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_PREAD64)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pwrite64",     (sqlite3_syscall_ptr)pwrite64,   0  },
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "pwrite64",     (sqlite3_syscall_ptr)0,          0  },
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    aSyscall[13].pCurrent)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "fchmod",       (sqlite3_syscall_ptr)fchmod,     0  },
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "fchmod",       (sqlite3_syscall_ptr)0,          0  },
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "fallocate",    (sqlite3_syscall_ptr)posix_fallocate,  0 },
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "fallocate",    (sqlite3_syscall_ptr)0,                0 },
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "unlink",       (sqlite3_syscall_ptr)unlink,           0 },
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osUnlink    ((int(*)(const char*))aSyscall[16].pCurrent)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "openDirectory",    (sqlite3_syscall_ptr)openDirectory,      0 },
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; /* End of the overrideable system calls */
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This is the xSetSystemCall() method of sqlite3_vfs for all of the
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** "unix" VFSes.  Return SQLITE_OK opon successfully updating the
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** system call pointer, or SQLITE_NOTFOUND if there is no configurable
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** system call named zName.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixSetSystemCall(
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pNotUsed,        /* The VFS pointer.  Not used */
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName,            /* Name of system call to override */
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_syscall_ptr pNewFunc  /* Pointer to new system call value */
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int i;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_NOTFOUND;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pNotUsed);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zName==0 ){
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If no zName is given, restore all system calls to their default
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** settings and return NULL
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( aSyscall[i].pDefault ){
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aSyscall[i].pCurrent = aSyscall[i].pDefault;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If zName is specified, operate on only the one system call
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** specified.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( strcmp(zName, aSyscall[i].zName)==0 ){
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( aSyscall[i].pDefault==0 ){
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          aSyscall[i].pDefault = aSyscall[i].pCurrent;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_OK;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        aSyscall[i].pCurrent = pNewFunc;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the value of a system call.  Return NULL if zName is not a
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** recognized system call name.  NULL is also returned if the system call
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is currently undefined.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_syscall_ptr unixGetSystemCall(
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pNotUsed,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int i;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pNotUsed);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the name of the first system call after zName.  If zName==NULL
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** then return the name of the first system call.  Return NULL if zName
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is the last system call or if zName is not the name of a valid
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** system call.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i = -1;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(p);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zName ){
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<ArraySize(aSyscall)-1; i++){
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( strcmp(zName, aSyscall[i].zName)==0 ) break;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i++; i<ArraySize(aSyscall); i++){
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Retry open() calls that fail due to EINTR
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int robust_open(const char *z, int f, int m){
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ rc = osOpen(z,f,m); }while( rc<0 && errno==EINTR );
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Helper functions to obtain and relinquish the global mutex. The
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** global mutex is used to protect the unixInodeInfo and
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** vxworksFileId objects used by this file, all of which may be
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** shared by multiple threads.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Function unixMutexHeld() is used to assert() that the global mutex
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is held when required. This function is only used as part of assert()
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** statements. e.g.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   unixEnterMutex()
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     assert( unixMutexHeld() );
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   unixEnterLeave()
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void unixEnterMutex(void){
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void unixLeaveMutex(void){
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixMutexHeld(void) {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Helper function for printing out trace information from debugging
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** binaries. This returns the string represetation of the supplied
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** integer lock-type.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char *azFileLock(int eFileLock){
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( eFileLock ){
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NO_LOCK: return "NONE";
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SHARED_LOCK: return "SHARED";
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RESERVED_LOCK: return "RESERVED";
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PENDING_LOCK: return "PENDING";
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case EXCLUSIVE_LOCK: return "EXCLUSIVE";
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "ERROR";
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_LOCK_TRACE
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Print out information about all locking operations.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine is used for troubleshooting locks on multithreaded
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** platforms.  Enable by compiling with the -DSQLITE_LOCK_TRACE
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** command-line option on the compiler.  This code is normally
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** turned off.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int lockTrace(int fd, int op, struct flock *p){
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zOpName, *zType;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int s;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int savedErrno;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( op==F_GETLK ){
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zOpName = "GETLK";
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( op==F_SETLK ){
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zOpName = "SETLK";
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s = osFcntl(fd, op, p);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->l_type==F_RDLCK ){
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zType = "RDLCK";
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( p->l_type==F_WRLCK ){
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zType = "WRLCK";
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( p->l_type==F_UNLCK ){
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zType = "UNLCK";
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( 0 );
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( p->l_whence==SEEK_SET );
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s = osFcntl(fd, op, p);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  savedErrno = errno;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     (int)p->l_pid, s);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct flock l2;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l2 = *p;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    osFcntl(fd, F_GETLK, &l2);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( l2.l_type==F_RDLCK ){
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zType = "RDLCK";
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else if( l2.l_type==F_WRLCK ){
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zType = "WRLCK";
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else if( l2.l_type==F_UNLCK ){
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zType = "UNLCK";
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( 0 );
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errno = savedErrno;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef osFcntl
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define osFcntl lockTrace
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_LOCK_TRACE */
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Retry ftruncate() calls that fail due to EINTR
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int robust_ftruncate(int h, sqlite3_int64 sz){
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine translates a standard POSIX errno code into something
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** useful to the clients of the sqlite3 functions.  Specifically, it is
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** intended to translate a variety of "try again" errors into SQLITE_BUSY
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and a variety of "please close the file descriptor NOW" errors into
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLITE_IOERR
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Errors during initialization of locks, or file system support for locks,
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (posixError) {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* At one point this code was not commented out. In theory, this branch
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** should never be hit, as this function should only be called after
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** a locking-related function (i.e. fcntl()) has returned non-zero with
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the value of errno as the first argument. Since a system call has failed,
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** errno should be non-zero.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Despite this, if errno really is zero, we still don't want to return
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** SQLITE_OK. The system call failed, and *some* SQLite error should be
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** propagated back to the caller. Commenting this branch out means errno==0
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** will be handled by the "default:" case below.
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case 0:
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EAGAIN:
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ETIMEDOUT:
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EBUSY:
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EINTR:
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENOLCK:
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* random NFS retry error, unless during file system support
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * introspection, in which it actually means what it says */
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_BUSY;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EACCES:
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* EACCES is like EAGAIN during locking operations, but not any other time*/
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_BUSY;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* else fall through */
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EPERM:
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_PERM;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** this module never makes such a call. And the code in SQLite itself
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** this case is also commented out. If the system does set errno to EDEADLK,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the default SQLITE_IOERR_XXX code will be returned. */
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EDEADLK:
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_BLOCKED;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if EOPNOTSUPP!=ENOTSUP
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EOPNOTSUPP:
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* something went terribly awry, unless during file system support
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * introspection, in which it actually means what it says */
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef ENOTSUP
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENOTSUP:
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* invalid fd, unless during file system support introspection, in which
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * it actually means what it says */
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EIO:
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EBADF:
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case EINVAL:
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENOTCONN:
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENODEV:
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENXIO:
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENOENT:
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ESTALE:
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case ENOSYS:
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* these should force the client to close the file and reconnect */
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default:
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sqliteIOErr;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)****************** Begin Unique File ID Utility Used By VxWorks ***************
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** On most versions of unix, we can get a unique ID for a file by concatenating
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the device number and the inode number.  But this does not work on VxWorks.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** On VxWorks, a unique file id must be based on the canonical filename.
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A pointer to an instance of the following structure can be used as a
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** unique file ID in VxWorks.  Each instance of this structure contains
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a copy of the canonical filename.  There is also a reference count.
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The structure is reclaimed when the number of pointers to it drops to
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** zero.
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** There are never very many files open at one time and lookups are not
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a performance-critical path, so it is sufficient to put these
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** structures on a linked list.
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct vxworksFileId {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct vxworksFileId *pNext;  /* Next in a list of them all */
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRef;                     /* Number of references to this one */
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nName;                    /* Length of the zCanonicalName[] string */
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zCanonicalName;         /* Canonical filename */
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All unique filenames are held on a linked list headed by this
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** variable:
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct vxworksFileId *vxworksFileList = 0;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Simplify a filename into its canonical form
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by making the following changes:
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  * removing any trailing and duplicate /
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  * convert /./ into just /
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  * convert /A/../ where A is any simple name into just /
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Changes are made in-place.  Return the new name length.
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The original filename is in z[0..n-1].  Return the number of
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** characters in the simplified name.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int vxworksSimplifyName(char *z, int n){
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, j;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( n>1 && z[n-1]=='/' ){ n--; }
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=j=0; i<n; i++){
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( z[i]=='/' ){
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( z[i+1]=='/' ) continue;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i += 1;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while( j>0 && z[j-1]!='/' ){ j--; }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( j>0 ){ j--; }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i += 2;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    z[j++] = z[i];
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z[j] = 0;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return j;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Find a unique file ID for the given absolute pathname.  Return
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a pointer to the vxworksFileId object.  This pointer is the unique
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file ID.
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The nRef field of the vxworksFileId object is incremented before
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the object is returned.  A new vxworksFileId object is created
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and added to the global list if necessary.
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If a memory allocation error occurs, return NULL.
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct vxworksFileId *pNew;         /* search key and new file ID */
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct vxworksFileId *pCandidate;   /* For looping over existing file IDs */
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n;                              /* Length of zAbsoluteName string */
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( zAbsoluteName[0]=='/' );
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  n = (int)strlen(zAbsoluteName);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNew==0 ) return 0;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->zCanonicalName = (char*)&pNew[1];
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  n = vxworksSimplifyName(pNew->zCanonicalName, n);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Search for an existing entry that matching the canonical name.
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** If found, increment the reference count and return a pointer to
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the existing file ID.
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pCandidate->nName==n
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ){
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       sqlite3_free(pNew);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       pCandidate->nRef++;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       unixLeaveMutex();
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       return pCandidate;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* No match was found.  We will make a new file ID */
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->nRef = 1;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->nName = n;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->pNext = vxworksFileList;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  vxworksFileList = pNew;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pNew;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Decrement the reference count on a vxworksFileId object.  Free
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the object when the reference count reaches zero.
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void vxworksReleaseFileId(struct vxworksFileId *pId){
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pId->nRef>0 );
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pId->nRef--;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pId->nRef==0 ){
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct vxworksFileId **pp;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( *pp==pId );
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pp = pId->pNext;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pId);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* OS_VXWORKS */
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*************** End of Unique File ID Utility Used By VxWorks ****************
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************** Posix Advisory Locking ****************************
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** POSIX advisory locks are broken by design.  ANSI STD 1003.1 (1996)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** section 6.5.2.2 lines 483 through 490 specify that when a process
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sets or clears a lock, that operation overrides any prior locks set
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by the same process.  It does not explicitly say so, but this implies
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that it overrides locks set by the same process using a different
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file descriptor.  Consider this test case:
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Suppose ./file1 and ./file2 are really the same file (because
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** one is a hard or symbolic link to the other) then if you set
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an exclusive lock on fd1, then try to get an exclusive lock
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on fd2, it works.  I would have expected the second lock to
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** fail since there was already a lock on the file due to fd1.
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** But not so.  Since both locks came from the same process, the
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** second overrides the first, even though they were on different
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file descriptors opened on different file names.
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This means that we cannot use POSIX locks to synchronize file access
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** among competing threads of the same process.  POSIX locks will work fine
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to synchronize access for threads in separate processes, but not
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** threads within the same process.
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** To work around the problem, SQLite has to manage file locks internally
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on its own.  Whenever a new database is opened, we have to find the
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** specific inode of the database file (the inode is determined by the
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** st_dev and st_ino fields of the stat structure that fstat() fills in)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and check for locks already existing on that inode.  When locks are
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** created or removed, we have to look at our own internal record of the
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** locks to see if another thread has previously set a lock on that same
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** inode.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For VxWorks, we have to use the alternative unique ID system based on
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** canonical filename and implemented in the previous division.)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The sqlite3_file structure for POSIX is no longer just an integer file
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** descriptor.  It is now a structure that holds the integer file
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** descriptor and a pointer to a structure that describes the internal
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** locks on the corresponding inode.  There is one locking structure
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** per inode, so if the same inode is opened twice, both unixFile structures
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** point to the same locking structure.  The locking structure keeps
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a reference count (so we will know when to delete it) and a "cnt"
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** field that tells us its internal lock status.  cnt==0 means the
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file is unlocked.  cnt==-1 means the file has an exclusive lock.
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** cnt>0 means there are cnt shared locks on the file.
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Any attempt to lock or unlock a file first checks the locking
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** structure.  The fcntl() system call is only invoked to set a
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** POSIX lock if the internal lock structure transitions between
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a locked and an unlocked state.
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** But wait:  there are yet more problems with POSIX advisory locks.
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If you close a file descriptor that points to a file that has locks,
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** all locks on that file that are owned by the current process are
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** released.  To work around this problem, each unixInodeInfo object
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** maintains a count of the number of pending locks on tha inode.
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When an attempt is made to close an unixFile, if there are
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** other unixFile open on the same inode that are holding locks, the call
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to close() the file descriptor is deferred until all of the locks clear.
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The unixInodeInfo structure keeps a list of file descriptors that need to
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** be closed and that list is walked (and cleared) when the last lock
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** clears.
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Yet another problem:  LinuxThreads do not play well with posix locks.
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Many older versions of linux use the LinuxThreads library which is
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** not posix compliant.  Under LinuxThreads, a lock created by thread
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A cannot be modified or overridden by a different thread B.
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Only thread A can modify the lock.  Locking behavior is correct
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** if the appliation uses the newer Native Posix Thread Library (NPTL)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on linux - with NPTL a lock created by thread A can override locks
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in thread B.  But there is no way to know at compile-time which
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** threading library is being used.  So there is no way to know at
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** compile-time whether or not thread A can override locks on thread B.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** One has to do a run-time check to discover the behavior of the
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** current process.
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLite used to support LinuxThreads.  But support for LinuxThreads
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** was dropped beginning with version 3.7.0.  SQLite will still work with
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** LinuxThreads provided that (1) there is no more than one connection
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** per database file in the same process and (2) database connections
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** do not move across threads.
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An instance of the following structure serves as the key used
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to locate a particular unixInodeInfo object.
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct unixFileId {
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dev_t dev;                  /* Device number */
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct vxworksFileId *pId;  /* Unique file ID for vxworks. */
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ino_t ino;                  /* Inode number */
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An instance of the following structure is allocated for each open
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** inode.  Or, on LinuxThreads, there is one of these structures for
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** each inode opened by each thread.
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A single inode can have multiple file descriptors, so each unixFile
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** structure contains a pointer to an instance of this object and this
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** object keeps a count of the number of unixFile pointing to it.
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct unixInodeInfo {
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct unixFileId fileId;       /* The lookup key */
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nShared;                    /* Number of SHARED locks held */
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char eFileLock;        /* One of SHARED_LOCK, RESERVED_LOCK etc. */
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char bProcessLock;     /* An exclusive process lock is held */
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRef;                       /* Number of pointers to this structure */
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmNode *pShmNode;          /* Shared memory associated with this inode */
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nLock;                      /* Number of outstanding file locks */
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *pUnused;          /* Unused file descriptors to close */
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pPrev;           /*    .... doubly linked */
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SQLITE_ENABLE_LOCKING_STYLE)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long sharedByte;  /* for AFP simulated shared lock */
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sem_t *pSem;                    /* Named POSIX semaphore */
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A lists of all unixInodeInfo objects.
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unixInodeInfo *inodeList = 0;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function - unixLogError_x(), is only ever called via the macro
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** unixLogError().
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is invoked after an error occurs in an OS function and errno has been
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** set. It logs a message using sqlite3_log() containing the current value of
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** errno and, if possible, the human-readable equivalent from strerror() or
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** strerror_r().
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The first argument passed to the macro should be the error code that
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The two subsequent arguments should be the name of the OS function that
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** failed (e.g. "unlink", "open") and the the associated file-system path,
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** if any.
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define unixLogError(a,b,c)     unixLogErrorAtLine(a,b,c,__LINE__)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixLogErrorAtLine(
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int errcode,                    /* SQLite error code */
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zFunc,              /* Name of OS function that failed */
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,              /* File path associated with error */
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iLine                       /* Source line number where error occurred */
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zErr;                     /* Message from strerror() or equivalent */
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iErrno = errno;             /* Saved syscall error number */
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the strerror() function to obtain the human-readable error message
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** equivalent to errno. Otherwise, use strerror_r().
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char aErr[80];
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(aErr, 0, sizeof(aErr));
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zErr = aErr;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** assume that the system provides the the GNU version of strerror_r() that
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** returns a pointer to a buffer containing the error message. That pointer
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** may point to aErr[], or it may point to some static storage somewhere.
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Otherwise, assume that the system provides the POSIX version of
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** strerror_r(), which always writes an error message into aErr[].
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** If the code incorrectly assumes that it is the POSIX version that is
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** available, the error message will often be an empty string. Not a
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** huge problem. Incorrectly concluding that the GNU version is available
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** could lead to a segfault though.
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zErr =
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strerror_r(iErrno, aErr, sizeof(aErr)-1);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif SQLITE_THREADSAFE
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* This is a threadsafe build, but strerror_r() is not available. */
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zErr = "";
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Non-threadsafe build, use strerror(). */
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zErr = strerror(iErrno);
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( errcode!=SQLITE_OK );
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zPath==0 ) zPath = "";
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_log(errcode,
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "os_unix.c:%d: (%d) %s(%s) - %s",
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iLine, iErrno, zFunc, zPath, zErr
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return errcode;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file descriptor.
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** We assume that close() almost always works, since it is only in a
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** very sick application or on a very sick platform that it might fail.
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If it does fail, simply leak the file descriptor, but do log the
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** error.
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Note that it is not safe to retry close() after EINTR since the
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file descriptor might have already been reused by another thread.
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** So we don't even try to recover from an EINTR.  Just log the error
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and move on.
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void robust_close(unixFile *pFile, int h, int lineno){
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( osClose(h) ){
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       pFile ? pFile->zPath : 0, lineno);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void closePendingFds(unixFile *pFile){
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode = pFile->pInode;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *p;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *pNext;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(p=pInode->pUnused; p; p=pNext){
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNext = p->pNext;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    robust_close(pFile, p->fd, __LINE__);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode->pUnused = 0;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Release a unixInodeInfo structure previously allocated by findInodeInfo().
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The mutex entered using the unixEnterMutex() function must be held
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** when this function is called.
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void releaseInodeInfo(unixFile *pFile){
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode = pFile->pInode;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( unixMutexHeld() );
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( ALWAYS(pInode) ){
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nRef--;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode->nRef==0 ){
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( pInode->pShmNode==0 );
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closePendingFds(pFile);
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pInode->pPrev ){
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( pInode->pPrev->pNext==pInode );
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pInode->pPrev->pNext = pInode->pNext;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( inodeList==pInode );
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        inodeList = pInode->pNext;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pInode->pNext ){
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( pInode->pNext->pPrev==pInode );
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pInode->pNext->pPrev = pInode->pPrev;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(pInode);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Given a file descriptor, locate the unixInodeInfo object that
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** describes that file descriptor.  Create a new one if necessary.  The
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** return value might be uninitialized if an error occurs.
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The mutex entered using the unixEnterMutex() function must be held
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** when this function is called.
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return an appropriate error code.
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int findInodeInfo(
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile,               /* Unix file with file desc used in the key */
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo **ppInode        /* Return the unixInodeInfo object here */
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                        /* System call return code */
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd;                        /* The file descriptor for pFile */
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct unixFileId fileId;      /* Lookup key for the unixInodeInfo */
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat statbuf;           /* Low-level file information */
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode = 0;     /* Candidate unixInodeInfo object */
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( unixMutexHeld() );
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Get low-level information about the file that we can used to
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** create a unique name for the file.
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd = pFile->h;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = osFstat(fd, &statbuf);
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=0 ){
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = errno;
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EOVERFLOW
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR;
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __APPLE__
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* On OS X on an msdos filesystem, the inode number is reported
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** incorrectly for zero-size files.  See ticket #3260.  To work
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** around this problem (we consider it a bug in OS X, not SQLite)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** we always increase the file size to 1 by writing a single byte
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** prior to accessing the inode number.  The one byte written is
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** an ASCII 'S' character which also happens to be the first byte
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** in the header of every SQLite database.  In this way, if there
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** is a race condition such that another thread has already populated
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the first page of the database, no damage is done.
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=1 ){
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = errno;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_IOERR;
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = osFstat(fd, &statbuf);
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=0 ){
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = errno;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_IOERR;
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&fileId, 0, sizeof(fileId));
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fileId.dev = statbuf.st_dev;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fileId.pId = pFile->pId;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fileId.ino = statbuf.st_ino;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode = inodeList;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode = pInode->pNext;
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pInode==0 ){
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode = sqlite3_malloc( sizeof(*pInode) );
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode==0 ){
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pInode, 0, sizeof(*pInode));
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&pInode->fileId, &fileId, sizeof(fileId));
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nRef = 1;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->pNext = inodeList;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->pPrev = 0;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( inodeList ) inodeList->pPrev = pInode;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inodeList = pInode;
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nRef++;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppInode = pInode;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, set *pResOut
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to a non-zero value otherwise *pResOut is set to zero.  The return value
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to SQLITE_OK unless an I/O error occurs during lock checking.
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reserved = 0;
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check if a thread in this process holds such a lock */
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->pInode->eFileLock>SHARED_LOCK ){
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reserved = 1;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Otherwise see if some other process holds it.
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __DJGPP__
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !reserved && !pFile->pInode->bProcessLock ){
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct flock lock;
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_whence = SEEK_SET;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_start = RESERVED_BYTE;
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_len = 1;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_type = F_WRLCK;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( osFcntl(pFile->h, F_GETLK, &lock) ){
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = errno;
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if( lock.l_type!=F_UNLCK ){
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reserved = 1;
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = reserved;
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Attempt to set a system-lock on the file pFile.  The lock is
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** described by pLock.
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the pFile was opened read/write from unix-excl, then the only lock
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ever obtained is an exclusive lock, and it is obtained exactly once
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the first time any lock is attempted.  All subsequent system locking
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** operations become no-ops.  Locking operations still happen internally,
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in order to coordinate access between separate database connections
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** within this process, but all of that is handled in memory and the
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** operating system does not participate.
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is a pass-through to fcntl(F_SETLK) if pFile is using
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and is read-only.
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Zero is returned if the call completes successfully, or -1 if a call
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixFileLock(unixFile *pFile, struct flock *pLock){
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode = pFile->pInode;
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( unixMutexHeld() );
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pInode!=0 );
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( ((pFile->ctrlFlags & UNIXFILE_EXCL)!=0 || pInode->bProcessLock)
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   && ((pFile->ctrlFlags & UNIXFILE_RDONLY)==0)
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode->bProcessLock==0 ){
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct flock lock;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( pInode->nLock==0 );
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_whence = SEEK_SET;
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_start = SHARED_FIRST;
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_len = SHARED_SIZE;
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_type = F_WRLCK;
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = osFcntl(pFile->h, F_SETLK, &lock);
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc<0 ) return rc;
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->bProcessLock = 1;
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->nLock++;
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = 0;
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = osFcntl(pFile->h, F_SETLK, pLock);
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter eFileLock - one
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following:
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (1) SHARED_LOCK
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (2) RESERVED_LOCK
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (3) PENDING_LOCK
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (4) EXCLUSIVE_LOCK
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between.  The locking might fail on one of the later
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal.  The following chart shows the allowed
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states:
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    UNLOCKED -> SHARED
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> RESERVED
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> (PENDING) -> EXCLUSIVE
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    RESERVED -> (PENDING) -> EXCLUSIVE
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    PENDING -> EXCLUSIVE
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock.  Use the sqlite3OsUnlock()
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** routine to lower a locking level.
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixLock(sqlite3_file *id, int eFileLock){
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The following describes the implementation of the various locks and
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** lock transitions in terms of the POSIX advisory shared and exclusive
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** lock primitives (called read-locks and write-locks below, to avoid
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** confusion with SQLite lock names). The algorithms are complicated
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** slightly in order to be compatible with windows systems simultaneously
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** accessing the same database file, in case that is ever required.
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** byte', each single bytes at well known offsets, and the 'shared byte
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** range', a range of 510 bytes at a well known offset.
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** To obtain a SHARED lock, a read-lock is obtained on the 'pending
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** byte'.  If this is successful, a random byte from the 'shared byte
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** range' is read-locked and the lock on the 'pending byte' released.
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** A process may only obtain a RESERVED lock after it has a SHARED lock.
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** A RESERVED lock is implemented by grabbing a write-lock on the
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** 'reserved byte'.
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** A process may only obtain a PENDING lock after it has obtained a
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** on the 'pending byte'. This ensures that no new SHARED locks can be
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** obtained, but existing SHARED locks are allowed to persist. A process
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** does not have to obtain a RESERVED lock on the way to a PENDING lock.
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** This property is used by the algorithm for rolling back a journal file
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** after a crash.
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** implemented by obtaining a write-lock on the entire 'shared byte
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** range'. Since all other locks require a read-lock on one of the bytes
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** within this range, this ensures that no other locks are held on the
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** database.
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** The reason a single byte cannot be used instead of the 'shared byte
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** range' is that some versions of windows do not support read-locks. By
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** locking a random byte from a range, concurrent SHARED locks may exist
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** even if the locking primitive used is always a write-lock.
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode = pFile->pInode;
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct flock lock;
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tErrno = 0;
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      azFileLock(eFileLock), azFileLock(pFile->eFileLock),
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If there is already a lock of this type or more restrictive on the
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** unixFile, do nothing. Don't use the end_lock: exit path, as
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** unixEnterMutex() hasn't been called yet.
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock>=eFileLock ){
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            azFileLock(eFileLock)));
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Make sure the locking sequence is correct.
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **  (1) We never move from unlocked to anything higher than shared lock.
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **  (2) SQLite never explicitly requests a pendig lock.
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **  (3) A shared lock is always held when a reserve lock is requested.
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock!=PENDING_LOCK );
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* This mutex is needed because pFile->pInode is shared across threads
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode = pFile->pInode;
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If some thread using this PID has a lock via a different unixFile*
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** handle that precludes the requested lock, return BUSY.
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (pFile->eFileLock!=pInode->eFileLock &&
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_lock;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If a SHARED lock is requested, and some thread using this PID already
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** has a SHARED or RESERVED lock, then increment reference counts and
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** return SQLITE_OK.
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==SHARED_LOCK &&
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( eFileLock==SHARED_LOCK );
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile->eFileLock==0 );
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->nShared>0 );
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = SHARED_LOCK;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nShared++;
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nLock++;
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_lock;
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* A PENDING lock is needed before acquiring a SHARED lock and before
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** be released.
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock.l_len = 1L;
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock.l_whence = SEEK_SET;
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==SHARED_LOCK
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_start = PENDING_BYTE;
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( unixFileLock(pFile, &lock) ){
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tErrno = errno;
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_BUSY ){
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = tErrno;
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto end_lock;
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If control gets to this point, then actually go ahead and make
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** operating system calls for the specified lock.
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==SHARED_LOCK ){
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->nShared==0 );
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->eFileLock==0 );
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( rc==SQLITE_OK );
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Now get the read-lock */
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_start = SHARED_FIRST;
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_len = SHARED_SIZE;
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( unixFileLock(pFile, &lock) ){
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tErrno = errno;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Drop the temporary PENDING lock */
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_start = PENDING_BYTE;
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_len = 1L;
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_type = F_UNLCK;
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* This could happen with a network mount */
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tErrno = errno;
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_UNLOCK;
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc ){
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_BUSY ){
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = tErrno;
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto end_lock;
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->eFileLock = SHARED_LOCK;
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->nLock++;
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->nShared = 1;
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* We are trying for an exclusive lock but another thread in this
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** same process is still holding a shared lock. */
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The request was for a RESERVED or EXCLUSIVE lock.  It is
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** assumed that there is a SHARED or greater lock on the file
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** already.
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( 0!=pFile->eFileLock );
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_type = F_WRLCK;
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( eFileLock==RESERVED_LOCK ){
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_start = RESERVED_BYTE;
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_len = 1L;
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_start = SHARED_FIRST;
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_len = SHARED_SIZE;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( unixFileLock(pFile, &lock) ){
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tErrno = errno;
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_BUSY ){
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = tErrno;
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Set up the transaction-counter change checking flags when
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** transitioning from a SHARED to a RESERVED lock.  The change
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** from SHARED to RESERVED marks the beginning of a normal
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** write operation (not a hot journal rollback).
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   && pFile->eFileLock<=SHARED_LOCK
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   && eFileLock==RESERVED_LOCK
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->transCntrChng = 0;
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->dbUpdate = 0;
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->inNormalWrite = 1;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->eFileLock = eFileLock;
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( eFileLock==EXCLUSIVE_LOCK ){
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = PENDING_LOCK;
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->eFileLock = PENDING_LOCK;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)end_lock:
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("LOCK    %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc==SQLITE_OK ? "ok" : "failed"));
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Add the file descriptor used by file handle pFile to the corresponding
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pUnused list.
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void setPendingFd(unixFile *pFile){
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode = pFile->pInode;
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *p = pFile->pUnused;
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pNext = pInode->pUnused;
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode->pUnused = p;
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->h = -1;
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->pUnused = 0;
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the byte range is divided into 2 parts and the first part is unlocked then
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** set to a read lock, then the other part is simply unlocked.  This works
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** remove the write lock on a region when a read lock is set.
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode;
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct flock lock;
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int h;
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      getpid()));
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock<=SHARED_LOCK );
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock<=eFileLock ){
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  h = pFile->h;
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode = pFile->pInode;
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pInode->nShared!=0 );
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock>SHARED_LOCK ){
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->eFileLock==pFile->eFileLock );
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimulateIOErrorBenign(1);
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimulateIOError( h=(-1) )
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimulateIOErrorBenign(0);
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* When reducing a lock such that other processes can start
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** reading the database file again, make sure that the
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** transaction counter was updated if any part of the database
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** file changed.  If the transaction counter is not updated,
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** other connections to the same file might not realize that
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the file has changed and hence might not know to flush their
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** cache.  The use of a stale cache can lead to database corruption.
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile->inNormalWrite==0
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         || pFile->dbUpdate==0
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         || pFile->transCntrChng==1 );
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->inNormalWrite = 0;
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* downgrading to a shared lock on NFS involves clearing the write lock
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** before establishing the readlock - to avoid a race condition we downgrade
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the lock in 2 blocks, so that part of the range will be covered by a
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** write lock until the rest is covered by a read lock:
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **  1:   [WWWWW]
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **  2:   [....W]
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **  3:   [RRRRW]
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **  4:   [RRRR.]
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( eFileLock==SHARED_LOCK ){
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (void)handleNFSUnlock;
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( handleNFSUnlock==0 );
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( handleNFSUnlock ){
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int tErrno;               /* Error code from system call errors */
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        off_t divSize = SHARED_SIZE - 1;
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_type = F_UNLCK;
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_whence = SEEK_SET;
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_start = SHARED_FIRST;
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_len = divSize;
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( unixFileLock(pFile, &lock)==(-1) ){
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tErrno = errno;
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_IOERR_UNLOCK;
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( IS_LOCK_ERROR(rc) ){
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pFile->lastErrno = tErrno;
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto end_unlock;
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_type = F_RDLCK;
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_whence = SEEK_SET;
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_start = SHARED_FIRST;
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_len = divSize;
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( unixFileLock(pFile, &lock)==(-1) ){
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tErrno = errno;
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( IS_LOCK_ERROR(rc) ){
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pFile->lastErrno = tErrno;
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto end_unlock;
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_type = F_UNLCK;
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_whence = SEEK_SET;
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_start = SHARED_FIRST+divSize;
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_len = SHARED_SIZE-divSize;
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( unixFileLock(pFile, &lock)==(-1) ){
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tErrno = errno;
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_IOERR_UNLOCK;
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( IS_LOCK_ERROR(rc) ){
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pFile->lastErrno = tErrno;
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto end_unlock;
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_type = F_RDLCK;
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_whence = SEEK_SET;
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_start = SHARED_FIRST;
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lock.l_len = SHARED_SIZE;
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( unixFileLock(pFile, &lock) ){
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* In theory, the call to unixFileLock() cannot fail because another
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** process is holding an incompatible lock. If it does, this
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** indicates that the other process is not following the locking
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** SQLITE_BUSY would confuse the upper layer (in practice it causes
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** an assert to fail). */
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_IOERR_RDLOCK;
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pFile->lastErrno = errno;
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto end_unlock;
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_type = F_UNLCK;
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_whence = SEEK_SET;
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_start = PENDING_BYTE;
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( unixFileLock(pFile, &lock)==0 ){
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->eFileLock = SHARED_LOCK;
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_UNLOCK;
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = errno;
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto end_unlock;
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==NO_LOCK ){
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Decrement the shared lock counter.  Release the lock using an
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** OS call only when all threads in this same process have released
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the lock.
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nShared--;
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode->nShared==0 ){
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_type = F_UNLCK;
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_whence = SEEK_SET;
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lock.l_start = lock.l_len = 0L;
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(1);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOError( h=(-1) )
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(0);
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( unixFileLock(pFile, &lock)==0 ){
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pInode->eFileLock = NO_LOCK;
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_IOERR_UNLOCK;
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	pFile->lastErrno = errno;
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pInode->eFileLock = NO_LOCK;
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->eFileLock = NO_LOCK;
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Decrement the count of locks against this same file.  When the
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** count reaches zero, close any other file descriptors whose close
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** was deferred because of outstanding locks.
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nLock--;
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->nLock>=0 );
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode->nLock==0 ){
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closePendingFds(pFile);
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)end_unlock:
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixUnlock(sqlite3_file *id, int eFileLock){
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return posixUnlock(id, eFileLock, 0);
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function performs the parts of the "close file" operation
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** common to all locking schemes. It closes the directory and file
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** handles, if they are valid, and sets all fields of the unixFile
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** structure to 0.
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is *not* necessary to hold the mutex when this routine is called,
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** even on VxWorks.  A mutex will be acquired on VxWorks by the
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** vxworksReleaseFileId() routine.
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int closeUnixFile(sqlite3_file *id){
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->h>=0 ){
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    robust_close(pFile, pFile->h, __LINE__);
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->h = -1;
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->pId ){
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pFile->isDelete ){
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      osUnlink(pFile->pId->zCanonicalName);
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    vxworksReleaseFileId(pFile->pId);
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->pId = 0;
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("CLOSE   %-3d\n", pFile->h));
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenCounter(-1);
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pFile->pUnused);
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pFile, 0, sizeof(unixFile));
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file.
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixClose(sqlite3_file *id){
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile *)id;
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixUnlock(id, NO_LOCK);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* unixFile.pInode is always valid here. Otherwise, a different close
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** routine (e.g. nolockClose()) would be called instead.
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If there are outstanding locks, do not actually close the file just
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** yet because that would clear those locks.  Instead, add the file
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** descriptor to pInode->pUnused list.  It will be automatically closed
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** when the last lock is cleared.
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setPendingFd(pFile);
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  releaseInodeInfo(pFile);
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = closeUnixFile(id);
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************** End of the posix advisory lock implementation *****************
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)****************************** No-op Locking **********************************
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Of the various locking implementations available, this is by far the
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** simplest:  locking is ignored.  No attempt is made to lock the database
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file for reading or writing.
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This locking mode is appropriate for use on read-only databases
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (ex: databases that are burned into CD-ROM, for example.)  It can
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** also be used if the application employs some external mechanism to
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** prevent simultaneous access of the same database by two or more
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database connections.  But there is a serious risk of database
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** corruption if this locking mode is used in situations where multiple
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database connections are accessing the same database file at the same
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** time and one or more of those connections are writing.
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = 0;
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER2(NotUsed, NotUsed2);
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER2(NotUsed, NotUsed2);
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close the file.
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nolockClose(sqlite3_file *id) {
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return closeUnixFile(id);
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************* End of the no-op lock implementation *********************
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)************************* Begin dot-file Locking ******************************
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The dotfile locking implementation uses the existance of separate lock
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** files in order to control access to the database.  This works on just
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** about every filesystem imaginable.  But there are serious downsides:
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    (1)  There is zero concurrency.  A single reader blocks all other
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         connections from reading or writing the database.
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    (2)  An application crash or power loss can leave stale lock files
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**         sitting around that need to be cleared manually.
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Nevertheless, a dotlock is an appropriate locking mode for use if no
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** other locking strategy is available.
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Dotfile locking works by creating a file in the same directory as the
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database and with the same name but with a ".lock" extension added.
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The existance of a lock file implies an EXCLUSIVE lock.  All other lock
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The file suffix added to the data base filename in order to create the
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lock file.
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DOTLOCK_SUFFIX ".lock"
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, set *pResOut
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to a non-zero value otherwise *pResOut is set to zero.  The return value
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to SQLITE_OK unless an I/O error occurs during lock checking.
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** In dotfile locking, either a lock exists or it does not.  So in this
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** variation of CheckReservedLock(), *pResOut is set to true if any lock
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is held on the file and false if the file is unlocked.
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reserved = 0;
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check if a thread in this process holds such a lock */
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock>SHARED_LOCK ){
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Either this connection or some other connection in the same process
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** holds a lock on the file.  No need to check further. */
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reserved = 1;
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The lock is held if and only if the lockfile exists */
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *zLockFile = (const char*)pFile->lockingContext;
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reserved = osAccess(zLockFile, 0)==0;
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = reserved;
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter eFileLock - one
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following:
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (1) SHARED_LOCK
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (2) RESERVED_LOCK
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (3) PENDING_LOCK
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (4) EXCLUSIVE_LOCK
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between.  The locking might fail on one of the later
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal.  The following chart shows the allowed
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states:
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    UNLOCKED -> SHARED
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> RESERVED
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> (PENDING) -> EXCLUSIVE
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    RESERVED -> (PENDING) -> EXCLUSIVE
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    PENDING -> EXCLUSIVE
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock.  Use the sqlite3OsUnlock()
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** routine to lower a locking level.
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** With dotfile locking, we really only support state (4): EXCLUSIVE.
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** But we track the other locking levels internally.
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int dotlockLock(sqlite3_file *id, int eFileLock) {
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd;
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zLockFile = (char *)pFile->lockingContext;
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If we have any lock, then the lock file already exists.  All we have
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** to do is adjust our internal record of the lock level.
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock > NO_LOCK ){
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !OS_VXWORKS
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Always update the timestamp on the old file */
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    utimes(zLockFile, NULL);
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* grab an exclusive lock */
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd = robust_open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fd<0 ){
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* failed to open/create the file, someone else may have stolen the lock */
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tErrno = errno;
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( EEXIST == tErrno ){
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_BUSY;
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( IS_LOCK_ERROR(rc) ){
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = tErrno;
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  robust_close(pFile, fd, __LINE__);
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* got it, set the type and return ok */
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->eFileLock = eFileLock;
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When the locking level reaches NO_LOCK, delete the lock file.
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zLockFile = (char *)pFile->lockingContext;
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("UNLOCK  %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   pFile->eFileLock, getpid()));
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock<=SHARED_LOCK );
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* no-op if possible */
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock==eFileLock ){
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* To downgrade to shared, simply update our internal notion of the
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** lock state.  No need to mess with the file on disk.
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==SHARED_LOCK ){
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = SHARED_LOCK;
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* To fully unlock the database, delete the lock file */
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock==NO_LOCK );
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( osUnlink(zLockFile) ){
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc = 0;
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tErrno = errno;
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( ENOENT != tErrno ){
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_UNLOCK;
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( IS_LOCK_ERROR(rc) ){
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = tErrno;
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->eFileLock = NO_LOCK;
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file.  Make sure the lock has been released before closing.
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int dotlockClose(sqlite3_file *id) {
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( id ){
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *pFile = (unixFile*)id;
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dotlockUnlock(id, NO_LOCK);
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pFile->lockingContext);
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = closeUnixFile(id);
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************** End of the dot-file lock implementation *******************
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)************************** Begin flock Locking ********************************
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Use the flock() system call to do file locking.
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** flock() locking is like dot-file locking in that the various
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** fine-grain locking levels supported by SQLite are collapsed into
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a single exclusive lock.  In other words, SHARED, RESERVED, and
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** PENDING locks are the same thing as an EXCLUSIVE lock.  SQLite
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still works when you do this, but concurrency is reduced since
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** only a single process can be reading the database at a time.
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** compiling for VXWORKS.
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Retry flock() calls that fail with EINTR
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef EINTR
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int robust_flock(int fd, int op){
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define robust_flock(a,b) flock(a,b)
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, set *pResOut
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to a non-zero value otherwise *pResOut is set to zero.  The return value
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to SQLITE_OK unless an I/O error occurs during lock checking.
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reserved = 0;
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check if a thread in this process holds such a lock */
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock>SHARED_LOCK ){
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reserved = 1;
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Otherwise see if some other process holds it. */
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !reserved ){
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* attempt to get the lock */
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !lrc ){
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* got the lock, unlock it */
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lrc = robust_flock(pFile->h, LOCK_UN);
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ( lrc ) {
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int tErrno = errno;
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* unlock failed with an error */
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lrc = SQLITE_IOERR_UNLOCK;
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( IS_LOCK_ERROR(lrc) ){
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pFile->lastErrno = tErrno;
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = lrc;
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int tErrno = errno;
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reserved = 1;
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* someone else might have it reserved */
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( IS_LOCK_ERROR(lrc) ){
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = tErrno;
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = lrc;
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reserved=1;
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = reserved;
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter eFileLock - one
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following:
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (1) SHARED_LOCK
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (2) RESERVED_LOCK
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (3) PENDING_LOCK
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (4) EXCLUSIVE_LOCK
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between.  The locking might fail on one of the later
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal.  The following chart shows the allowed
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states:
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    UNLOCKED -> SHARED
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> RESERVED
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> (PENDING) -> EXCLUSIVE
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    RESERVED -> (PENDING) -> EXCLUSIVE
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    PENDING -> EXCLUSIVE
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** flock() only really support EXCLUSIVE locks.  We track intermediate
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lock states in the sqlite3_file structure, but all locks SHARED or
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** above are really EXCLUSIVE locks and exclude all other processes from
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** access the file.
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock.  Use the sqlite3OsUnlock()
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** routine to lower a locking level.
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int flockLock(sqlite3_file *id, int eFileLock) {
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* if we already have a lock, it is exclusive.
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Just adjust level and punt on outta here. */
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pFile->eFileLock > NO_LOCK) {
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* grab an exclusive lock */
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tErrno = errno;
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* didn't get, must be busy */
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( IS_LOCK_ERROR(rc) ){
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = tErrno;
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* got it, set the type and return ok */
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("LOCK    %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           rc==SQLITE_OK ? "ok" : "failed"));
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int flockUnlock(sqlite3_file *id, int eFileLock) {
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("UNLOCK  %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pFile->eFileLock, getpid()));
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock<=SHARED_LOCK );
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* no-op if possible */
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock==eFileLock ){
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* shared can just be set because we always have an exclusive */
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (eFileLock==SHARED_LOCK) {
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* no, really, unlock. */
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( robust_flock(pFile->h, LOCK_UN) ){
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_UNLOCK;
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = NO_LOCK;
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file.
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int flockClose(sqlite3_file *id) {
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( id ){
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flockUnlock(id, NO_LOCK);
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return closeUnixFile(id);
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************* End of the flock lock implementation *********************
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)************************ Begin Named Semaphore Locking ************************
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Named semaphore locking is only supported on VxWorks.
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Semaphore locking is like dot-lock and flock in that it really only
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** supports EXCLUSIVE locking.  Only a single process can read or write
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the database file at a time.  This reduces potential concurrency, but
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** makes the lock implementation much easier.
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, set *pResOut
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to a non-zero value otherwise *pResOut is set to zero.  The return value
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to SQLITE_OK unless an I/O error occurs during lock checking.
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reserved = 0;
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check if a thread in this process holds such a lock */
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock>SHARED_LOCK ){
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reserved = 1;
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Otherwise see if some other process holds it. */
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !reserved ){
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sem_t *pSem = pFile->pInode->pSem;
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct stat statBuf;
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( sem_trywait(pSem)==-1 ){
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int tErrno = errno;
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( EAGAIN != tErrno ){
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = tErrno;
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* someone else has the lock when we are in NO_LOCK */
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reserved = (pFile->eFileLock < SHARED_LOCK);
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* we could have it if we want it */
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sem_post(pSem);
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = reserved;
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter eFileLock - one
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following:
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (1) SHARED_LOCK
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (2) RESERVED_LOCK
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (3) PENDING_LOCK
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (4) EXCLUSIVE_LOCK
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between.  The locking might fail on one of the later
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal.  The following chart shows the allowed
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states:
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    UNLOCKED -> SHARED
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> RESERVED
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> (PENDING) -> EXCLUSIVE
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    RESERVED -> (PENDING) -> EXCLUSIVE
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    PENDING -> EXCLUSIVE
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Semaphore locks only really support EXCLUSIVE locks.  We track intermediate
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lock states in the sqlite3_file structure, but all locks SHARED or
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** above are really EXCLUSIVE locks and exclude all other processes from
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** access the file.
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock.  Use the sqlite3OsUnlock()
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** routine to lower a locking level.
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int semLock(sqlite3_file *id, int eFileLock) {
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd;
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sem_t *pSem = pFile->pInode->pSem;
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* if we already have a lock, it is exclusive.
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Just adjust level and punt on outta here. */
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pFile->eFileLock > NO_LOCK) {
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto sem_end_lock;
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* lock semaphore now but bail out when already locked. */
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sem_trywait(pSem)==-1 ){
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto sem_end_lock;
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* got it, set the type and return ok */
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->eFileLock = eFileLock;
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sem_end_lock:
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int semUnlock(sqlite3_file *id, int eFileLock) {
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sem_t *pSem = pFile->pInode->pSem;
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pSem );
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("UNLOCK  %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   pFile->eFileLock, getpid()));
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock<=SHARED_LOCK );
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* no-op if possible */
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock==eFileLock ){
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* shared can just be set because we always have an exclusive */
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (eFileLock==SHARED_LOCK) {
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* no, really unlock. */
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ( sem_post(pSem)==-1 ) {
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc, tErrno = errno;
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( IS_LOCK_ERROR(rc) ){
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = tErrno;
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->eFileLock = NO_LOCK;
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Close a file.
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int semClose(sqlite3_file *id) {
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( id ){
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *pFile = (unixFile*)id;
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    semUnlock(id, NO_LOCK);
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile );
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixEnterMutex();
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    releaseInodeInfo(pFile);
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixLeaveMutex();
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    closeUnixFile(id);
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* OS_VXWORKS */
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Named semaphore locking is only available on VxWorks.
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************** End of the named semaphore lock implementation ****************
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************** Begin AFP Locking *********************************
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** AFP is the Apple Filing Protocol.  AFP is a network filesystem found
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on Apple Macintosh computers - both OS9 and OSX.
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Third-party implementations of AFP are available.  But this code here
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** only works on OSX.
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The afpLockingContext structure contains all afp lock specific state
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct afpLockingContext afpLockingContext;
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct afpLockingContext {
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reserved;
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *dbPath;             /* Name of the open file */
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ByteRangeLockPB2
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long offset;        /* offset to first byte to lock */
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long length;        /* nbr of bytes to lock */
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char unLockFlag;         /* 1 = unlock, 0 = lock */
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char startEndFlag;       /* 1=rel to end of fork, 0=rel to start */
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd;                           /* file desc to assoc this lock with */
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define afpfsByteRangeLock2FSCTL        _IOWR('z', 23, struct ByteRangeLockPB2)
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This is a utility for setting or clearing a bit-range lock on an
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** AFP filesystem.
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return SQLITE_OK on success, SQLITE_BUSY on failure.
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int afpSetLock(
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *path,              /* Name of the file to be locked or unlocked */
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile,               /* Open file descriptor on path */
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long offset,     /* First byte to be locked */
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long length,     /* Number of bytes to lock */
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int setLockFlag                /* True to set lock.  False to clear lock */
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ByteRangeLockPB2 pb;
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err;
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pb.unLockFlag = setLockFlag ? 0 : 1;
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pb.startEndFlag = 0;
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pb.offset = offset;
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pb.length = length;
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pb.fd = pFile->h;
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset, length));
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ( err==-1 ) {
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc;
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tErrno = errno;
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             path, tErrno, strerror(tErrno)));
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqliteErrorFromPosixError(tErrno,
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( IS_LOCK_ERROR(rc) ){
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = tErrno;
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, set *pResOut
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to a non-zero value otherwise *pResOut is set to zero.  The return value
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to SQLITE_OK unless an I/O error occurs during lock checking.
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reserved = 0;
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( context->reserved ){
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pResOut = 1;
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check if a thread in this process holds such a lock */
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->pInode->eFileLock>SHARED_LOCK ){
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reserved = 1;
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Otherwise see if some other process holds it.
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !reserved ){
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* lock the RESERVED byte */
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( SQLITE_OK==lrc ){
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* if we succeeded in taking the reserved lock, unlock it to restore
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** the original state */
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* if we failed to get the lock then someone else must have it */
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reserved = 1;
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( IS_LOCK_ERROR(lrc) ){
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc=lrc;
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = reserved;
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter eFileLock - one
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following:
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (1) SHARED_LOCK
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (2) RESERVED_LOCK
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (3) PENDING_LOCK
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (4) EXCLUSIVE_LOCK
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between.  The locking might fail on one of the later
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal.  The following chart shows the allowed
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states:
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    UNLOCKED -> SHARED
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> RESERVED
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> (PENDING) -> EXCLUSIVE
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    RESERVED -> (PENDING) -> EXCLUSIVE
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    PENDING -> EXCLUSIVE
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock.  Use the sqlite3OsUnlock()
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** routine to lower a locking level.
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int afpLock(sqlite3_file *id, int eFileLock){
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode = pFile->pInode;
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           azFileLock(eFileLock), azFileLock(pFile->eFileLock),
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If there is already a lock of this type or more restrictive on the
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** unixEnterMutex() hasn't been called yet.
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock>=eFileLock ){
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("LOCK    %d %s ok (already held) (afp)\n", pFile->h,
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           azFileLock(eFileLock)));
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Make sure the locking sequence is correct
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **  (1) We never move from unlocked to anything higher than shared lock.
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **  (2) SQLite never explicitly requests a pendig lock.
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **  (3) A shared lock is always held when a reserve lock is requested.
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock!=PENDING_LOCK );
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* This mutex is needed because pFile->pInode is shared across threads
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode = pFile->pInode;
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If some thread using this PID has a lock via a different unixFile*
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** handle that precludes the requested lock, return BUSY.
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (pFile->eFileLock!=pInode->eFileLock &&
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     ){
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto afp_end_lock;
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If a SHARED lock is requested, and some thread using this PID already
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** has a SHARED or RESERVED lock, then increment reference counts and
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** return SQLITE_OK.
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==SHARED_LOCK &&
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( eFileLock==SHARED_LOCK );
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile->eFileLock==0 );
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->nShared>0 );
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = SHARED_LOCK;
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nShared++;
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nLock++;
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto afp_end_lock;
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* A PENDING lock is needed before acquiring a SHARED lock and before
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** be released.
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==SHARED_LOCK
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int failed;
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (failed) {
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = failed;
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto afp_end_lock;
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If control gets to this point, then actually go ahead and make
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** operating system calls for the specified lock.
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eFileLock==SHARED_LOCK ){
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int lrc1, lrc2, lrc1Errno;
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long lk, mask;
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->nShared==0 );
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->eFileLock==0 );
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Now get the read-lock SHARED_LOCK */
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* note that the quality of the randomness doesn't matter that much */
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lk = random();
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lrc1 = afpSetLock(context->dbPath, pFile,
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SHARED_FIRST+pInode->sharedByte, 1, 1);
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( IS_LOCK_ERROR(lrc1) ){
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lrc1Errno = pFile->lastErrno;
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Drop the temporary PENDING lock */
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( IS_LOCK_ERROR(lrc1) ) {
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = lrc1Errno;
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = lrc1;
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto afp_end_lock;
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if( IS_LOCK_ERROR(lrc2) ){
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = lrc2;
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto afp_end_lock;
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if( lrc1 != SQLITE_OK ) {
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = lrc1;
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->eFileLock = SHARED_LOCK;
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->nLock++;
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->nShared = 1;
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* We are trying for an exclusive lock but another thread in this
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     ** same process is still holding a shared lock. */
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The request was for a RESERVED or EXCLUSIVE lock.  It is
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** assumed that there is a SHARED or greater lock on the file
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** already.
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int failed = 0;
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( 0!=pFile->eFileLock );
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Acquire a RESERVED lock */
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !failed ){
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context->reserved = 1;
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!failed && eFileLock == EXCLUSIVE_LOCK) {
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Acquire an EXCLUSIVE lock */
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Remove the shared lock before trying the range.  we'll need to
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** reestablish the shared lock if we can't get the  afpUnlock
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         pInode->sharedByte, 1, 0)) ){
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int failed2 = SQLITE_OK;
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* now attemmpt to get the exclusive lock range */
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               SHARED_SIZE, 1);
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* Can't reestablish the shared lock.  Sqlite can't deal, this is
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** a critical I/O error
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               SQLITE_IOERR_LOCK;
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto afp_end_lock;
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = failed;
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( failed ){
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = failed;
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = eFileLock;
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->eFileLock = eFileLock;
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( eFileLock==EXCLUSIVE_LOCK ){
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->eFileLock = PENDING_LOCK;
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->eFileLock = PENDING_LOCK;
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)afp_end_lock:
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("LOCK    %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         rc==SQLITE_OK ? "ok" : "failed"));
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int afpUnlock(sqlite3_file *id, int eFileLock) {
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode;
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int skipShared = 0;
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int h = pFile->h;
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           getpid()));
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eFileLock<=SHARED_LOCK );
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock<=eFileLock ){
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode = pFile->pInode;
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pInode->nShared!=0 );
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock>SHARED_LOCK ){
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pInode->eFileLock==pFile->eFileLock );
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimulateIOErrorBenign(1);
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimulateIOError( h=(-1) )
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SimulateIOErrorBenign(0);
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* When reducing a lock such that other processes can start
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** reading the database file again, make sure that the
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** transaction counter was updated if any part of the database
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** file changed.  If the transaction counter is not updated,
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** other connections to the same file might not realize that
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the file has changed and hence might not know to flush their
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** cache.  The use of a stale cache can lead to database corruption.
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile->inNormalWrite==0
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           || pFile->dbUpdate==0
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           || pFile->transCntrChng==1 );
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->inNormalWrite = 0;
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pFile->eFileLock==EXCLUSIVE_LOCK ){
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* only re-establish the shared lock if necessary */
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        skipShared = 1;
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !rc ){
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context->reserved = 0;
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->eFileLock = SHARED_LOCK;
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Decrement the shared lock counter.  Release the lock using an
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** OS call only when all threads in this same process have released
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the lock.
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode->nShared--;
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode->nShared==0 ){
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(1);
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOError( h=(-1) )
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(0);
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !skipShared ){
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !rc ){
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pInode->eFileLock = NO_LOCK;
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->eFileLock = NO_LOCK;
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pInode->nLock--;
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( pInode->nLock>=0 );
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pInode->nLock==0 ){
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        closePendingFds(pFile);
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file & cleanup AFP specific locking context
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int afpClose(sqlite3_file *id) {
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( id ){
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *pFile = (unixFile*)id;
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    afpUnlock(id, NO_LOCK);
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixEnterMutex();
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pFile->pInode && pFile->pInode->nLock ){
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If there are outstanding locks, do not actually close the file just
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** yet because that would clear those locks.  Instead, add the file
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** descriptor to pInode->aPending.  It will be automatically closed when
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** the last lock is cleared.
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      setPendingFd(pFile);
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    releaseInodeInfo(pFile);
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pFile->lockingContext);
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = closeUnixFile(id);
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixLeaveMutex();
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The code above is the AFP lock implementation.  The code is specific
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to MacOSX and does not work on other unix platforms.  No alternative
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is available.  If you don't compile for a mac, then the "unix-afp"
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** VFS is not available.
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)********************* End of the AFP lock implementation **********************
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*************************** Begin NFS Locking ********************************/
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** must be either NO_LOCK or SHARED_LOCK.
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) **
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** If the locking level of the file descriptor is already at or below
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the requested locking level, this routine is a no-op.
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int nfsUnlock(sqlite3_file *id, int eFileLock){
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return posixUnlock(id, eFileLock, 1);
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The code above is the NFS lock implementation.  The code is specific
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to MacOSX and does not work on other unix platforms.  No alternative
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is available.
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)********************* End of the NFS lock implementation **********************
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**************** Non-locking sqlite3_file methods *****************************
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The next division contains implementations for all methods of the
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_file object other than the locking methods.  The locking
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** methods were defined in divisions above (one locking method per
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** division).  Those methods that are common to all locking modes
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are gather together into this division.
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Seek to the offset passed as the second argument, then read cnt
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes into pBuf. Return the number of bytes actually read.
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** NB:  If you define USE_PREAD or USE_PREAD64, then it might also
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** be necessary to define _XOPEN_SOURCE to be 500.  This varies from
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** one system to another.  Since SQLite does not define USE_PREAD
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** any any form by default, we will not attempt to define _XOPEN_SOURCE.
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** See tickets #2741 and #2681.
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** To avoid stomping the errno value on a failed read the lastErrno value
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set before returning.
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int got;
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i64 newOffset;
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TIMER_START;
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_PREAD)
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ got = osPread(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( got = -1 );
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_PREAD64)
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ got = osPread64(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR);
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( got = -1 );
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  newOffset = lseek(id->h, offset, SEEK_SET);
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( newOffset-- );
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( newOffset!=offset ){
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( newOffset == -1 ){
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((unixFile*)id)->lastErrno = errno;
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((unixFile*)id)->lastErrno = 0;
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ got = osRead(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TIMER_END;
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( got<0 ){
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((unixFile*)id)->lastErrno = errno;
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("READ    %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return got;
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from a file into a buffer.  Return SQLITE_OK if all
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes were read successfully and SQLITE_IOERR if anything goes
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** wrong.
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixRead(
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *id,
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pBuf,
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amt,
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 offset
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile *)id;
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int got;
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id );
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If this is a database file (not a journal, master-journal or temp
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** file), the bytes in the locking range should never be read or written. */
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile->pUnused==0
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || offset>=PENDING_BYTE+512
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || offset+amt<=PENDING_BYTE
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  got = seekAndRead(pFile, offset, pBuf, amt);
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( got==amt ){
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( got<0 ){
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* lastErrno set by seekAndRead */
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_READ;
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = 0; /* not a system error */
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Unread parts of the buffer must be zero-filled */
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&((char*)pBuf)[got], 0, amt-got);
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_SHORT_READ;
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Seek to the offset in id->offset then read cnt bytes into pBuf.
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the number of bytes actually read.  Update the offset.
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** To avoid stomping the errno value on a failed write the lastErrno value
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set before returning.
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int got;
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  i64 newOffset;
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TIMER_START;
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_PREAD)
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_PREAD64)
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR);
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  newOffset = lseek(id->h, offset, SEEK_SET);
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( newOffset-- );
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( newOffset!=offset ){
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( newOffset == -1 ){
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((unixFile*)id)->lastErrno = errno;
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((unixFile*)id)->lastErrno = 0;
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{ got = osWrite(id->h, pBuf, cnt); }while( got<0 && errno==EINTR );
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TIMER_END;
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( got<0 ){
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((unixFile*)id)->lastErrno = errno;
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return got;
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data from a buffer into a file.  Return SQLITE_OK on success
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or some other error code on failure.
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixWrite(
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *id,
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *pBuf,
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amt,
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 offset
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int wrote = 0;
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id );
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( amt>0 );
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If this is a database file (not a journal, master-journal or temp
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** file), the bytes in the locking range should never be read or written. */
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile->pUnused==0
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || offset>=PENDING_BYTE+512
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || offset+amt<=PENDING_BYTE
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If we are doing a normal write to a database file (as opposed to
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** doing a hot-journal rollback or a write to some file other than a
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** normal database file) then record the fact that the database
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** has changed.  If the transaction counter is modified, record that
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** fact too.
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->inNormalWrite ){
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->dbUpdate = 1;  /* The database has been modified */
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( offset<=24 && offset+amt>=27 ){
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc;
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char oldCntr[4];
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(1);
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = seekAndRead(pFile, 24, oldCntr, 4);
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(0);
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->transCntrChng = 1;  /* The transaction counter has changed */
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    amt -= wrote;
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset += wrote;
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBuf = &((char*)pBuf)[wrote];
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError(( wrote=(-1), amt=1 ));
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateDiskfullError(( wrote=0, amt=1 ));
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( amt>0 ){
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( wrote<0 ){
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* lastErrno set by seekAndWrite */
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_IOERR_WRITE;
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = 0; /* not a system error */
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_FULL;
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Count the number of fullsyncs and normal syncs.  This is used to test
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that syncs and fullsyncs are occurring at the right times.
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_sync_count = 0;
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_fullsync_count = 0;
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** We do not trust systems to provide a working fdatasync().  Some do.
31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Others do no.  To be safe, we will stick with the (slower) fsync().
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If you know that your system does support fdatasync() correctly,
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** then simply compile with -Dfdatasync=fdatasync
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(fdatasync) && !defined(__linux__)
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define fdatasync fsync
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the F_FULLFSYNC macro is defined.  F_FULLFSYNC is currently
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** only available on Mac OS X.  But that could change.
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef F_FULLFSYNC
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define HAVE_FULLFSYNC 1
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define HAVE_FULLFSYNC 0
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The fsync() system call does not work as advertised on many
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** unix systems.  The following procedure is an attempt to make
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it work better.
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The SQLITE_NO_SYNC macro disables all fsync()s.  This is useful
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for testing when we want to run through the test suite quickly.
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or power failure will likely corrupt the database file.
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLite sets the dataOnly flag if the size of the file is unchanged.
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The idea behind dataOnly is that it should only write the file content
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to disk, not the inode.  We only set dataOnly if the file size is
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** unchanged since the file size is part of the inode.  However,
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Ted Ts'o tells us that fdatasync() will also write the inode if the
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file size has changed.  The only real difference between fdatasync()
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and fsync(), Ted tells us, is that fdatasync() will not flush the
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** inode if the mtime or owner or other inode attributes have changed.
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** We only care about the file size, not the other file attributes, so
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** as far as SQLite is concerned, an fdatasync() is always adequate.
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** So, we always use fdatasync() if it is available, regardless of
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the value of the dataOnly flag.
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
31655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int full_fsync(int fd, int fullSync, int dataOnly){
31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The following "ifdef/elif/else/" block has the same structure as
31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the one below. It is replicated here solely to avoid cluttering
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** up the real code with the UNUSED_PARAMETER() macros.
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_NO_SYNC
31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(fd);
31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(fullSync);
31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(dataOnly);
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif HAVE_FULLFSYNC
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(dataOnly);
31785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
31795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(fullSync);
31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(dataOnly);
31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Record the number of times that we do a normal fsync() and
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** FULLSYNC.  This is used during testing to verify that this procedure
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** gets called with the correct arguments.
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fullSync ) sqlite3_fullsync_count++;
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_sync_count++;
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** no-op
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_NO_SYNC
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = SQLITE_OK;
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif HAVE_FULLFSYNC
31985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fullSync ){
31995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = osFcntl(fd, F_FULLFSYNC, 0);
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = 1;
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the FULLFSYNC failed, fall back to attempting an fsync().
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** It shouldn't be possible for fullfsync to fail on the local
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** file system (on OSX), so failure indicates that FULLFSYNC
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** isn't supported for this file system. So, attempt an fsync
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** and (for now) ignore the overhead of a superfluous fcntl call.
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** It'd be better to detect fullfsync support once and avoid
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the fcntl call every time sync is called.
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc ) rc = fsync(fd);
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__APPLE__)
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
32155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** so currently we default to the macro that redefines fdatasync to fsync
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = fsync(fd);
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = fdatasync(fd);
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
32215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==-1 && errno==ENOTSUP ){
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = fsync(fd);
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* OS_VXWORKS */
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( OS_VXWORKS && rc!= -1 ){
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = 0;
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a file descriptor to the directory containing file zFilename.
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If successful, *pFd is set to the opened file descriptor and
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** value.
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The directory file descriptor is used for only one thing - to
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** fsync() a directory to make sure file creation and deletion events
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are flushed to disk.  Such fsyncs are not needed on newer
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** journaling filesystems, but are required on older filesystems.
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine can be overridden using the xSetSysCall interface.
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The ability to override this routine was added in support of the
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** chromium sandbox.  Opening a directory is a security risk (we are
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** told) so making it overrideable allows the chromium sandbox to
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** replace this routine with a harmless no-op.  To make this routine
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a no-op, replace it with a stub that returns SQLITE_OK but leaves
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** *pFd set to a negative number.
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If SQLITE_OK is returned, the caller is responsible for closing
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the file descriptor *pFd using close().
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int openDirectory(const char *zFilename, int *pFd){
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ii;
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = -1;
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zDirname[MAX_PATHNAME+1];
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( ii>0 ){
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zDirname[ii] = '\0';
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( fd>=0 ){
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef FD_CLOEXEC
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pFd = fd;
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Make sure all writes to a particular file are committed to disk.
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If dataOnly==0 then both the file itself and its metadata (file
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** size, access time, etc) are synced.  If dataOnly!=0 then only the
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file data is synced.
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Under Unix, also make sure that the directory entry for the file
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** has been created by fsync-ing the directory that contains the file.
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If we do not do this and we encounter a power failure, the directory
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** entry for the journal might not exist after we reboot.  The next
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLite to access the file will not know that the journal exists (because
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the directory entry for the journal was never created) and the transaction
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will not roll back - possibly leading to database corruption.
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixSync(sqlite3_file *id, int flags){
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert((flags&0x0F)==SQLITE_SYNC_NORMAL
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      || (flags&0x0F)==SQLITE_SYNC_FULL
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** line is to test that doing so does not cause any problems.
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateDiskfullError( return SQLITE_FULL );
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("SYNC    %-3d\n", pFile->h));
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = full_fsync(pFile->h, isFullsync, isDataOnly);
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( rc=1 );
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc ){
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = errno;
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Also fsync the directory containing the file if the DIRSYNC flag
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** is set.  This is a one-time occurrance.  Many systems (examples: AIX)
33205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** are unable to fsync a directory, so ignore errors on the fsync.
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int dirfd;
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            HAVE_FULLFSYNC, isFullsync));
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = osOpenDirectory(pFile->zPath, &dirfd);
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK && dirfd>=0 ){
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      full_fsync(dirfd, 0, 0);
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      robust_close(pFile, dirfd, __LINE__);
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else if( rc==SQLITE_CANTOPEN ){
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_OK;
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate an open file to a specified size
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixTruncate(sqlite3_file *id, i64 nByte){
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile *)id;
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_TRUNCATE );
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the user has configured a chunk-size for this file, truncate the
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** file so that it consists of an integer number of chunks (i.e. the
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** actual file size after the operation may be larger than the requested
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** size).
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->szChunk ){
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = robust_ftruncate(pFile->h, (off_t)nByte);
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc ){
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = errno;
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If we are doing a normal write to a database file (as opposed to
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** doing a hot-journal rollback or a write to some file other than a
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** normal database file) and we truncate the file to zero length,
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** that effectively updates the change counter.  This might happen
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** when restoring a database using the backup API from a zero-length
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** source.
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pFile->inNormalWrite && nByte==0 ){
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->transCntrChng = 1;
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Determine the current size of a file in bytes
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixFileSize(sqlite3_file *id, i64 *pSize){
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat buf;
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id );
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = osFstat(((unixFile*)id)->h, &buf);
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( rc=1 );
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=0 ){
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((unixFile*)id)->lastErrno = errno;
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_FSTAT;
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pSize = buf.st_size;
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* When opening a zero-size database, the findInodeInfo() procedure
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** writes a single byte into that file in order to work around a bug
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** in the OS-X msdos filesystem.  In order to avoid problems with upper
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** layers, we need to report this file size as zero even though it is
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** really 1.   Ticket #3260.
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( *pSize==1 ) *pSize = 0;
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Handler for proxy-locking file-control verbs.  Defined below in the
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** proxying locking division.
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyFileControl(sqlite3_file*,int,void*);
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file-control operation.
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the user has configured a chunk-size for this file, it could be
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that the file needs to be extended at this point. Otherwise, the
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fcntlSizeHint(unixFile *pFile, i64 nByte){
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->szChunk ){
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i64 nSize;                    /* Required file size */
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct stat buf;              /* Used to hold return values of fstat() */
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( nSize>(i64)buf.st_size ){
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
34325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* The code below is handling the return value of osFallocate()
34335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** correctly. posix_fallocate() is defined to "returns zero on success,
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** or an error number on  failure". See the manpage for details. */
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int err;
34365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      do{
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }while( err==EINTR );
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( err ) return SQLITE_IOERR_WRITE;
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If the OS does not have posix_fallocate(), fake it. First use
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** ftruncate() to set the file size, then write a single byte to
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** the last byte in each block within the extended region. This
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** is the same technique used by glibc to implement posix_fallocate()
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** on systems that do not have a real fallocate() system call.
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int nBlk = buf.st_blksize;  /* File-system block size */
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i64 iWrite;                 /* Next offset to write to */
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( robust_ftruncate(pFile->h, nSize) ){
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = errno;
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while( iWrite<nSize ){
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int nWrite = seekAndWrite(pFile, iWrite, "", 1);
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iWrite += nBlk;
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
34655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
34685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Information and control of an open file handle.
34695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixFileControl(sqlite3_file *id, int op, void *pArg){
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( op ){
34725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_LOCKSTATE: {
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *(int*)pArg = ((unixFile*)id)->eFileLock;
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_LAST_ERRNO: {
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *(int*)pArg = ((unixFile*)id)->lastErrno;
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_CHUNK_SIZE: {
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((unixFile*)id)->szChunk = *(int *)pArg;
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_SIZE_HINT: {
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The pager calls this method to signal that it has done
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** a rollback and that the database is therefore unchanged and
34905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** it hence it is OK for the transaction change counter to be
34915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** unchanged.
34925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
34935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_DB_UNCHANGED: {
34945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((unixFile*)id)->dbUpdate = 0;
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_SET_LOCKPROXYFILE:
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_GET_LOCKPROXYFILE: {
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return proxyFileControl(id,op,pArg);
35025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
35045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_SYNC_OMITTED: {
35055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;  /* A no-op */
35065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
35085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_NOTFOUND;
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the sector size in bytes of the underlying block device for
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the specified file. This is almost always 512 bytes, but may be
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** larger for some devices.
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLite code assumes this function cannot fail. It also assumes that
35175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** if two files are created in the same file-system directory (i.e.
35185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a database and its journal file) that the sector size will be the
35195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** same for both.
35205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
35215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixSectorSize(sqlite3_file *NotUsed){
35225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
35235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_DEFAULT_SECTOR_SIZE;
35245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the device characteristics for the file. This is always 0 for unix.
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
35315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
35325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_WAL
35355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Object used to represent an shared memory buffer.
35395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When multiple threads all reference the same wal-index, each thread
35415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** has its own unixShm object, but they all point to a single instance
35425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of this unixShmNode object.  In other words, each wal-index is opened
35435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** only once per process.
35445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Each unixShmNode object is connected to a single unixInodeInfo object.
35465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** We could coalesce this object into unixInodeInfo, but that would mean
35475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** every open file that does not use shared memory (in other words, most
35485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** open files) would have to carry around this extra information.  So
35495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the unixInodeInfo object contains a pointer to this unixShmNode object
35505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and the unixShmNode object is created only when needed.
35515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** unixMutexHeld() must be true when creating or destroying
35535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this object or while reading or writing the following fields:
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      nRef
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following fields are read-only after the object is created:
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      fid
35605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      zFilename
35615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
35635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** unixMutexHeld() is true when reading or writing any other field
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in this structure.
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct unixShmNode {
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode;     /* unixInodeInfo that owns this SHM node */
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex *mutex;      /* Mutex to access this object */
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFilename;           /* Name of the mmapped file */
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int h;                     /* Open file descriptor */
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szRegion;              /* Size of shared-memory regions */
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRegion;               /* Size of array apRegion */
35735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char **apRegion;           /* Array of mapped shared-memory regions */
35745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRef;                  /* Number of unixShm objects pointing to this */
35755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm *pFirst;           /* All unixShm objects pointing to this */
35765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
35775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 exclMask;               /* Mask of exclusive locks held */
35785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 sharedMask;             /* Mask of shared locks held */
35795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 nextShmId;              /* Next available unixShm.id value */
35805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
35815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
35825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Structure used internally by this VFS to record the state of an
35855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** open shared memory connection.
35865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following fields are initialized when this object is created and
35885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are read-only thereafter:
35895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    unixShm.pFile
35915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    unixShm.id
35925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
35935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All other fields are read/write.  The unixShm.pFile->mutex must be held
35945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** while accessing any read/write fields.
35955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
35965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct unixShm {
35975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
35985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
35995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 hasMutex;               /* True if holding the unixShmNode mutex */
36005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u16 sharedMask;            /* Mask of shared locks held */
36015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u16 exclMask;              /* Mask of exclusive locks held */
36025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
36035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 id;                     /* Id of this connection within its unixShmNode */
36045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
36055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
36065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
36085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Constants used for locking
36095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
36105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNIX_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)         /* first lock byte */
36115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UNIX_SHM_DMS    (UNIX_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
36125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
36145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
36155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
36165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
36175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** otherwise.
36185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
36195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixShmSystemLock(
36205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
36215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lockType,          /* F_UNLCK, F_RDLCK, or F_WRLCK */
36225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ofst,              /* First byte of the locking range */
36235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n                  /* Number of bytes to lock */
36245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
36255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct flock f;       /* The posix advisory locking structure */
36265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;   /* Result code form fcntl() */
36275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Access to the unixShmNode object is serialized by the caller */
36295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
36305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Shared locks never span more than one byte */
36325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n==1 || lockType!=F_RDLCK );
36335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Locks are within range */
36355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n>=1 && n<SQLITE_SHM_NLOCK );
36365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode->h>=0 ){
36385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Initialize the locking parameters */
36395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&f, 0, sizeof(f));
36405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    f.l_type = lockType;
36415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    f.l_whence = SEEK_SET;
36425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    f.l_start = ofst;
36435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    f.l_len = n;
36445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = osFcntl(pShmNode->h, F_SETLK, &f);
36465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
36475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
36485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Update the global lock state and do debug tracing */
36505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
36515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { u16 mask;
36525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("SHM-LOCK "));
36535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mask = (1<<(ofst+n)) - (1<<ofst);
36545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
36555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( lockType==F_UNLCK ){
36565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("unlock %d ok", ofst));
36575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->exclMask &= ~mask;
36585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->sharedMask &= ~mask;
36595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else if( lockType==F_RDLCK ){
36605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("read-lock %d ok", ofst));
36615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->exclMask &= ~mask;
36625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->sharedMask |= mask;
36635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
36645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( lockType==F_WRLCK );
36655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("write-lock %d ok", ofst));
36665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->exclMask |= mask;
36675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->sharedMask &= ~mask;
36685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
36705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( lockType==F_UNLCK ){
36715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("unlock %d failed", ofst));
36725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else if( lockType==F_RDLCK ){
36735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("read-lock failed"));
36745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
36755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( lockType==F_WRLCK );
36765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("write-lock %d failed", ofst));
36775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
36795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE((" - afterwards %03x,%03x\n",
36805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pShmNode->sharedMask, pShmNode->exclMask));
36815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
36825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
36835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
36855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
36895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
36905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
36915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This is not a VFS shared-memory method; it is a utility function called
36925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by VFS shared-memory methods.
36935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
36945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void unixShmPurge(unixFile *pFd){
36955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmNode *p = pFd->pInode->pShmNode;
36965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( unixMutexHeld() );
36975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p && p->nRef==0 ){
36985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
36995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( p->pInode==pFd->pInode );
37005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->mutex ) sqlite3_mutex_free(p->mutex);
37015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<p->nRegion; i++){
37025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( p->h>=0 ){
37035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        munmap(p->apRegion[i], p->szRegion);
37045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
37055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_free(p->apRegion[i]);
37065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
37075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
37085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p->apRegion);
37095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->h>=0 ){
37105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      robust_close(pFd, p->h, __LINE__);
37115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->h = -1;
37125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
37135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pInode->pShmNode = 0;
37145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p);
37155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
37165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
37195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a shared-memory area associated with open database file pDbFd.
37205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This particular implementation uses mmapped files.
37215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
37225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The file used to implement shared-memory is in the same directory
37235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** as the open database file and has the same name as the open database
37245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file with the "-shm" suffix added.  For example, if the database file
37255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is "/home/user1/config.db" then the file that is created and mmapped
37265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for shared memory will be called "/home/user1/config.db-shm".
37275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
37285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Another approach to is to use files in /dev/shm or /dev/tmp or an
37295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** some other tmpfs mount. But if a file in a different directory
37305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** from the database file is used, then differing access permissions
37315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or a chroot() might cause two different processes on the same
37325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database to end up using different files for shared memory -
37335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** meaning that their memory would not really be shared - resulting
37345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in database corruption.  Nevertheless, this tmpfs file usage
37355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
37365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or the equivalent.  The use of the SQLITE_SHM_DIRECTORY compile-time
37375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** option results in an incompatible build of SQLite;  builds of SQLite
37385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
37395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** same database file at the same time, database corruption will likely
37405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
37415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** "unsupported" and may go away in a future SQLite release.
37425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
37435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When opening a new shared-memory file, if no other instances of that
37445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file are currently open, in this process or in other processes, then
37455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the file must be truncated to zero length or have its header cleared.
37465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
37475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the original database file (pDbFd) is using the "unix-excl" VFS
37485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that means that an exclusive lock is held on the database file and
37495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that no other processes are able to read or write the database.  In
37505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that case, we do not really need shared memory.  No shared memory
37515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file is created.  The shared memory will be simulated with heap memory.
37525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
37535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixOpenSharedMemory(unixFile *pDbFd){
37545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct unixShm *p = 0;          /* The connection to be opened */
37555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct unixShmNode *pShmNode;   /* The underlying mmapped file */
37565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                         /* Result code */
37575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixInodeInfo *pInode;          /* The inode of fd */
37585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zShmFilename;             /* Name of the file used for SHM */
37595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nShmFilename;               /* Size of the SHM filename in bytes */
37605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Allocate space for the new unixShm object. */
37625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = sqlite3_malloc( sizeof(*p) );
37635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p==0 ) return SQLITE_NOMEM;
37645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, sizeof(*p));
37655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pDbFd->pShm==0 );
37665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check to see if a unixShmNode object already exists. Reuse an existing
37685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** one if present. Create a new one if necessary.
37695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
37705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
37715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pInode = pDbFd->pInode;
37725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode = pInode->pShmNode;
37735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode==0 ){
37745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct stat sStat;                 /* fstat() info for database file */
37755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Call fstat() to figure out the permissions on the database file. If
37775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** a new *-shm file is created, an attempt will be made to create it
37785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** with the same permissions. The actual permissions the file is created
37795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** with are subject to the current umask setting.
37805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
37815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){
37825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_FSTAT;
37835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shm_open_err;
37845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
37855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_SHM_DIRECTORY
37875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 30;
37885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
37895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nShmFilename = 5 + (int)strlen(pDbFd->zPath);
37905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
37915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
37925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pShmNode==0 ){
37935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
37945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shm_open_err;
37955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
37965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pShmNode, 0, sizeof(*pShmNode));
37975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
37985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_SHM_DIRECTORY
37995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nShmFilename, zShmFilename,
38005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
38015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     (u32)sStat.st_ino, (u32)sStat.st_dev);
38025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
38035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
38045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
38055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->h = -1;
38065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pDbFd->pInode->pShmNode = pShmNode;
38075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->pInode = pDbFd->pInode;
38085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
38095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pShmNode->mutex==0 ){
38105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
38115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shm_open_err;
38125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode->bProcessLock==0 ){
38155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->h = robust_open(zShmFilename, O_RDWR|O_CREAT,
38165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               (sStat.st_mode & 0777));
38175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pShmNode->h<0 ){
38185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
38195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto shm_open_err;
38205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Check to see if another process is holding the dead-man switch.
38235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** If not, truncate the file to zero length.
38245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
38255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_OK;
38265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
38275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( robust_ftruncate(pShmNode->h, 0) ){
38285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
38295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
38305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
38325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
38335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
38345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc ) goto shm_open_err;
38355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
38365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
38375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Make the new connection a child of the unixShmNode */
38395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pShmNode = pShmNode;
38405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
38415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->id = pShmNode->nextShmId++;
38425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
38435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode->nRef++;
38445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pDbFd->pShm = p;
38455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
38465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The reference count on pShmNode has already been incremented under
38485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the cover of the unixEnterMutex() mutex and the pointer from the
38495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** new (struct unixShm) object to the pShmNode has been set. All that is
38505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** left to do is to link the new object into the linked list starting
38515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
38525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** mutex.
38535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
38545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
38555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pNext = pShmNode->pFirst;
38565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode->pFirst = p;
38575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
38585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
38595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Jump here on any error */
38615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)shm_open_err:
38625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmPurge(pDbFd);       /* This call frees pShmNode if required */
38635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
38645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
38655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
38665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
38675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
38695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called to obtain a pointer to region iRegion of the
38705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** shared-memory associated with the database file fd. Shared-memory regions
38715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are numbered starting from zero. Each shared-memory region is szRegion
38725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes in size.
38735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
38745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If an error occurs, an error code is returned and *pp is set to NULL.
38755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
38765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
38775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** region has not been allocated (by any client, including one running in a
38785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** separate process), then *pp is set to NULL and SQLITE_OK returned. If
38795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bExtend is non-zero and the requested shared-memory region has not yet
38805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** been allocated, it is allocated by this function.
38815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
38825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the shared-memory region has already been allocated or is allocated by
38835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this call as described above, then it is mapped into this processes
38845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** address space (if it is not already), *pp is set to point to the mapped
38855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** memory and SQLITE_OK returned.
38865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
38875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixShmMap(
38885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd,               /* Handle open on database file */
38895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iRegion,                    /* Region to retrieve */
38905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szRegion,                   /* Size of regions */
38915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bExtend,                    /* True to extend file if necessary */
38925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void volatile **pp              /* OUT: Mapped memory */
38935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
38945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pDbFd = (unixFile*)fd;
38955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm *p;
38965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmNode *pShmNode;
38975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
38985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the shared-memory file has not yet been opened, open it now. */
39005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pDbFd->pShm==0 ){
39015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = unixOpenSharedMemory(pDbFd);
39025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ) return rc;
39035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = pDbFd->pShm;
39065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode = p->pShmNode;
39075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
39085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
39095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->pInode==pDbFd->pInode );
39105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
39115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
39125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode->nRegion<=iRegion ){
39145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char **apNew;                      /* New apRegion[] array */
39155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
39165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct stat sStat;                 /* Used by fstat() */
39175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->szRegion = szRegion;
39195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pShmNode->h>=0 ){
39215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* The requested region is not mapped into this processes address space.
39225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** Check to see if it has been allocated (i.e. if the wal-index file is
39235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** large enough to contain the requested region).
39245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
39255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( osFstat(pShmNode->h, &sStat) ){
39265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_IOERR_SHMSIZE;
39275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto shmpage_out;
39285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
39295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( sStat.st_size<nByte ){
39315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* The requested memory region does not exist. If bExtend is set to
39325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
39335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        **
39345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** Alternatively, if bExtend is true, use ftruncate() to allocate
39355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** the requested memory region.
39365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        */
39375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( !bExtend ) goto shmpage_out;
39385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( robust_ftruncate(pShmNode->h, nByte) ){
39395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
39405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            pShmNode->zFilename);
39415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto shmpage_out;
39425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
39435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
39445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Map the requested memory region into this processes address space. */
39475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    apNew = (char **)sqlite3_realloc(
39485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
39495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
39505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !apNew ){
39515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_NOMEM;
39525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shmpage_out;
39535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->apRegion = apNew;
39555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while(pShmNode->nRegion<=iRegion){
39565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void *pMem;
39575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pShmNode->h>=0 ){
39585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE,
39595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
39605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        );
39615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pMem==MAP_FAILED ){
39625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_IOERR;
39635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto shmpage_out;
39645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
39655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
39665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pMem = sqlite3_malloc(szRegion);
39675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pMem==0 ){
39685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_NOMEM;
39695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto shmpage_out;
39705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
39715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memset(pMem, 0, szRegion);
39725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
39735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->apRegion[pShmNode->nRegion] = pMem;
39745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->nRegion++;
39755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)shmpage_out:
39795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode->nRegion>iRegion ){
39805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pp = pShmNode->apRegion[iRegion];
39815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
39825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pp = 0;
39835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
39845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
39855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
39865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
39895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Change the lock state for a shared-memory segment.
39905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
39915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
39925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** different here than in posix.  In xShmLock(), one can go from unlocked
39935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to shared and back or from unlocked to exclusive and back.  But one may
39945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** not go from shared to exclusive or from exclusive to shared.
39955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
39965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixShmLock(
39975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd,          /* Database file holding the shared memory */
39985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ofst,                  /* First lock to acquire or release */
39995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n,                     /* Number of locks to acquire or release */
40005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags                  /* What to do with the lock */
40015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
40025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pDbFd = (unixFile*)fd;      /* Connection holding shared memory */
40035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm *p = pDbFd->pShm;             /* The shared memory being locked */
40045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm *pX;                          /* For looping over all siblings */
40055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmNode *pShmNode = p->pShmNode;  /* The underlying file iNode */
40065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;                   /* Result code */
40075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u16 mask;                             /* Mask of locks to take or release */
40085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode==pDbFd->pInode->pShmNode );
40105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->pInode==pDbFd->pInode );
40115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
40125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n>=1 );
40135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
40145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
40155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
40165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
40175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
40185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
40195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
40205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mask = (1<<(ofst+n)) - (1<<ofst);
40225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n>1 || mask==(1<<ofst) );
40235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
40245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags & SQLITE_SHM_UNLOCK ){
40255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u16 allMask = 0; /* Mask of locks held by siblings */
40265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* See if any siblings hold this same lock */
40285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
40295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pX==p ) continue;
40305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
40315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allMask |= pX->sharedMask;
40325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Unlock the system-level locks */
40355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (mask & allMask)==0 ){
40365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
40375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
40385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_OK;
40395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Undo the local locks */
40425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
40435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->exclMask &= ~mask;
40445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->sharedMask &= ~mask;
40455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( flags & SQLITE_SHM_SHARED ){
40475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u16 allShared = 0;  /* Union of locks held by connections other than "p" */
40485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Find out which shared locks are already held by sibling connections.
40505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** If any sibling already holds an exclusive lock, go ahead and return
40515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** SQLITE_BUSY.
40525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
40535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
40545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (pX->exclMask & mask)!=0 ){
40555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_BUSY;
40565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
40575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
40585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allShared |= pX->sharedMask;
40595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get shared locks at the system level, if necessary */
40625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
40635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (allShared & mask)==0 ){
40645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
40655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
40665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_OK;
40675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
40685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get the local shared locks */
40715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
40725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->sharedMask |= mask;
40735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
40755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Make sure no sibling connections hold locks that will block this
40765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** lock.  If any do, return SQLITE_BUSY right away.
40775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
40785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
40795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
40805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_BUSY;
40815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
40825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
40835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
40855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get the exclusive locks at the system level.  Then if successful
40865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** also mark the local connection as being locked.
40875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
40885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
40895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
40905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
40915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( (p->sharedMask & mask)==0 );
40925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        p->exclMask |= mask;
40935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
40945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
40955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
40965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
40975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
40985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           p->id, getpid(), p->sharedMask, p->exclMask));
40995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
41005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
41035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implement a memory barrier or memory fence on shared memory.
41045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All loads and stores begun before the barrier must complete before
41065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** any load or store begun after the barrier.
41075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
41085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void unixShmBarrier(
41095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd                /* Database file holding the shared memory */
41105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
41115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(fd);
41125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
41135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
41145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
41175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a connection to shared-memory.  Delete the underlying
41185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** storage if deleteFlag is true.
41195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If there is no shared memory associated with the connection then this
41215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** routine is a harmless no-op.
41225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
41235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixShmUnmap(
41245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd,               /* The underlying database file */
41255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int deleteFlag                  /* Delete shared-memory if true */
41265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
41275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm *p;                     /* The connection to be closed */
41285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShmNode *pShmNode;          /* The underlying shared-memory file */
41295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixShm **pp;                   /* For looping over sibling connections */
41305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pDbFd;                /* The underlying database file */
41315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pDbFd = (unixFile*)fd;
41335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = pDbFd->pShm;
41345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p==0 ) return SQLITE_OK;
41355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode = p->pShmNode;
41365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode==pDbFd->pInode->pShmNode );
41385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->pInode==pDbFd->pInode );
41395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Remove connection p from the set of connections associated
41415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** with pShmNode */
41425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
41435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
41445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pp = p->pNext;
41455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Free the connection p */
41475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
41485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pDbFd->pShm = 0;
41495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
41505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If pShmNode->nRef has reached 0, then close the underlying
41525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** shared-memory file, too */
41535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
41545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->nRef>0 );
41555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode->nRef--;
41565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode->nRef==0 ){
41575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
41585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixShmPurge(pDbFd);
41595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
41605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
41615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
41635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
41645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
41675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define unixShmMap     0
41685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define unixShmLock    0
41695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define unixShmBarrier 0
41705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define unixShmUnmap   0
41715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* #ifndef SQLITE_OMIT_WAL */
41725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
41745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Here ends the implementation of all sqlite3_file methods.
41755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)********************** End sqlite3_file Methods *******************************
41775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
41785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
41805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This division contains definitions of sqlite3_io_methods objects that
41815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** implement various file locking strategies.  It also contains definitions
41825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of "finder" functions.  A finder-function is used to locate the appropriate
41835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_io_methods object for a particular database file.  The pAppData
41845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** field of the sqlite3_vfs VFS objects are initialized to be pointers to
41855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the correct finder-function for that VFS.
41865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Most finder functions return a pointer to a fixed sqlite3_io_methods
41885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** object.  The only interesting finder-function is autolockIoFinder, which
41895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** looks at the filesystem type and tries to guess the best locking
41905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** strategy from that.
41915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** For finder-funtion F, two objects are created:
41935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    (1) The real finder-function named "FImpt()".
41955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    (2) A constant pointer to this function named just "F".
41975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
41995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A pointer to the F pointer is used as the pAppData value for VFS
42005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** objects.  We have to do this instead of letting pAppData point
42015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** directly at the finder-function since C90 rules prevent a void*
42025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** from be cast into a function pointer.
42035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
42045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
42055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Each instance of this macro generates two objects:
42065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
42075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  A constant sqlite3_io_methods object call METHOD that has locking
42085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
42095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
42105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  An I/O method finder function called FINDER that returns a pointer
42115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      to the METHOD object in the previous bullet.
42125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
42135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK)      \
42145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods METHOD = {                                   \
42155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   VERSION,                    /* iVersion */                                \
42165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   CLOSE,                      /* xClose */                                  \
42175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixRead,                   /* xRead */                                   \
42185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixWrite,                  /* xWrite */                                  \
42195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixTruncate,               /* xTruncate */                               \
42205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixSync,                   /* xSync */                                   \
42215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixFileSize,               /* xFileSize */                               \
42225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   LOCK,                       /* xLock */                                   \
42235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   UNLOCK,                     /* xUnlock */                                 \
42245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   CKLOCK,                     /* xCheckReservedLock */                      \
42255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixFileControl,            /* xFileControl */                            \
42265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixSectorSize,             /* xSectorSize */                             \
42275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
42285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixShmMap,                 /* xShmMap */                                 \
42295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixShmLock,                /* xShmLock */                                \
42305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixShmBarrier,             /* xShmBarrier */                             \
42315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   unixShmUnmap                /* xShmUnmap */                               \
42325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};                                                                           \
42335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
42345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
42355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &METHOD;                                                            \
42365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}                                                                            \
42375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
42385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    = FINDER##Impl;
42395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
42415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Here are all of the sqlite3_io_methods objects for each of the
42425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** locking strategies.  Functions that return pointers to these methods
42435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are also created.
42445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
42455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
42465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  posixIoFinder,            /* Finder function name */
42475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  posixIoMethods,           /* sqlite3_io_methods object name */
42485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  2,                        /* shared memory is enabled */
42495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixClose,                /* xClose method */
42505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLock,                 /* xLock method */
42515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixUnlock,               /* xUnlock method */
42525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixCheckReservedLock     /* xCheckReservedLock method */
42535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
42545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
42555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nolockIoFinder,           /* Finder function name */
42565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nolockIoMethods,          /* sqlite3_io_methods object name */
42575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                        /* shared memory is disabled */
42585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nolockClose,              /* xClose method */
42595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nolockLock,               /* xLock method */
42605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nolockUnlock,             /* xUnlock method */
42615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nolockCheckReservedLock   /* xCheckReservedLock method */
42625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
42635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
42645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dotlockIoFinder,          /* Finder function name */
42655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dotlockIoMethods,         /* sqlite3_io_methods object name */
42665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                        /* shared memory is disabled */
42675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dotlockClose,             /* xClose method */
42685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dotlockLock,              /* xLock method */
42695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dotlockUnlock,            /* xUnlock method */
42705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dotlockCheckReservedLock  /* xCheckReservedLock method */
42715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
42725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
42745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
42755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flockIoFinder,            /* Finder function name */
42765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flockIoMethods,           /* sqlite3_io_methods object name */
42775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                        /* shared memory is disabled */
42785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flockClose,               /* xClose method */
42795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flockLock,                /* xLock method */
42805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flockUnlock,              /* xUnlock method */
42815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flockCheckReservedLock    /* xCheckReservedLock method */
42825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
42835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
42845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
42865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
42875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  semIoFinder,              /* Finder function name */
42885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  semIoMethods,             /* sqlite3_io_methods object name */
42895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                        /* shared memory is disabled */
42905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  semClose,                 /* xClose method */
42915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  semLock,                  /* xLock method */
42925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  semUnlock,                /* xUnlock method */
42935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  semCheckReservedLock      /* xCheckReservedLock method */
42945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
42955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
42965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
42985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
42995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpIoFinder,              /* Finder function name */
43005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpIoMethods,             /* sqlite3_io_methods object name */
43015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                        /* shared memory is disabled */
43025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpClose,                 /* xClose method */
43035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpLock,                  /* xLock method */
43045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpUnlock,                /* xUnlock method */
43055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  afpCheckReservedLock      /* xCheckReservedLock method */
43065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
43075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
43085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
43105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The proxy locking method is a "super-method" in the sense that it
43115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** opens secondary file descriptors for the conch and lock files and
43125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it uses proxy, dot-file, AFP, and flock() locking methods on those
43135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** secondary files.  For this reason, the division that implements
43145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** proxy locking is located much further down in the file.  But we need
43155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to go ahead and define the sqlite3_io_methods and finder function
43165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for proxy locking here.  So we forward declare the I/O methods.
43175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
43185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
43195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyClose(sqlite3_file*);
43205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyLock(sqlite3_file*, int);
43215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyUnlock(sqlite3_file*, int);
43225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyCheckReservedLock(sqlite3_file*, int*);
43235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
43245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyIoFinder,            /* Finder function name */
43255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyIoMethods,           /* sqlite3_io_methods object name */
43265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                        /* shared memory is disabled */
43275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyClose,               /* xClose method */
43285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyLock,                /* xLock method */
43295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyUnlock,              /* xUnlock method */
43305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyCheckReservedLock    /* xCheckReservedLock method */
43315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
43325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
43335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
43355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
43365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IOMETHODS(
43375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nfsIoFinder,               /* Finder function name */
43385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nfsIoMethods,              /* sqlite3_io_methods object name */
43395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                         /* shared memory is disabled */
43405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixClose,                 /* xClose method */
43415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLock,                  /* xLock method */
43425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nfsUnlock,                 /* xUnlock method */
43435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixCheckReservedLock      /* xCheckReservedLock method */
43445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
43455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
43465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
43485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
43495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This "finder" function attempts to determine the best locking strategy
43505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for the database file "filePath".  It then returns the sqlite3_io_methods
43515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** object that implements that strategy.
43525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
43535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This is for MacOSX only.
43545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
43555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods *autolockIoFinderImpl(
43565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *filePath,    /* name of the database file */
43575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pNew           /* open file object for the database file */
43585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
43595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const struct Mapping {
43605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *zFilesystem;              /* Filesystem type name */
43615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sqlite3_io_methods *pMethods;   /* Appropriate locking method */
43625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } aMap[] = {
43635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "hfs",    &posixIoMethods },
43645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "ufs",    &posixIoMethods },
43655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "afpfs",  &afpIoMethods },
43665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "smbfs",  &afpIoMethods },
43675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "webdav", &nolockIoMethods },
43685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 0, 0 }
43695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
43705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
43715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct statfs fsInfo;
43725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct flock lockInfo;
43735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !filePath ){
43755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If filePath==NULL that means we are dealing with a transient file
43765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** that does not need to be locked. */
43775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &nolockIoMethods;
43785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( statfs(filePath, &fsInfo) != -1 ){
43805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( fsInfo.f_flags & MNT_RDONLY ){
43815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &nolockIoMethods;
43825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
43835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; aMap[i].zFilesystem; i++){
43845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
43855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return aMap[i].pMethods;
43865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
43875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
43885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
43895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Default case. Handles, amongst others, "nfs".
43915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Test byte-range lock using fcntl(). If the call succeeds,
43925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** assume that the file-system supports POSIX style locks.
43935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
43945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_len = 1;
43955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_start = 0;
43965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_whence = SEEK_SET;
43975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_type = F_RDLCK;
43985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
43995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
44005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &nfsIoMethods;
44015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
44025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &posixIoMethods;
44035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
44045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
44055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &dotlockIoMethods;
44065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods
44095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
44105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
44125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
44145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
44155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This "finder" function attempts to determine the best locking strategy
44165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for the database file "filePath".  It then returns the sqlite3_io_methods
44175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** object that implements that strategy.
44185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
44195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This is for VXWorks only.
44205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
44215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods *autolockIoFinderImpl(
44225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *filePath,    /* name of the database file */
44235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pNew           /* the open file object */
44245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
44255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct flock lockInfo;
44265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !filePath ){
44285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If filePath==NULL that means we are dealing with a transient file
44295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** that does not need to be locked. */
44305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &nolockIoMethods;
44315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Test if fcntl() is supported and use POSIX style locks.
44345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Otherwise fall back to the named semaphore method.
44355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
44365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_len = 1;
44375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_start = 0;
44385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_whence = SEEK_SET;
44395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lockInfo.l_type = F_RDLCK;
44405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
44415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &posixIoMethods;
44425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
44435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &semIoMethods;
44445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
44455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods
44475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
44485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
44505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
44525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An abstract type for a pointer to a IO method finder function:
44535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
44545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
44555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************************************************************************
44585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**************************** sqlite3_vfs methods ****************************
44595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
44605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This division contains the implementation of methods on the
44615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_vfs object.
44625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
44635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
44655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Initializes a unixFile structure with zeros.
44665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
44675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void initUnixFile(sqlite3_file* file) {
44685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(file, 0, sizeof(unixFile));
44695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
44705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
44725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Initialize the contents of the unixFile structure pointed to by pId.
44735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
44745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int fillInUnixFile(
44755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,      /* Pointer to vfs object */
44765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int h,                  /* Open file descriptor of file being opened */
44775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int syncDir,            /* True to sync directory on first sync */
44785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pId,      /* Write to the unixFile structure here */
44795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zFilename,  /* Name of the file being opened */
44805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int noLock,             /* Omit locking if true */
44815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isDelete,           /* Delete on close if true */
44825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isReadOnly          /* True if the file is opened read-only */
44835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
44845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const sqlite3_io_methods *pLockingStyle;
44855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pNew = (unixFile *)pId;
44865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
44875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pNew->pInode==NULL );
44895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Parameter isDelete is only used on vxworks. Express this explicitly
44915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** here to prevent compiler warnings about unused parameters.
44925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
44935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(isDelete);
44945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Usually the path zFilename should not be a relative pathname. The
44965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** exception is when opening the proxy "conch" file in builds that
44975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** include the special Apple locking styles.
44985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
44995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
45005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( zFilename==0 || zFilename[0]=='/'
45015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    || pVfs->pAppData==(void*)&autolockIoFinder );
45025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
45035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( zFilename==0 || zFilename[0]=='/' );
45045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
45055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
45075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->h = h;
45085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->zPath = zFilename;
4509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if( strcmp(pVfs->zName,"unix-excl")==0 ){
45105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->ctrlFlags = UNIXFILE_EXCL;
45115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
45125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->ctrlFlags = 0;
45135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isReadOnly ){
45155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->ctrlFlags |= UNIXFILE_RDONLY;
45165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( syncDir ){
45185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->ctrlFlags |= UNIXFILE_DIRSYNC;
45195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
45225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->pId = vxworksFindFileId(zFilename);
45235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNew->pId==0 ){
45245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    noLock = 1;
45255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_NOMEM;
45265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
45285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( noLock ){
45305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pLockingStyle = &nolockIoMethods;
45315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
45325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
45335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
45345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Cache zFilename in the locking context (AFP and dotlock override) for
45355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** proxyLock activation is possible (remote proxy is based on db name)
45365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** zFilename remains valid until file is closed, to support */
45375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->lockingContext = (void*)zFilename;
45385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
45395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pLockingStyle == &posixIoMethods
45425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
45435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    || pLockingStyle == &nfsIoMethods
45445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
45455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
45465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixEnterMutex();
45475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = findInodeInfo(pNew, &pNew->pInode);
45485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
45495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If an error occured in findInodeInfo(), close the file descriptor
45505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** immediately, before releasing the mutex. findInodeInfo() may fail
45515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** in two scenarios:
45525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      **
45535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      **   (a) A call to fstat() failed.
45545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      **   (b) A malloc failed.
45555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      **
45565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** Scenario (b) may only occur if the process is holding no other
45575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** file descriptors open on the same file. If there were other file
45585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** descriptors on this file, then no malloc would be required by
45595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** findInodeInfo(). If this is the case, it is quite safe to close
45605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** handle h - as it is guaranteed that no posix locks will be released
45615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** by doing so.
45625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      **
45635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** If scenario (a) caused the error then things are not so safe. The
45645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** implicit assumption here is that if fstat() fails, things are in
45655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** such bad shape that dropping a lock or two doesn't matter much.
45665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
45675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      robust_close(pNew, h, __LINE__);
45685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      h = -1;
45695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
45705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixLeaveMutex();
45715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
45745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if( pLockingStyle == &afpIoMethods ){
45755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* AFP locking uses the file path so it needs to be included in
45765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the afpLockingContext.
45775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
45785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    afpLockingContext *pCtx;
45795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
45805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pCtx==0 ){
45815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
45825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
45835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* NB: zFilename exists and remains valid until the file is closed
45845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** according to requirement F11141.  So we do not need to make a
45855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** copy of the filename. */
45865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCtx->dbPath = zFilename;
45875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCtx->reserved = 0;
45885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      srandomdev();
45895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unixEnterMutex();
45905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = findInodeInfo(pNew, &pNew->pInode);
45915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
45925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sqlite3_free(pNew->lockingContext);
45935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        robust_close(pNew, h, __LINE__);
45945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        h = -1;
45955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
45965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unixLeaveMutex();
45975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
45985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
45995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
46005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if( pLockingStyle == &dotlockIoMethods ){
46025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Dotfile locking uses the file path so it needs to be included in
46035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the dotlockLockingContext
46045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
46055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zLockFile;
46065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nFilename;
46075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nFilename = (int)strlen(zFilename) + 6;
46085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zLockFile = (char *)sqlite3_malloc(nFilename);
46095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zLockFile==0 ){
46105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
46115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
46125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
46135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
46145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->lockingContext = zLockFile;
46155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
46165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
46185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if( pLockingStyle == &semIoMethods ){
46195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Named semaphore locking uses the file path so it needs to be
46205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** included in the semLockingContext
46215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
46225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixEnterMutex();
46235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = findInodeInfo(pNew, &pNew->pInode);
46245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
46255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zSemName = pNew->pInode->aSemName;
46265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int n;
46275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
46285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       pNew->pId->zCanonicalName);
46295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for( n=1; zSemName[n]; n++ )
46305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( zSemName[n]=='/' ) zSemName[n] = '_';
46315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
46325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pNew->pInode->pSem == SEM_FAILED ){
46335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_NOMEM;
46345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pNew->pInode->aSemName[0] = '\0';
46355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
46365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
46375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixLeaveMutex();
46385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
46395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
46405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->lastErrno = 0;
46425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
46435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
46445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( h>=0 ) robust_close(pNew, h, __LINE__);
46455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    h = -1;
46465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    osUnlink(zFilename);
46475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isDelete = 0;
46485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
46495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->isDelete = isDelete;
46505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
46515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
46525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( h>=0 ) robust_close(pNew, h, __LINE__);
46535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
46545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew->pMethod = pLockingStyle;
46555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenCounter(+1);
46565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
46575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
46585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
46595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
46615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the name of a directory in which to put temporary files.
46625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If no suitable temporary file directory can be found, return NULL.
46635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
46645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char *unixTempFileDir(void){
46655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char *azDirs[] = {
46665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0,
46675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0,
46685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "/var/tmp",
46695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "/usr/tmp",
46705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     "/tmp",
46715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     0        /* List terminator */
46725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
46735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int i;
46745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat buf;
46755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zDir = 0;
46765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  azDirs[0] = sqlite3_temp_directory;
46785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
46795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
46805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zDir==0 ) continue;
46815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( osStat(zDir, &buf) ) continue;
46825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !S_ISDIR(buf.st_mode) ) continue;
46835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( osAccess(zDir, 07) ) continue;
46845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
46855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
46865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zDir;
46875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
46885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
46905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Create a temporary file name in zBuf.  zBuf must be allocated
46915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by the calling process and must be big enough to hold at least
46925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pVfs->mxPathname bytes.
46935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
46945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixGetTempname(int nBuf, char *zBuf){
46955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const unsigned char zChars[] =
46965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "abcdefghijklmnopqrstuvwxyz"
46975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
46985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "0123456789";
46995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int i, j;
47005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zDir;
47015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* It's odd to simulate an io-error here, but really this is just
47035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** using the io-error infrastructure to test that SQLite handles this
47045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** function failing.
47055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
47065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR );
47075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zDir = unixTempFileDir();
47095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zDir==0 ) zDir = ".";
47105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check that the output buffer is large enough for the temporary file
47125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** name. If it is not, return SQLITE_ERROR.
47135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
47145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= (size_t)nBuf ){
47155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
47165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
47175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{
47195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
47205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    j = (int)strlen(zBuf);
47215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_randomness(15, &zBuf[j]);
47225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<15; i++, j++){
47235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
47245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
47255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zBuf[j] = 0;
47265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }while( osAccess(zBuf,0)==0 );
47275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
47285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
47295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
47315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
47325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Routine to transform a unixFile into a proxy-locking unixFile.
47335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implementation in the proxy-lock division, but used by unixOpen()
47345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** if SQLITE_PREFER_PROXY_LOCKING is defined.
47355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
47365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyTransformUnixFile(unixFile*, const char*);
47375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
47385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
47405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Search for an unused file descriptor that was opened on the database
47415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file (not a journal or master-journal file) identified by pathname
47425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
47435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** argument to this function.
47445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
47455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Such a file descriptor may exist if a database connection was closed
47465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** but the associated file descriptor could not be closed because some
47475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** other file descriptor open on the same file is holding a file-lock.
47485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Refer to comments in the unixClose() function and the lengthy comment
47495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** describing "Posix Advisory Locking" at the start of this file for
47505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** further details. Also, ticket #4018.
47515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
47525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If a suitable file descriptor is found, then it is returned. If no
47535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** such file descriptor is located, -1 is returned.
47545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
47555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
47565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *pUnused = 0;
47575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Do not search for an unused file descriptor on vxworks. Not because
47595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** vxworks would not benefit from the change (it might, we're not sure),
47605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** but because no way to test it is currently available. It is better
47615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** not to risk breaking vxworks support for the sake of such an obscure
47625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** feature.  */
47635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !OS_VXWORKS
47645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat sStat;                   /* Results of stat() call */
47655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* A stat() call may fail for various reasons. If this happens, it is
47675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** almost certain that an open() call on the same path will also fail.
47685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** For this reason, if an error occurs in the stat() call here, it is
47695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** ignored and -1 is returned. The caller will try to open a new file
47705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** descriptor on the same path, fail, and return an error to SQLite.
47715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
47725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Even if a subsequent open() call does succeed, the consequences of
47735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** not searching for a resusable file descriptor are not dire.  */
47745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( 0==osStat(zPath, &sStat) ){
47755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixInodeInfo *pInode;
47765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixEnterMutex();
47785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pInode = inodeList;
47795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( pInode && (pInode->fileId.dev!=sStat.st_dev
47805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     || pInode->fileId.ino!=sStat.st_ino) ){
47815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       pInode = pInode->pNext;
47825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
47835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pInode ){
47845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnixUnusedFd **pp;
47855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
47865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pUnused = *pp;
47875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pUnused ){
47885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *pp = pUnused->pNext;
47895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
47905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
47915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixLeaveMutex();
47925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
47935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif    /* if !OS_VXWORKS */
47945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pUnused;
47955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
47965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
47985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called by unixOpen() to determine the unix permissions
47995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to create new files with. If no error occurs, then SQLITE_OK is returned
48005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and a value suitable for passing as the third argument to open(2) is
48015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** written to *pMode. If an IO error occurs, an SQLite error code is
48025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returned and the value of *pMode is not modified.
48035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
48045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the file being opened is a temporary file, it is always created with
48055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the octal permissions 0600 (read/writable by owner only). If the file
48065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is a database or master journal file, it is created with the permissions
48075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** mask SQLITE_DEFAULT_FILE_PERMISSIONS.
48085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
48095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Finally, if the file being opened is a WAL or regular journal file, then
48105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this function queries the file-system for the permissions on the
48115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** corresponding database file and sets *pMode to this value. Whenever
48125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** possible, WAL and journal files are created using the same permissions
48135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** as the associated database file.
48145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
48155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int findCreateFileMode(
48165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,              /* Path of file (possibly) being created */
48175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,                      /* Flags passed as 4th argument to xOpen() */
48185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode_t *pMode                   /* OUT: Permissions to open file with */
48195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
48205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;             /* Return Code */
48215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
48225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char zDb[MAX_PATHNAME+1];     /* Database file path */
48235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nDb;                      /* Number of valid bytes in zDb */
48245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct stat sStat;            /* Output of stat() on database file */
48255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* zPath is a path to a WAL or journal file. The following block derives
48275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the path to the associated database file from zPath. This block handles
48285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** the following naming conventions:
48295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **
48305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **   "<path to db>-journal"
48315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **   "<path to db>-wal"
48325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **   "<path to db>-journal-NNNN"
48335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **   "<path to db>-wal-NNNN"
48345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **
48355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** where NNNN is a 4 digit decimal number. The NNNN naming schemes are
48365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** used by the test_multiplex.c module.
48375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
48385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nDb = sqlite3Strlen30(zPath) - 1;
48395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( nDb>0 && zPath[nDb]!='l' ) nDb--;
48405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7);
48415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(zDb, zPath, nDb);
48425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zDb[nDb] = '\0';
48435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( 0==osStat(zDb, &sStat) ){
48455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pMode = sStat.st_mode & 0777;
48465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
48475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_FSTAT;
48485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
48495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
48505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pMode = 0600;
48515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
48525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
48535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
48545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
48555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
48565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
48585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Initializes a unixFile structure with zeros.
48595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
48605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void chromium_sqlite3_initialize_unix_sqlite3_file(sqlite3_file* file) {
48615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(file, 0, sizeof(unixFile));
48625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
48635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* vfs,
48655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int fd,
48665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int dirfd,
48675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               sqlite3_file* file,
48685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const char* fileName,
48695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int noLock,
48705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int isDelete) {
48715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fillInUnixFile(vfs, fd, dirfd, file, fileName, noLock, isDelete, 0);
48725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
48735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
48755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Search for an unused file descriptor that was opened on the database file.
48765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If a suitable file descriptor if found, then it is stored in *fd; otherwise,
48775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** *fd is not modified.
48785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
48795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If a reusable file descriptor is not found, and a new UnixUnusedFd cannot
48805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** be allocated, SQLITE_NOMEM is returned. Otherwise, SQLITE_OK is returned.
48815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
48825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int chromium_sqlite3_get_reusable_file_handle(sqlite3_file* file,
48835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const char* fileName,
48845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int flags,
48855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              int* fd) {
48865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile* unixSQLite3File = (unixFile*)file;
48875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fileType = flags & 0xFFFFFF00;
48885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fileType == SQLITE_OPEN_MAIN_DB) {
48895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnixUnusedFd *unusedFd = findReusableFd(fileName, flags);
48905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unusedFd) {
48915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *fd = unusedFd->fd;
48925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
48935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unusedFd = sqlite3_malloc(sizeof(*unusedFd));
48945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!unusedFd) {
48955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_NOMEM;
48965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
48975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
48985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixSQLite3File->pUnused = unusedFd;
48995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
49005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
49015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
49045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Marks 'fd' as the unused file descriptor for 'pFile'.
49055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
49065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void chromium_sqlite3_update_reusable_file_handle(sqlite3_file* file,
49075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  int fd,
49085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  int flags) {
49095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile* unixSQLite3File = (unixFile*)file;
49105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unixSQLite3File->pUnused) {
49115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixSQLite3File->pUnused->fd = fd;
49125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixSQLite3File->pUnused->flags = flags;
49135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
49145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
49175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Destroys pFile's field that keeps track of the unused file descriptor.
49185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
49195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void chromium_sqlite3_destroy_reusable_file_handle(sqlite3_file* file) {
49205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile* unixSQLite3File = (unixFile*)file;
49215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(unixSQLite3File->pUnused);
49225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
49235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
49255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open the file zPath.
49265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
49275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Previously, the SQLite OS layer used three functions in place of this
49285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** one:
49295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
49305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     sqlite3OsOpenReadWrite();
49315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     sqlite3OsOpenReadOnly();
49325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     sqlite3OsOpenExclusive();
49335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
49345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** These calls correspond to the following combinations of flags:
49355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
49365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     ReadWrite() ->     (READWRITE | CREATE)
49375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     ReadOnly()  ->     (READONLY)
49385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
49395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
49405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The old OpenExclusive() accepted a boolean argument - "delFlag". If
49415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** true, the file was configured to be automatically deleted when the
49425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file handle closed. To achieve the same effect using this new
49435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** interface, add the DELETEONCLOSE flag to those specified above for
49445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** OpenExclusive().
49455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
49465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixOpen(
49475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,           /* The VFS for which this is the xOpen method */
49485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,           /* Pathname of file to be opened */
49495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,         /* The file descriptor to be filled in */
49505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,                   /* Input flags to control the opening */
49515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pOutFlags               /* Output flags returned to SQLite core */
49525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
49535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *p = (unixFile *)pFile;
49545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = -1;                   /* File descriptor returned by open() */
49555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int openFlags = 0;             /* Flags to pass to open() */
49565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eType = flags&0xFFFFFF00;  /* Type of file to open */
49575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int noLock;                    /* True to omit locking primitives */
49585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;            /* Function Return Code */
49595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
49615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
49625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isCreate     = (flags & SQLITE_OPEN_CREATE);
49635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
49645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
49655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
49665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isAutoProxy  = (flags & SQLITE_OPEN_AUTOPROXY);
49675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
49685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If creating a master or main-file journal, this function will open
49705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** a file-descriptor on the directory too. The first time unixSync()
49715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** is called the directory file descriptor will be fsync()ed and close()d.
49725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
49735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int syncDir = (isCreate && (
49745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        eType==SQLITE_OPEN_MASTER_JOURNAL
49755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     || eType==SQLITE_OPEN_MAIN_JOURNAL
49765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     || eType==SQLITE_OPEN_WAL
49775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ));
49785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If argument zPath is a NULL pointer, this function is required to open
49805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** a temporary file. Use this buffer to store the file name in.
49815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
49825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zTmpname[MAX_PATHNAME+1];
49835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName = zPath;
49845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check the following statements are true:
49865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
49875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and
49885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (b) if CREATE is set, then READWRITE must also be set, and
49895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
49905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
49915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
49925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
49935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(isCreate==0 || isReadWrite);
49945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(isExclusive==0 || isCreate);
49955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(isDelete==0 || isCreate);
49965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The main DB, main journal, WAL file and master journal are never
49985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** automatically deleted. Nor are they ever temporary files.  */
49995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
50005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
50015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
50025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
50035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Assert that the upper layer has set one of the "file-type" flags. */
50055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB
50065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
50075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL
50085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
50095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
50105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chromium_sqlite3_initialize_unix_sqlite3_file(pFile);
50125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( eType==SQLITE_OPEN_MAIN_DB ){
50145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = chromium_sqlite3_get_reusable_file_handle(pFile, zName, flags, &fd);
50155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
50165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
50175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
50185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( !zName ){
50195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If zName is NULL, the upper layer is requesting a temp file. */
50205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(isDelete && !syncDir);
50215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = unixGetTempname(MAX_PATHNAME+1, zTmpname);
50225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
50235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
50245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
50255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zName = zTmpname;
50265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
50275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Determine the value of the flags parameter passed to POSIX function
50295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** open(). These must be calculated even if open() is not called, as
50305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** they may be stored as part of the file handle and used by the
50315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** 'conch file' locking functions later on.  */
50325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isReadonly )  openFlags |= O_RDONLY;
50335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isReadWrite ) openFlags |= O_RDWR;
50345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isCreate )    openFlags |= O_CREAT;
50355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
50365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  openFlags |= (O_LARGEFILE|O_BINARY);
50375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fd<0 ){
50395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mode_t openMode;              /* Permissions to create file with */
50405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = findCreateFileMode(zName, flags, &openMode);
50415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
50425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( !p->pUnused );
50435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
50445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
50455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
50465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fd = robust_open(zName, openFlags, openMode);
50475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
50485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
50495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Failed to open the file for read/write access. Try read-only. */
50505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
50515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      openFlags &= ~(O_RDWR|O_CREAT);
50525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags |= SQLITE_OPEN_READONLY;
50535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      openFlags |= O_RDONLY;
50545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      isReadonly = 1;
50555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fd = robust_open(zName, openFlags, openMode);
50565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
50575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( fd<0 ){
50585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
50595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto open_finished;
50605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
50615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
50625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( fd>=0 );
50635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pOutFlags ){
50645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pOutFlags = flags;
50655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
50665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chromium_sqlite3_update_reusable_file_handle(pFile, fd, flags);
50685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isDelete ){
50705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
50715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zPath = zName;
50725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
50735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    osUnlink(zName);
50745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
50755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
50765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
50775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else{
50785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->openFlags = openFlags;
50795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
50805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
50815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef FD_CLOEXEC
50835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
50845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
50855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  noLock = eType!=SQLITE_OPEN_MAIN_DB;
50875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
50905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct statfs fsInfo;
50915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fstatfs(fd, &fsInfo) == -1 ){
50925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((unixFile*)pFile)->lastErrno = errno;
50935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    robust_close(p, fd, __LINE__);
50945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_ACCESS;
50955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
50965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
50975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
50985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
50995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
51005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
51025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_PREFER_PROXY_LOCKING
51035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  isAutoProxy = 1;
51045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
51055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
51065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
51075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int useProxy = 0;
51085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
51105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** never use proxy, NULL means use proxy for non-local files only.  */
51115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( envforce!=NULL ){
51125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      useProxy = atoi(envforce)>0;
51135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
51145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct statfs fsInfo;
51155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( statfs(zPath, &fsInfo) == -1 ){
51165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* In theory, the close(fd) call is sub-optimal. If the file opened
51175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** with fd is a database file, and there are other connections open
51185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** on that file that are currently holding advisory locks on it,
51195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** then the call to close() will cancel those locks. In practice,
51205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** we're assuming that statfs() doesn't fail very often. At least
51215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** not while other file descriptors opened by the same process on
51225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ** the same file are working.  */
51235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        p->lastErrno = errno;
51245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        robust_close(p, fd, __LINE__);
51255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_IOERR_ACCESS;
51265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto open_finished;
51275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
51285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      useProxy = !(fsInfo.f_flags&MNT_LOCAL);
51295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
51305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( useProxy ){
51315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
51325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          isDelete, isReadonly);
51335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
51345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
51355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( rc!=SQLITE_OK ){
51365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* Use unixClose to clean up the resources added in fillInUnixFile
51375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** and clear all the structure's references.  Specifically,
51385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
51395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
51405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          unixClose(pFile);
51415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return rc;
51425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
51435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
51445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto open_finished;
51455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
51465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
51475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
51485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = fillInUnixFile(pVfs, fd, syncDir, pFile, zPath, noLock,
51505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      isDelete, isReadonly);
51515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)open_finished:
51525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
51535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chromium_sqlite3_destroy_reusable_file_handle(pFile);
51545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
51555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
51565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
51575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
51605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the file at zPath. If the dirSync argument is true, fsync()
51615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the directory after deleting the file.
51625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
51635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixDelete(
51645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *NotUsed,     /* VFS containing this as the xDelete method */
51655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,        /* Name of file to be deleted */
51665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int dirSync               /* If true, fsync() directory after deleting file */
51675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
51685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
51695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
51705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError(return SQLITE_IOERR_DELETE);
51715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
51725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
51735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
51745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_DISABLE_DIRSYNC
51755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( dirSync ){
51765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int fd;
51775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = osOpenDirectory(zPath, &fd);
51785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
51795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
51805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( fsync(fd)==-1 )
51815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
51825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( fsync(fd) )
51835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
51845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
51855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
51865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
51875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      robust_close(0, fd, __LINE__);
51885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else if( rc==SQLITE_CANTOPEN ){
51895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_OK;
51905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
51915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
51925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
51935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
51945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
51955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
51975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Test the existance of or access permissions of file zPath. The
51985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** test performed depends on the value of flags:
51995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
52005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
52015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
52025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
52035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
52045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise return 0.
52055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
52065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixAccess(
52075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *NotUsed,   /* The VFS containing this xAccess method */
52085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,      /* Path of the file to examine */
52095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,              /* What do we want to learn about the zPath file? */
52105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pResOut            /* Write result boolean here */
52115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
52125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amode = 0;
52135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
52145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_ACCESS; );
52155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( flags ){
52165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ACCESS_EXISTS:
52175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      amode = F_OK;
52185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
52195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ACCESS_READWRITE:
52205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      amode = W_OK|R_OK;
52215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
52225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ACCESS_READ:
52235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      amode = R_OK;
52245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
52255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
52275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(!"Invalid flags argument");
52285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
52295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = (osAccess(zPath, amode)==0);
52305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
52315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct stat buf;
52325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( 0==osStat(zPath, &buf) && buf.st_size==0 ){
52335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pResOut = 0;
52345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
52355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
52365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
52375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
52385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
52415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Turn a relative pathname into a full pathname. The relative path
52425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is stored as a nul-terminated string in the buffer pointed to by
52435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** zPath.
52445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
52455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
52465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (in this case, MAX_PATHNAME bytes). The full-path is written to
52475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this buffer before returning.
52485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
52495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixFullPathname(
52505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
52515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,            /* Possibly relative input path */
52525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nOut,                     /* Size of output buffer in bytes */
52535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zOut                    /* Output buffer */
52545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
52555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* It's odd to simulate an io-error here, but really this is just
52575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** using the io-error infrastructure to test that SQLite handles this
52585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** function failing. This function could fail if, for example, the
52595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** current working directory has been unlinked.
52605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
52615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_ERROR );
52625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pVfs->mxPathname==MAX_PATHNAME );
52645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
52655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zOut[nOut-1] = '\0';
52675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zPath[0]=='/' ){
52685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nOut, zOut, "%s", zPath);
52695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
52705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nCwd;
52715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( osGetcwd(zOut, nOut-1)==0 ){
52725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
52735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
52745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nCwd = (int)strlen(zOut);
52755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
52765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
52775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
52785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
52795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_LOAD_EXTENSION
52825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
52835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Interfaces for opening a shared library, finding entry points
52845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** within the shared library, and closing the shared library.
52855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
52865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
52875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
52885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
52895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
52905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
52915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
52935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLite calls this function immediately after a call to unixDlSym() or
52945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** unixDlOpen() fails (returns a null pointer). If a more detailed error
52955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** message is available, it is written to zBufOut. If no error message
52965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is available, zBufOut is left unmodified and SQLite uses a default
52975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** error message.
52985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
52995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
53005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zErr;
53015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
53025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixEnterMutex();
53035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zErr = dlerror();
53045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zErr ){
53055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
53065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
53075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixLeaveMutex();
53085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
53095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
53105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
53115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** GCC with -pedantic-errors says that C90 does not allow a void* to be
53125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** cast into a pointer to a function.  And yet the library dlsym() routine
53135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** returns a void* which is really a pointer to a function.  So how do we
53145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** use dlsym() with -pedantic-errors?
53155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
53165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Variable x below is defined to be a pointer to a function taking
53175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** parameters void* and const char* and returning a pointer to a function.
53185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** We initialize x by assigning it a pointer to the dlsym() function.
53195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** (That assignment requires a cast.)  Then we call the function that
53205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** x points to.
53215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
53225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** This work-around is unlikely to work correctly on any system where
53235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** you really cannot cast a function pointer into void*.  But then, on the
53245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** other hand, dlsym() will not work on such a system either, so we have
53255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** not really lost anything.
53265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
53275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void (*(*x)(void*,const char*))(void);
53285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
53295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  x = (void(*(*)(void*,const char*))(void))dlsym;
53305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (*x)(p, zSym);
53315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
53325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
53335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
53345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dlclose(pHandle);
53355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
53365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
53375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define unixDlOpen  0
53385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define unixDlError 0
53395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define unixDlSym   0
53405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define unixDlClose 0
53415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
53425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
53445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write nBuf bytes of random data to the supplied buffer zBuf.
53455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
53465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
53475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
53485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
53495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* We have to initialize zBuf to prevent valgrind from reporting
53515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** errors.  The reports issued by valgrind are incorrect - we would
53525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** prefer that the randomness be increased by making use of the
53535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** uninitialized space in zBuf - but valgrind errors tend to worry
53545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** some users.  Rather than argue, it seems easier just to initialize
53555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the whole array and silence valgrind, even if that means less randomness
53565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** in the random seed.
53575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
53585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** When testing, initializing zBuf[] to zero is all we do.  That means
53595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** that we always use the same random number sequence.  This makes the
53605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** tests repeatable.
53615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
53625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(zBuf, 0, nBuf);
53635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(SQLITE_TEST)
53645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
53655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int pid, fd;
53665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fd = robust_open("/dev/urandom", O_RDONLY, 0);
53675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( fd<0 ){
53685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      time_t t;
53695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      time(&t);
53705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(zBuf, &t, sizeof(t));
53715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pid = getpid();
53725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
53735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
53745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nBuf = sizeof(t) + sizeof(pid);
53755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
53765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      do{ nBuf = osRead(fd, zBuf, nBuf); }while( nBuf<0 && errno==EINTR );
53775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      robust_close(0, fd, __LINE__);
53785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
53795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
53805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
53815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return nBuf;
53825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
53835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
53865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sleep for a little while.  Return the amount of time slept.
53875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The argument is the number of microseconds we want to sleep.
53885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The return value is the number of microseconds of sleep actually
53895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** requested from the underlying operating system, a number which
53905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** might be greater than or equal to the argument, but not less
53915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** than the argument.
53925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
53935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
53945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
53955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct timespec sp;
53965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sp.tv_sec = microseconds / 1000000;
53985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sp.tv_nsec = (microseconds % 1000000) * 1000;
53995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nanosleep(&sp, NULL);
54005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
54015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return microseconds;
54025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_USLEEP) && HAVE_USLEEP
54035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  usleep(microseconds);
54045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
54055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return microseconds;
54065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
54075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int seconds = (microseconds+999999)/1000000;
54085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sleep(seconds);
54095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
54105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return seconds*1000000;
54115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
54125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
54135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
54155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following variable, if set to a non-zero value, is interpreted as
54165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the number of seconds since 1970 and is used to set the result of
54175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3OsCurrentTime() during testing.
54185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
54195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
54205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_current_time = 0;  /* Fake system time in seconds since 1970. */
54215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
54225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
54245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Find the current time (in Universal Coordinated Time).  Write into *piNow
54255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the current time and date as a Julian Day number times 86_400_000.  In
54265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** other words, write into *piNow the number of milliseconds since the Julian
54275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** epoch of noon in Greenwich on November 24, 4714 B.C according to the
54285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** proleptic Gregorian calendar.
54295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
54305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** On success, return 0.  Return 1 if the time and date cannot be found.
54315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
54325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
54335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
54345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(NO_GETTOD)
54355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time_t t;
54365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time(&t);
54375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
54385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif OS_VXWORKS
54395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct timespec sNow;
54405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  clock_gettime(CLOCK_REALTIME, &sNow);
54415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
54425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
54435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct timeval sNow;
54445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gettimeofday(&sNow, 0);
54455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
54465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
54475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
54495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3_current_time ){
54505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
54515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
54525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
54535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
54545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
54555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
54565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
54585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Find the current time (in Universal Coordinated Time).  Write the
54595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** current time and date as a Julian Day number into *prNow and
54605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** return 0.  Return 1 if the time and date cannot be found.
54615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
54625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
54635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 i;
54645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
54655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixCurrentTimeInt64(0, &i);
54665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *prNow = i/86400000.0;
54675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
54685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
54695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
54715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** We added the xGetLastError() method with the intention of providing
54725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** better low-level error messages when operating-system problems come up
54735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** during SQLite operation.  But so far, none of that has been implemented
54745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the core.  So this routine is never called.  For now, it is merely
54755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a place-holder.
54765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
54775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
54785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed);
54795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed2);
54805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(NotUsed3);
54815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
54825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
54835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
54865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)************************ End of sqlite3_vfs methods ***************************
54875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
54885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/******************************************************************************
54905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)************************** Begin Proxy Locking ********************************
54915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
54925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Proxy locking is a "uber-locking-method" in this sense:  It uses the
54935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** other locking methods on secondary lock files.  Proxy locking is a
54945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** meta-layer over top of the primitive locking implemented above.  For
54955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this reason, the division that implements of proxy locking is deferred
54965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** until late in the file (here) after all of the other I/O methods have
54975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** been defined - so that the primitive locking methods are available
54985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** as services to help with the implementation of proxy locking.
54995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)****
55015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The default locking schemes in SQLite use byte-range locks on the
55035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database file to coordinate safe, concurrent access by multiple readers
55045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and writers [http://sqlite.org/lockingv3.html].  The five file locking
55055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
55065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** as POSIX read & write locks over fixed set of locations (via fsctl),
55075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on AFP and SMB only exclusive byte-range locks are available via fsctl
55085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
55095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
55105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** address in the shared range is taken for a SHARED lock, the entire
55115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** shared range is taken for an EXCLUSIVE lock):
55125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      PENDING_BYTE        0x40000000
55145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      RESERVED_BYTE       0x40000001
55155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      SHARED_RANGE        0x40000002 -> 0x40000200
55165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This works well on the local file system, but shows a nearly 100x
55185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** slowdown in read performance on AFP because the AFP client disables
55195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the read cache when byte-range locks are present.  Enabling the read
55205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** cache exposes a cache coherency problem that is present on all OS X
55215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** supported network file systems.  NFS and AFP both observe the
55225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** close-to-open semantics for ensuring cache coherency
55235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
55245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** address the requirements for concurrent database access by multiple
55255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** readers and writers
55265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
55275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** To address the performance and cache coherency issues, proxy file locking
55295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** changes the way database access is controlled by limiting access to a
55305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** single host at a time and moving file locks off of the database file
55315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and onto a proxy file on the local file system.
55325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Using proxy locks
55355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** -----------------
55365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** C APIs
55385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
55405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                       <proxy_path> | ":auto:");
55415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
55425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQL pragmas
55455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
55475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  PRAGMA [database.]lock_proxy_file
55485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Specifying ":auto:" means that if there is a conch file with a matching
55505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** host ID in it, the proxy path in the conch file will be used, otherwise
55515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a proxy path based on the user's temp dir
55525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
55535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** actual proxy file name is generated from the name and path of the
55545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** database file.  For example:
55555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       For database path "/Users/me/foo.db"
55575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
55585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Once a lock proxy is configured for a database connection, it can not
55605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** be removed, however it may be switched to a different proxy path via
55615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the above APIs (assuming the conch file is not being held by another
55625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** connection or process).
55635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** How proxy locking works
55665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** -----------------------
55675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Proxy file locking relies primarily on two new supporting files:
55695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  conch file to limit access to the database file to a single host
55715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      at a time
55725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   *  proxy file to act as a proxy for the advisory locks normally
55745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      taken on the database
55755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The conch file - to use a proxy file, sqlite must first "hold the conch"
55775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by taking an sqlite-style shared lock on the conch file, reading the
55785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** contents and comparing the host's unique host ID (see below) and lock
55795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** proxy path against the values stored in the conch.  The conch file is
55805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** stored in the same directory as the database file and the file name
55815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is patterned after the database file name as ".<databasename>-conch".
55825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the conch file does not exist, or it's contents do not match the
55835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** host ID and/or proxy path, then the lock is escalated to an exclusive
55845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lock and the conch file contents is updated with the host ID and proxy
55855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** path and the lock is downgraded to a shared lock again.  If the conch
55865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is held by another process (with a shared lock), the exclusive lock
55875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will fail and SQLITE_BUSY is returned.
55885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The proxy file - a single-byte file used for all advisory file locks
55905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** normally taken on the database file.   This allows for safe sharing
55915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the database file for multiple readers and writers on the same
55925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** host (the conch ensures that they all use the same local lock file).
55935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
55945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Requesting the lock proxy does not immediately take the conch, it is
55955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** only taken when the first request to lock database file is made.
55965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This matches the semantics of the traditional locking behavior, where
55975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** opening a connection to a database file does not take a lock on it.
55985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The shared lock and an open file descriptor are maintained until
55995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the connection to the database is closed.
56005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The proxy file and the lock file are never deleted so they only need
56025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to be created the first time they are used.
56035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Configuration options
56055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ---------------------
56065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  SQLITE_PREFER_PROXY_LOCKING
56085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       Database files accessed on non-local file systems are
56105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       automatically configured for proxy locking, lock files are
56115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       named automatically using the same logic as
56125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       PRAGMA lock_proxy_file=":auto:"
56135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  SQLITE_PROXY_DEBUG
56155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       Enables the logging of error messages during host id file
56175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       retrieval and creation
56185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  LOCKPROXYDIR
56205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       Overrides the default directory used for lock proxy files that
56225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       are named automatically via the ":auto:" setting
56235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
56255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       Permissions to use when creating a directory for storing the
56275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       lock proxy files, only used when LOCKPROXYDIR is not set.
56285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
56305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
56315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
56325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** force proxy locking to be used for every database file opened, and 0
56335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will force automatic proxy locking to be disabled for all database
56345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
56355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
56365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
56375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
56395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Proxy locking is only available on MacOSX
56405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
56415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
56425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
56445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The proxyLockingContext has the path and file structures for the remote
56455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and local proxy files in it
56465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
56475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct proxyLockingContext proxyLockingContext;
56485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct proxyLockingContext {
56495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *conchFile;         /* Open conch file */
56505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *conchFilePath;         /* Name of the conch file */
56515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *lockProxy;         /* Open proxy lock file */
56525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *lockProxyPath;         /* Name of the proxy lock file */
56535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *dbPath;                /* Name of the open file */
56545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int conchHeld;               /* 1 if the conch is held, -1 if lockless */
56555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *oldLockingContext;     /* Original lockingcontext to restore on close */
56565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_io_methods const *pOldMethod;     /* Original I/O methods for close */
56575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
56585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
56605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The proxy lock file path for the database at dbPath is written into lPath,
56615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** which must point to valid, writable memory large enough for a maxLen length
56625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file path.
56635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
56645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
56655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len;
56665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int dbLen;
56675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
56685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef LOCKPROXYDIR
56705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
56715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
56725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifdef _CS_DARWIN_USER_TEMP_DIR
56735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
56745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
56755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("GETLOCKPATH  failed %s errno=%d pid=%d\n",
56765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               lPath, errno, getpid()));
56775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_IOERR_LOCK;
56785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
56795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = strlcat(lPath, "sqliteplocks", maxLen);
56805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
56815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# else
56825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  len = strlcpy(lPath, "/tmp/", maxLen);
56835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
56845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
56855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( lPath[len-1]!='/' ){
56875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = strlcat(lPath, "/", maxLen);
56885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
56895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
56905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* transform the db path to a unique cache name */
56915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbLen = (int)strlen(dbPath);
56925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
56935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char c = dbPath[i];
56945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lPath[i+len] = (c=='/')?'_':c;
56955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
56965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lPath[i+len]='\0';
56975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strlcat(lPath, ":auto:", maxLen);
56985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("GETLOCKPATH  proxy lock path=%s pid=%d\n", lPath, getpid()));
56995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
57005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
57015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
57035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Creates the lock file and any missing directories in lockPath
57045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
57055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyCreateLockPath(const char *lockPath){
57065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i, len;
57075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[MAXPATHLEN];
57085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int start = 0;
57095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(lockPath!=NULL);
57115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* try to create all the intermediate directories */
57125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  len = (int)strlen(lockPath);
57135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buf[0] = lockPath[0];
57145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for( i=1; i<len; i++ ){
57155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( lockPath[i] == '/' && (i - start > 0) ){
57165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* only mkdir if leaf dir != "." or "/" or ".." */
57175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
57185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
57195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf[i]='\0';
57205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
57215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          int err=errno;
57225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( err!=EEXIST ) {
57235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            OSTRACE(("CREATELOCKPATH  FAILED creating %s, "
57245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "'%s' proxy lock path=%s pid=%d\n",
57255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     buf, strerror(err), lockPath, getpid()));
57265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return err;
57275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
57285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
57295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
57305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start=i+1;
57315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
57325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf[i] = lockPath[i];
57335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
57345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("CREATELOCKPATH  proxy lock path=%s pid=%d\n", lockPath, getpid()));
57355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
57365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
57375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
57395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Create a new VFS file descriptor (stored in memory obtained from
57405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_malloc) and open the file named "path" in the file descriptor.
57415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
57425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The caller is responsible not only for closing the file descriptor
57435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** but also for freeing the memory associated with the file descriptor.
57445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
57455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyCreateUnixFile(
57465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *path,        /* path for the new unixFile */
57475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile **ppFile,       /* unixFile created and returned by ref */
57485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int islockfile           /* if non zero missing dirs will be created */
57495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)) {
57505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = -1;
57515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pNew;
57525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
57535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int openFlags = O_RDWR | O_CREAT;
57545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs dummyVfs;
57555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int terrno = 0;
57565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnixUnusedFd *pUnused = NULL;
57575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* 1. first try to open/create the file
57595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** 2. if that fails, and this is a lock file (not-conch), try creating
57605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the parent directories and then try again.
57615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** 3. if that fails, try to open the file read-only
57625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
57635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
57645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pUnused = findReusableFd(path, openFlags);
57655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pUnused ){
57665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fd = pUnused->fd;
57675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
57685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pUnused = sqlite3_malloc(sizeof(*pUnused));
57695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !pUnused ){
57705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
57715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
57725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
57735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fd<0 ){
57745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
57755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    terrno = errno;
57765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( fd<0 && errno==ENOENT && islockfile ){
57775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( proxyCreateLockPath(path) == SQLITE_OK ){
57785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
57795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
57805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
57815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
57825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fd<0 ){
57835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    openFlags = O_RDONLY;
57845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
57855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    terrno = errno;
57865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
57875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fd<0 ){
57885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( islockfile ){
57895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_BUSY;
57905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
57915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (terrno) {
57925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case EACCES:
57935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_PERM;
57945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case EIO:
57955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_IOERR_LOCK; /* even though it is the conch */
57965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
57975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_CANTOPEN_BKPT;
57985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
57995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
58005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
58025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNew==NULL ){
58035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_NOMEM;
58045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_create_proxy;
58055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
58065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pNew, 0, sizeof(unixFile));
58075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->openFlags = openFlags;
58085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&dummyVfs, 0, sizeof(dummyVfs));
58095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dummyVfs.pAppData = (void*)&autolockIoFinder;
58105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dummyVfs.zName = "dummy";
58115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pUnused->fd = fd;
58125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pUnused->flags = openFlags;
58135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->pUnused = pUnused;
58145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = fillInUnixFile(&dummyVfs, fd, 0, (sqlite3_file*)pNew, path, 0, 0, 0);
58165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
58175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *ppFile = pNew;
58185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
58195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
58205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)end_create_proxy:
58215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  robust_close(pNew, fd, __LINE__);
58225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pNew);
58235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pUnused);
58245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
58255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
58265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
58285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* simulate multiple hosts by creating unique hostid file paths */
58295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_hostid_num = 0;
58305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
58315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROXY_HOSTIDLEN    16  /* conch file host id length */
58335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Not always defined in the headers as it ought to be */
58355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern int gethostuuid(uuid_t id, const struct timespec *wait);
58365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
58385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes of writable memory.
58395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
58405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyGetHostID(unsigned char *pHostID, int *pError){
58415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
58425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pHostID, 0, PROXY_HOSTIDLEN);
58435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\
58445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               && __MAC_OS_X_VERSION_MIN_REQUIRED<1050
58455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
58465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
58475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( gethostuuid(pHostID, &timeout) ){
58485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int err = errno;
58495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pError ){
58505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *pError = err;
58515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
58525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_IOERR;
58535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
58545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
58555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
58565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
58575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* simulate multiple hosts by creating unique hostid file paths */
58585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3_hostid_num != 0){
58595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
58605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
58615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
58625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
58645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
58655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The conch file contains the header, host id and lock file path
58675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
58685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROXY_CONCHVERSION 2   /* 1-byte header, 16-byte host id, path */
58695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROXY_HEADERLEN    1   /* conch file header length */
58705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROXY_PATHINDEX    (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
58715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PROXY_MAXCONCHLEN  (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
58725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
58745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Takes an open conch file, copies the contents to a new path and then moves
58755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it back.  The newly created file's file descriptor is assigned to the
58765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** conch file structure and finally the original conch file descriptor is
58775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** closed.  Returns zero if successful.
58785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
58795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
58805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
58815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *conchFile = pCtx->conchFile;
58825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char tPath[MAXPATHLEN];
58835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[PROXY_MAXCONCHLEN];
58845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *cPath = pCtx->conchFilePath;
58855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t readLen = 0;
58865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t pathLen = 0;
58875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char errmsg[64] = "";
58885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = -1;
58895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = -1;
58905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(myHostID);
58915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* create a new path by replace the trailing '-conch' with '-break' */
58935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
58945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pathLen>MAXPATHLEN || pathLen<6 ||
58955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
58965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
58975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_breaklock;
58985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
58995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* read the conch content */
59005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
59015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( readLen<PROXY_PATHINDEX ){
59025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
59035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_breaklock;
59045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
59055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* write it out to the temporary break file */
59065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL),
59075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   SQLITE_DEFAULT_FILE_PERMISSIONS);
59085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fd<0 ){
59095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
59105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_breaklock;
59115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
59125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
59135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
59145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_breaklock;
59155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
59165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rename(tPath, cPath) ){
59175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
59185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto end_breaklock;
59195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
59205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = 0;
59215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(stderr, "broke stale lock on %s\n", cPath);
59225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  robust_close(pFile, conchFile->h, __LINE__);
59235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  conchFile->h = fd;
59245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  conchFile->openFlags = O_RDWR | O_CREAT;
59255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)end_breaklock:
59275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc ){
59285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( fd>=0 ){
59295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      osUnlink(tPath);
59305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      robust_close(pFile, fd, __LINE__);
59315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
59325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
59335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
59345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
59355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
59365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Take the requested lock on the conch file and break a stale lock if the
59385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** host id matches.
59395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
59405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
59415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
59425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *conchFile = pCtx->conchFile;
59435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
59445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nTries = 0;
59455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct timespec conchModTime;
59465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
59485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
59495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nTries ++;
59505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_BUSY ){
59515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If the lock failed (busy):
59525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * 1st try: get the mod time of the conch, wait 0.5s and try again.
59535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * 2nd try: fail if the mod time changed or host id is different, wait
59545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *           10 sec and try again
59555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * 3rd try: break the lock unless the mod time has changed.
59565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
59575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct stat buf;
59585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( osFstat(conchFile->h, &buf) ){
59595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->lastErrno = errno;
59605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_IOERR_LOCK;
59615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
59625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( nTries==1 ){
59645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        conchModTime = buf.st_mtimespec;
59655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        usleep(500000); /* wait 0.5 sec and try the lock again*/
59665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
59675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
59685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( nTries>1 );
59705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
59715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
59725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_BUSY;
59735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
59745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( nTries==2 ){
59765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char tBuf[PROXY_MAXCONCHLEN];
59775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
59785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( len<0 ){
59795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pFile->lastErrno = errno;
59805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SQLITE_IOERR_LOCK;
59815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
59825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
59835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* don't break the lock if the host id doesn't match */
59845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
59855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SQLITE_BUSY;
59865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
59875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
59885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* don't break the lock on short read or a version mismatch */
59895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return SQLITE_BUSY;
59905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
59915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        usleep(10000000); /* wait 10 sec and try the lock again */
59925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
59935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
59945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( nTries==3 );
59965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( 0==proxyBreakConchLock(pFile, myHostID) ){
59975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_OK;
59985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( lockType==EXCLUSIVE_LOCK ){
59995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
60005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
60015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( !rc ){
60025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
60035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
60045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
60055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
60065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while( rc==SQLITE_BUSY && nTries<3 );
60075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
60095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
60105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Takes the conch by taking a shared lock and read the contents conch, if
60125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lockPath is non-NULL, the host ID and lock file path must match.  A NULL
60135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** lockPath means that the lockPath in the conch file will be used if the
60145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** host IDs match, or a new lock path will be generated automatically
60155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and written to the conch file.
60165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
60175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyTakeConch(unixFile *pFile){
60185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
60195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCtx->conchHeld!=0 ){
60215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
60225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
60235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *conchFile = pCtx->conchFile;
60245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uuid_t myHostID;
60255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int pError = 0;
60265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char readBuf[PROXY_MAXCONCHLEN];
60275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char lockPath[MAXPATHLEN];
60285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *tempLockPath = NULL;
60295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc = SQLITE_OK;
60305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int createConch = 0;
60315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int hostIdMatch = 0;
60325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int readLen = 0;
60335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int tryOldLockPath = 0;
60345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int forceNewLockPath = 0;
60355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("TAKECONCH  %d for %s pid=%d\n", conchFile->h,
60375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
60385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = proxyGetHostID(myHostID, &pError);
60405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (rc&0xff)==SQLITE_IOERR ){
60415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = pError;
60425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto end_takeconch;
60435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
60445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
60455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
60465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto end_takeconch;
60475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
60485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* read the existing conch file */
60495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
60505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( readLen<0 ){
60515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* I/O error: lastErrno set by seekAndRead */
60525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = conchFile->lastErrno;
60535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_READ;
60545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto end_takeconch;
60555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
60565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             readBuf[0]!=(char)PROXY_CONCHVERSION ){
60575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* a short read or version format mismatch means we need to create a new
60585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** conch file.
60595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
60605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      createConch = 1;
60615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
60625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* if the host id matches and the lock path already exists in the conch
60635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** we'll try to use the path there, if we can't open that path, we'll
60645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** retry with a new auto-generated path
60655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
60665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do { /* in case we need to try again for an :auto: named lock file */
60675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !createConch && !forceNewLockPath ){
60695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
60705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  PROXY_HOSTIDLEN);
60715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* if the conch has data compare the contents */
60725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( !pCtx->lockProxyPath ){
60735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* for auto-named local lock file, just check the host ID and we'll
60745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ** use the local lock file path that's already in there
60755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           */
60765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( hostIdMatch ){
60775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            size_t pathLen = (readLen - PROXY_PATHINDEX);
60785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if( pathLen>=MAXPATHLEN ){
60805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              pathLen=MAXPATHLEN-1;
60815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
60825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
60835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            lockPath[pathLen] = 0;
60845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tempLockPath = lockPath;
60855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tryOldLockPath = 1;
60865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* create a copy of the lock path if the conch is taken */
60875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto end_takeconch;
60885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
60895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else if( hostIdMatch
60905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               && !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
60915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           readLen-PROXY_PATHINDEX)
60925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ){
60935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* conch host and lock path match */
60945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto end_takeconch;
60955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
60965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
60975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* if the conch isn't writable and doesn't match, we can't take it */
60995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (conchFile->openFlags&O_RDWR) == 0 ){
61005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_BUSY;
61015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto end_takeconch;
61025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
61035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* either the conch didn't match or we need to create a new one */
61055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !pCtx->lockProxyPath ){
61065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
61075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tempLockPath = lockPath;
61085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* create a copy of the lock path _only_ if the conch is taken */
61095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
61105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* update conch with host and path (this will fail if other process
61125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** has a shared lock already), if the host id matches, use the big
61135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** stick.
61145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
61155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      futimes(conchFile->h, NULL);
61165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( hostIdMatch && !createConch ){
61175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( conchFile->pInode && conchFile->pInode->nShared>1 ){
61185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* We are trying for an exclusive lock but another thread in this
61195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ** same process is still holding a shared lock. */
61205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_BUSY;
61215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
61225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
61235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
61245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
61255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
61265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
61275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
61285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char writeBuffer[PROXY_MAXCONCHLEN];
61295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int writeSize = 0;
61305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        writeBuffer[0] = (char)PROXY_CONCHVERSION;
61325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
61335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pCtx->lockProxyPath!=NULL ){
61345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
61355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
61365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
61375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
61385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
61395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        robust_ftruncate(conchFile->h, writeSize);
61405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
61415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fsync(conchFile->h);
61425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* If we created a new conch file (not just updated the contents of a
61435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ** valid conch file), try to match the permissions of the database
61445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         */
61455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( rc==SQLITE_OK && createConch ){
61465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          struct stat buf;
61475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          int err = osFstat(pFile->h, &buf);
61485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( err==0 ){
61495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
61505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        S_IROTH|S_IWOTH);
61515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* try to match the database file R/W permissions, ignore failure */
61525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_PROXY_DEBUG
61535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            osFchmod(conchFile->h, cmode);
61545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
61555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            do{
61565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              rc = osFchmod(conchFile->h, cmode);
61575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }while( rc==(-1) && errno==EINTR );
61585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if( rc!=0 ){
61595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              int code = errno;
61605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              fprintf(stderr, "fchmod %o FAILED with %d %s\n",
61615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      cmode, code, strerror(code));
61625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            } else {
61635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
61645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
61655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }else{
61665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int code = errno;
61675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
61685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    err, code, strerror(code));
61695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
61705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
61715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
61725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
61735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
61745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    end_takeconch:
61765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
61775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK && pFile->openFlags ){
61785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pFile->h>=0 ){
61795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          robust_close(pFile, pFile->h, __LINE__);
61805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
61815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->h = -1;
61825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int fd = robust_open(pCtx->dbPath, pFile->openFlags,
61835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SQLITE_DEFAULT_FILE_PERMISSIONS);
61845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
61855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( fd>=0 ){
61865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pFile->h = fd;
61875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
61885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
61895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           during locking */
61905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
61915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
61925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK && !pCtx->lockProxy ){
61935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
61945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
61955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
61965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* we couldn't create the proxy lock file with the old lock file path
61975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ** so try again via auto-naming
61985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           */
61995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          forceNewLockPath = 1;
62005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tryOldLockPath = 0;
62015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue; /* go back to the do {} while start point, try again */
62025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
62035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
62045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
62055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Need to make a copy of path if we extracted the value
62065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ** from the conch file or the path was allocated on the stack
62075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         */
62085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( tempLockPath ){
62095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
62105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( !pCtx->lockProxyPath ){
62115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rc = SQLITE_NOMEM;
62125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
62135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
62145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
62155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
62165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pCtx->conchHeld = 1;
62175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pCtx->lockProxy->pMethod == &afpIoMethods ){
62195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          afpLockingContext *afpCtx;
62205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
62215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          afpCtx->dbPath = pCtx->lockProxyPath;
62225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
62235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
62245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
62255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
62265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("TAKECONCH  %d %s\n", conchFile->h,
62275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               rc==SQLITE_OK?"ok":"failed"));
62285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
62295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (1); /* in case we need to retry the :auto: lock file -
62305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 ** we should never get here except via the 'continue' call. */
62315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
62325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
62335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
62355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If pFile holds a lock on a conch file, then release that lock.
62365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
62375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyReleaseConch(unixFile *pFile){
62385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;         /* Subroutine return code */
62395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyLockingContext *pCtx;  /* The locking context for the proxy lock */
62405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *conchFile;        /* Name of the conch file */
62415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCtx = (proxyLockingContext *)pFile->lockingContext;
62435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  conchFile = pCtx->conchFile;
62445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("RELEASECONCH  %d for %s pid=%d\n", conchFile->h,
62455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
62465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           getpid()));
62475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCtx->conchHeld>0 ){
62485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
62495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
62505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCtx->conchHeld = 0;
62515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("RELEASECONCH  %d %s\n", conchFile->h,
62525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (rc==SQLITE_OK ? "ok" : "failed")));
62535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
62545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
62555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
62575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Given the name of a database file, compute the name of its conch file.
62585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Store the conch filename in memory obtained from sqlite3_malloc().
62595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Make *pConchPath point to the new name.  Return SQLITE_OK on success
62605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or SQLITE_NOMEM if unable to obtain memory.
62615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
62625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The caller is responsible for ensuring that the allocated memory
62635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** space is eventually freed.
62645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
62655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** *pConchPath is set to NULL if a memory allocation error occurs.
62665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
62675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
62685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;                        /* Loop counter */
62695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
62705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *conchPath;              /* buffer in which to construct conch name */
62715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Allocate space for the conch filename and initialize the name to
62735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the name of the original database file. */
62745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
62755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( conchPath==0 ){
62765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
62775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
62785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(conchPath, dbPath, len+1);
62795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* now insert a "." before the last / character */
62815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for( i=(len-1); i>=0; i-- ){
62825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( conchPath[i]=='/' ){
62835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i++;
62845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
62855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
62865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
62875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  conchPath[i]='.';
62885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while ( i<len ){
62895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    conchPath[i+1]=dbPath[i];
62905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i++;
62915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
62925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* append the "-conch" suffix to the file */
62945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&conchPath[i+1], "-conch", 7);
62955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (int)strlen(conchPath) == len+7 );
62965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
62975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
62985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
62995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Takes a fully configured proxy locking-style unix file and switches
63025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the local lock file path
63035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
63045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int switchLockProxyPath(unixFile *pFile, const char *path) {
63055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
63065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *oldPath = pCtx->lockProxyPath;
63075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
63085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock!=NO_LOCK ){
63105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_BUSY;
63115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
63125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* nothing to do if the path is NULL, :auto: or matches the existing path */
63145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
63155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
63165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
63175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
63185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *lockProxy = pCtx->lockProxy;
63195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCtx->lockProxy=NULL;
63205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCtx->conchHeld = 0;
63215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( lockProxy!=NULL ){
63225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
63235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc ) return rc;
63245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(lockProxy);
63255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
63265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(oldPath);
63275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
63285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
63295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
63315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
63325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
63345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pFile is a file that has been opened by a prior xOpen call.  dbPath
63355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is a string buffer at least MAXPATHLEN+1 characters in size.
63365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
63375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine find the filename associated with pFile and writes it
63385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** int dbPath.
63395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
63405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
63415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__APPLE__)
63425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->pMethod == &afpIoMethods ){
63435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* afp style keeps a reference to the db path in the filePath field
63445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** of the struct */
63455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
63465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
63475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else
63485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
63495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->pMethod == &dotlockIoMethods ){
63505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* dot lock style uses the locking context to store the dot lock
63515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** file path */
63525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
63535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
63545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
63555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* all other styles use the locking context to store the db file path */
63565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
63575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
63585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
63595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
63605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
63615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
63635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Takes an already filled in unix file and alters it so all file locking
63645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will be performed on the local proxy lock file.  The following fields
63655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are preserved in the locking context so that they can be restored and
63665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the unix structure properly cleaned up at close time:
63675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  ->lockingContext
63685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**  ->pMethod
63695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
63705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
63715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyLockingContext *pCtx;
63725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char dbPath[MAXPATHLEN+1];       /* Name of the database file */
63735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *lockPath=NULL;
63745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
63755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->eFileLock!=NO_LOCK ){
63775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_BUSY;
63785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
63795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxyGetDbPathForUnixFile(pFile, dbPath);
63805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
63815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lockPath=NULL;
63825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
63835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lockPath=(char *)path;
63845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
63855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TRANSPROXY  %d for %s pid=%d\n", pFile->h,
63875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (lockPath ? lockPath : ":auto:"), getpid()));
63885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pCtx = sqlite3_malloc( sizeof(*pCtx) );
63905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pCtx==0 ){
63915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
63925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
63935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pCtx, 0, sizeof(*pCtx));
63945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
63965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
63975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
63985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
63995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
64005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** (c) the file system is read-only, then enable no-locking access.
64015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
64025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** that openFlags will have only one of O_RDONLY or O_RDWR.
64035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
64045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct statfs fsInfo;
64055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct stat conchInfo;
64065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int goLockless = 0;
64075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
64095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int err = errno;
64105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
64115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
64125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
64135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
64145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( goLockless ){
64155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pCtx->conchHeld = -1; /* read only FS/ lockless */
64165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_OK;
64175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
64185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
64195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
64205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && lockPath ){
64215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
64225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
64235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
64255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
64265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pCtx->dbPath==NULL ){
64275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
64285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
64295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
64305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
64315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* all memory is allocated, proxys are created and assigned,
64325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** switch the locking context and pMethod then return.
64335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
64345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCtx->oldLockingContext = pFile->lockingContext;
64355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lockingContext = pCtx;
64365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pCtx->pOldMethod = pFile->pMethod;
64375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->pMethod = &proxyIoMethods;
64385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
64395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pCtx->conchFile ){
64405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
64415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(pCtx->conchFile);
64425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
64435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3DbFree(0, pCtx->lockProxyPath);
64445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pCtx->conchFilePath);
64455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pCtx);
64465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
64475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TRANSPROXY  %d %s\n", pFile->h,
64485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (rc==SQLITE_OK ? "ok" : "failed")));
64495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
64505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
64515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
64545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine handles sqlite3_file_control() calls that are specific
64555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to proxy locking.
64565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
64575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
64585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( op ){
64595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_GET_LOCKPROXYFILE: {
64605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unixFile *pFile = (unixFile*)id;
64615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pFile->pMethod == &proxyIoMethods ){
64625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
64635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxyTakeConch(pFile);
64645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pCtx->lockProxyPath ){
64655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *(const char **)pArg = pCtx->lockProxyPath;
64665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
64675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *(const char **)pArg = ":auto: (not held)";
64685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
64695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
64705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *(const char **)pArg = NULL;
64715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
64725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
64735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
64745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_SET_LOCKPROXYFILE: {
64755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unixFile *pFile = (unixFile*)id;
64765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int rc = SQLITE_OK;
64775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
64785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pArg==NULL || (const char *)pArg==0 ){
64795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( isProxyStyle ){
64805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* turn off proxy locking - not supported */
64815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
64825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
64835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* turn off proxy locking - already off - NOOP */
64845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_OK;
64855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
64865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
64875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const char *proxyPath = (const char *)pArg;
64885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( isProxyStyle ){
64895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          proxyLockingContext *pCtx =
64905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (proxyLockingContext*)pFile->lockingContext;
64915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( !strcmp(pArg, ":auto:")
64925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           || (pCtx->lockProxyPath &&
64935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
64945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ){
64955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rc = SQLITE_OK;
64965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }else{
64975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rc = switchLockProxyPath(pFile, proxyPath);
64985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
64995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }else{
65005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          /* turn on proxy file locking */
65015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = proxyTransformUnixFile(pFile, proxyPath);
65025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
65035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
65045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
65055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
65065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default: {
65075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( 0 );  /* The call assures that only valid opcodes are sent */
65085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
65095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
65105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*NOTREACHED*/
65115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_ERROR;
65125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
65135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
65155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Within this division (the proxying locking implementation) the procedures
65165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** above this point are all utilities.  The lock-related methods of the
65175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** proxy-locking sqlite3_io_method object follow.
65185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
65195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
65225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified
65235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, set *pResOut
65245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to a non-zero value otherwise *pResOut is set to zero.  The return value
65255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to SQLITE_OK unless an I/O error occurs during lock checking.
65265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
65275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
65285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
65295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = proxyTakeConch(pFile);
65305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
65315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
65325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pCtx->conchHeld>0 ){
65335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unixFile *proxy = pCtx->lockProxy;
65345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
65355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{ /* conchHeld < 0 is lockless */
65365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pResOut=0;
65375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
65385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
65395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
65405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
65415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
65435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter eFileLock - one
65445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following:
65455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
65465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (1) SHARED_LOCK
65475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (2) RESERVED_LOCK
65485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (3) PENDING_LOCK
65495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (4) EXCLUSIVE_LOCK
65505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
65515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states
65525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between.  The locking might fail on one of the later
65535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but
65545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal.  The following chart shows the allowed
65555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states:
65565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
65575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    UNLOCKED -> SHARED
65585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> RESERVED
65595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> (PENDING) -> EXCLUSIVE
65605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    RESERVED -> (PENDING) -> EXCLUSIVE
65615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    PENDING -> EXCLUSIVE
65625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
65635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock.  Use the sqlite3OsUnlock()
65645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** routine to lower a locking level.
65655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
65665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyLock(sqlite3_file *id, int eFileLock) {
65675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
65685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = proxyTakeConch(pFile);
65695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
65705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
65715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pCtx->conchHeld>0 ){
65725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unixFile *proxy = pCtx->lockProxy;
65735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
65745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->eFileLock = proxy->eFileLock;
65755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
65765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* conchHeld < 0 is lockless */
65775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
65785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
65795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
65805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
65815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
65845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
65855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
65865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
65875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
65885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
65895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
65905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyUnlock(sqlite3_file *id, int eFileLock) {
65915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unixFile *pFile = (unixFile*)id;
65925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = proxyTakeConch(pFile);
65935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
65945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
65955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pCtx->conchHeld>0 ){
65965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unixFile *proxy = pCtx->lockProxy;
65975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
65985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->eFileLock = proxy->eFileLock;
65995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
66005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* conchHeld < 0 is lockless */
66015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
66025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
66035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
66045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
66055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
66075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file that uses proxy locks.
66085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
66095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int proxyClose(sqlite3_file *id) {
66105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( id ){
66115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *pFile = (unixFile*)id;
66125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
66135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *lockProxy = pCtx->lockProxy;
66145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFile *conchFile = pCtx->conchFile;
66155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc = SQLITE_OK;
66165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( lockProxy ){
66185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
66195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc ) return rc;
66205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
66215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc ) return rc;
66225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(lockProxy);
66235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pCtx->lockProxy = 0;
66245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
66255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( conchFile ){
66265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pCtx->conchHeld ){
66275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = proxyReleaseConch(pFile);
66285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( rc ) return rc;
66295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
66305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
66315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc ) return rc;
66325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(conchFile);
66335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
66345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3DbFree(0, pCtx->lockProxyPath);
66355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pCtx->conchFilePath);
66365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3DbFree(0, pCtx->dbPath);
66375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* restore the original locking context and pMethod then close it */
66385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lockingContext = pCtx->oldLockingContext;
66395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->pMethod = pCtx->pOldMethod;
66405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pCtx);
66415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pFile->pMethod->xClose(id);
66425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
66435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
66445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
66455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
66495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
66505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The proxy locking style is intended for use with AFP filesystems.
66515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** And since AFP is only supported on MacOSX, the proxy locking is also
66525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** restricted to MacOSX.
66535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
66545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
66555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************* End of the proxy lock implementation **********************
66565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
66575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
66595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Initialize the operating system interface.
66605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
66615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine registers all VFS implementations for unix-like operating
66625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** systems.  This routine, and the sqlite3_os_end() routine that follows,
66635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** should be the only routines in this file that are visible from other
66645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** files.
66655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
66665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine is called once during SQLite initialization and by a
66675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** single thread.  The memory allocation and mutex subsystems have not
66685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** necessarily been initialized when this routine is called, and so they
66695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** should not be used.
66705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
66715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_init(void){
66725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
66735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** The following macro defines an initializer for an sqlite3_vfs object.
66745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** The name of the VFS is NAME.  The pAppData is a pointer to a pointer
66755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** to the "finder" function.  (pAppData is a pointer to a pointer because
66765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** silly C90 rules prohibit a void* from being cast to a function pointer
66775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** and so we have to go through the intermediate pointer to avoid problems
66785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** when compiling with -pedantic-errors on GCC.)
66795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
66805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** The FINDER parameter to this macro is the name of the pointer to the
66815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** finder-function.  The finder-function returns a pointer to the
66825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** sqlite_io_methods object that implements the desired locking
66835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** behaviors.  See the division above that contains the IOMETHODS
66845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** macro for addition information on finder-functions.
66855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
66865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Most finders simply return a pointer to a fixed sqlite3_io_methods
66875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** object.  But the "autolockIoFinder" available on MacOSX does a little
66885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** more than that; it looks at the filesystem type that hosts the
66895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** database file and tries to choose an locking method appropriate for
66905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** that filesystem time.
66915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
66925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define UNIXVFS(VFSNAME, FINDER) {                        \
66935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    3,                    /* iVersion */                    \
66945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(unixFile),     /* szOsFile */                    \
66955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MAX_PATHNAME,         /* mxPathname */                  \
66965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                    /* pNext */                       \
66975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VFSNAME,              /* zName */                       \
66985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void*)&FINDER,       /* pAppData */                    \
66995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixOpen,             /* xOpen */                       \
67005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixDelete,           /* xDelete */                     \
67015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixAccess,           /* xAccess */                     \
67025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixFullPathname,     /* xFullPathname */               \
67035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixDlOpen,           /* xDlOpen */                     \
67045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixDlError,          /* xDlError */                    \
67055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixDlSym,            /* xDlSym */                      \
67065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixDlClose,          /* xDlClose */                    \
67075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixRandomness,       /* xRandomness */                 \
67085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixSleep,            /* xSleep */                      \
67095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixCurrentTime,      /* xCurrentTime */                \
67105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixGetLastError,     /* xGetLastError */               \
67115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
67125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixSetSystemCall,    /* xSetSystemCall */              \
67135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixGetSystemCall,    /* xGetSystemCall */              \
67145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unixNextSystemCall,   /* xNextSystemCall */             \
67155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
67165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
67185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** All default VFSes for unix are contained in the following array.
67195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
67205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
67215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** by the SQLite core when the VFS is registered.  So the following
67225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** array cannot be const.
67235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
67245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static sqlite3_vfs aVfs[] = {
67255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
67265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix",          autolockIoFinder ),
67275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
67285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix",          posixIoFinder ),
67295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
67305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-none",     nolockIoFinder ),
67315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-dotfile",  dotlockIoFinder ),
67325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-excl",     posixIoFinder ),
67335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OS_VXWORKS
67345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-namedsem", semIoFinder ),
67355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
67365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE
67375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-posix",    posixIoFinder ),
67385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !OS_VXWORKS
67395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-flock",    flockIoFinder ),
67405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
67415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
67425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
67435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-afp",      afpIoFinder ),
67445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-nfs",      nfsIoFinder ),
67455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNIXVFS("unix-proxy",    proxyIoFinder ),
67465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
67475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
67485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int i;          /* Loop counter */
67495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Double-check that the aSyscall[] array has been constructed
67515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** correctly.  See ticket [bb3a86e890c8e96ab] */
67525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( ArraySize(aSyscall)==18 );
67535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Register all VFSes defined in the aVfs[] array */
67555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
67565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_vfs_register(&aVfs[i], i==0);
67575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
67585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
67595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
67605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
67625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Shutdown the operating system interface.
67635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
67645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Some operating systems might need to do some cleanup in this routine,
67655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to release dynamically allocated objects.  But not on unix.
67665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine is a no-op for unix.
67675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
67685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_end(void){
67695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
67705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
67715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_UNIX */
6773