Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Continue with the cleanup of os_unix.c. (CVS 5969) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
215d36ea89078036fb66b5154f054613 |
User & Date: | drh 2008-12-03 19:34:47.000 |
Context
2008-12-03
| ||
21:26 | Make os_unix compile with SQLITE_ENABLE_PROXY_LOCKING (CVS 5970) (check-in: 3efedac6aa user: aswift tags: trunk) | |
19:34 | Continue with the cleanup of os_unix.c. (CVS 5969) (check-in: 215d36ea89 user: drh tags: trunk) | |
2008-11-29
| ||
22:49 | Fully initialize the unused bytes of the buffer that will become the journal file header, in order to silence a complaint from valgrind. (CVS 5968) (check-in: 2822cbb960 user: drh tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
20 21 22 23 24 25 26 | ** skip locking all together. ** ** This source file is organized into divisions where the logic for various ** subfunctions is contained within the appropriate division. PLEASE ** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed ** in the correct division and should be clearly labeled. ** | | | | | > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | ** skip locking all together. ** ** This source file is organized into divisions where the logic for various ** subfunctions is contained within the appropriate division. PLEASE ** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed ** in the correct division and should be clearly labeled. ** ** The layout of divisions is as follows: ** ** * General-purpose declarations and utility functions. ** * Unique file ID logic used by VxWorks. ** * Various locking primitive implementations: ** + for Posix Advisory Locks ** + for no-op locks ** + for dot-file locks ** + for flock() locking ** + for named semaphore locks (VxWorks only) ** + for AFP filesystem locks (MacOSX only) ** + for proxy locks (MacOSX only) ** * sqlite3_file methods not associated with locking. ** * Definitions of sqlite3_io_methods objects for all locking ** methods plus "finder" functions for each locking method. ** * sqlite3_vfs method implementations. ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). ** ** $Id: os_unix.c,v 1.225 2008/12/03 19:34:47 drh Exp $ */ #include "sqliteInt.h" #if SQLITE_OS_UNIX /* This file is used on unix only */ /* ** There are various methods for file locking used for concurrency ** control: ** ** 1. POSIX locking (the default), ** 2. No locking, ** 3. Dot-file locking, ** 4. flock() locking, ** 5. AFP locking (OSX only), ** 6. Named POSIX semaphores (VXWorks only), |
︙ | ︙ | |||
1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | /****************** End of the dot-file lock implementation ******************* ******************************************************************************/ /****************************************************************************** ************************** Begin flock Locking ******************************** ** ** Use the flock() system call to do file locking. ** ** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if ** compiling for VXWORKS. */ #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS | > > > > > > > > > > > | < > | 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 | /****************** End of the dot-file lock implementation ******************* ******************************************************************************/ /****************************************************************************** ************************** Begin flock Locking ******************************** ** ** Use the flock() system call to do file locking. ** ** flock() locking is like dot-file locking in that the various ** fine-grain locking levels supported by SQLite are collapsed into ** a single exclusive lock. In other words, SHARED, RESERVED, and ** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite ** still works when you do this, but concurrency is reduced since ** only a single process can be reading the database at a time. ** ** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if ** compiling for VXWORKS. */ #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, set *pResOut ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){ int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 | reserved=1; } #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ *pResOut = reserved; return rc; } static int flockLock(sqlite3_file *id, int locktype) { int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( pFile ); /* if we already have a lock, it is exclusive. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 | reserved=1; } #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ *pResOut = reserved; return rc; } /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK ** (3) PENDING_LOCK ** (4) EXCLUSIVE_LOCK ** ** Sometimes when requesting one lock state, additional lock states ** are inserted in between. The locking might fail on one of the later ** transitions leaving the lock state different from what it started but ** still short of its goal. The following chart shows the allowed ** transitions and the inserted intermediate states: ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** flock() only really support EXCLUSIVE locks. We track intermediate ** lock states in the sqlite3_file structure, but all locks SHARED or ** above are really EXCLUSIVE locks and exclude all other processes from ** access the file. ** ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ static int flockLock(sqlite3_file *id, int locktype) { int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( pFile ); /* if we already have a lock, it is exclusive. |
︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ rc = SQLITE_BUSY; } #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ return rc; } static int flockUnlock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; assert( pFile ); OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, pFile->locktype, getpid()); assert( locktype<=SHARED_LOCK ); | > > > > > > > > | 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 | if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){ rc = SQLITE_BUSY; } #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */ return rc; } /* ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int flockUnlock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; assert( pFile ); OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, pFile->locktype, getpid()); assert( locktype<=SHARED_LOCK ); |
︙ | ︙ | |||
1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 | /******************* End of the flock lock implementation ********************* ******************************************************************************/ /****************************************************************************** ************************ Begin Named Semaphore Locking ************************ ** ** Named semaphore locking is only supported on VxWorks. */ #if OS_VXWORKS | > > > > > > > > > | < > | 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 | /******************* End of the flock lock implementation ********************* ******************************************************************************/ /****************************************************************************** ************************ Begin Named Semaphore Locking ************************ ** ** Named semaphore locking is only supported on VxWorks. ** ** Semaphore locking is like dot-lock and flock in that it really only ** supports EXCLUSIVE locking. Only a single process can read or write ** the database file at a time. This reduces potential concurrency, but ** makes the lock implementation much easier. */ #if OS_VXWORKS /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, set *pResOut ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) { int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
︙ | ︙ | |||
1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 | } OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); *pResOut = reserved; return rc; } static int semLock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; int fd; sem_t *pSem = pFile->pOpen->pSem; int rc = SQLITE_OK; /* if we already have a lock, it is exclusive. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 | } OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); *pResOut = reserved; return rc; } /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK ** (3) PENDING_LOCK ** (4) EXCLUSIVE_LOCK ** ** Sometimes when requesting one lock state, additional lock states ** are inserted in between. The locking might fail on one of the later ** transitions leaving the lock state different from what it started but ** still short of its goal. The following chart shows the allowed ** transitions and the inserted intermediate states: ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** Semaphore locks only really support EXCLUSIVE locks. We track intermediate ** lock states in the sqlite3_file structure, but all locks SHARED or ** above are really EXCLUSIVE locks and exclude all other processes from ** access the file. ** ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ static int semLock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; int fd; sem_t *pSem = pFile->pOpen->pSem; int rc = SQLITE_OK; /* if we already have a lock, it is exclusive. |
︙ | ︙ | |||
2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 | /* got it, set the type and return ok */ pFile->locktype = locktype; sem_end_lock: return rc; } static int semUnlock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pOpen->pSem; assert( pFile ); assert( pSem ); OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, | > > > > > > > | 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 | /* got it, set the type and return ok */ pFile->locktype = locktype; sem_end_lock: return rc; } /* ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int semUnlock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; sem_t *pSem = pFile->pOpen->pSem; assert( pFile ); assert( pSem ); OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, |
︙ | ︙ | |||
2089 2090 2091 2092 2093 2094 2095 | #if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE /* ** The afpLockingContext structure contains all afp lock specific state */ typedef struct afpLockingContext afpLockingContext; struct afpLockingContext { unsigned long long sharedByte; | | | > > > | | | | | | | | | | | 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 | #if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE /* ** The afpLockingContext structure contains all afp lock specific state */ typedef struct afpLockingContext afpLockingContext; struct afpLockingContext { unsigned long long sharedByte; const char *dbPath; /* Name of the open file */ }; struct ByteRangeLockPB2 { unsigned long long offset; /* offset to first byte to lock */ unsigned long long length; /* nbr of bytes to lock */ unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */ unsigned char unLockFlag; /* 1 = unlock, 0 = lock */ unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */ int fd; /* file desc to assoc this lock with */ }; #define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2) /* ** This is a utility for setting or clearing a bit-range lock on an ** AFP filesystem. ** ** Return SQLITE_OK on success, SQLITE_BUSY on failure. */ static int afpSetLock( const char *path, /* Name of the file to be locked or unlocked */ unixFile *pFile, /* Open file descriptor on path */ unsigned long long offset, /* First byte to be locked */ unsigned long long length, /* Number of bytes to lock */ int setLockFlag /* True to set lock. False to clear lock */ ){ struct ByteRangeLockPB2 pb; int err; pb.unLockFlag = setLockFlag ? 0 : 1; pb.startEndFlag = 0; pb.offset = offset; pb.length = length; pb.fd = pFile->h; //SimulateIOErrorBenign(1); |
︙ | ︙ | |||
2150 2151 2152 2153 2154 2155 2156 | } return rc; } else { return SQLITE_OK; } } | > > > > | < > | | | > | > > > > > > > > > > > > > > > > > > > > > | 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 | } return rc; } else { return SQLITE_OK; } } /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, set *pResOut ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){ int rc = SQLITE_OK; int reserved = 0; unixFile *pFile = (unixFile*)id; SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); assert( pFile ); afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; /* Check if a thread in this process holds such a lock */ if( pFile->locktype>SHARED_LOCK ){ reserved = 1; } /* Otherwise see if some other process holds it. */ if( !reserved ){ /* lock the RESERVED byte */ int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); if( SQLITE_OK==lrc ){ /* if we succeeded in taking the reserved lock, unlock it to restore ** the original state */ lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); } else { /* if we failed to get the lock then someone else must have it */ reserved = 1; } if( IS_LOCK_ERROR(lrc) ){ rc=lrc; } } OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved); *pResOut = reserved; return rc; } /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK ** (3) PENDING_LOCK ** (4) EXCLUSIVE_LOCK ** ** Sometimes when requesting one lock state, additional lock states ** are inserted in between. The locking might fail on one of the later ** transitions leaving the lock state different from what it started but ** still short of its goal. The following chart shows the allowed ** transitions and the inserted intermediate states: ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ static int afpLock(sqlite3_file *id, int locktype){ int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; assert( pFile ); OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, |
︙ | ︙ | |||
2238 2239 2240 2241 2242 2243 2244 | ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will ** be released. */ if( locktype==SHARED_LOCK || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK) ){ int failed; | | | | | 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 | ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will ** be released. */ if( locktype==SHARED_LOCK || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK) ){ int failed; failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1); if (failed) { rc = failed; goto afp_end_lock; } } /* If control gets to this point, then actually go ahead and make ** operating system calls for the specified lock. */ if( locktype==SHARED_LOCK ){ int lk, lrc1, lrc2, lrc1Errno; /* Now get the read-lock SHARED_LOCK */ /* note that the quality of the randomness doesn't matter that much */ lk = random(); context->sharedByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); lrc1 = afpSetLock(context->dbPath, pFile, SHARED_FIRST+context->sharedByte, 1, 1); if( IS_LOCK_ERROR(lrc1) ){ lrc1Errno = pFile->lastErrno; } /* Drop the temporary PENDING lock */ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); if( IS_LOCK_ERROR(lrc1) ) { pFile->lastErrno = lrc1Errno; rc = lrc1; goto afp_end_lock; } else if( IS_LOCK_ERROR(lrc2) ){ rc = lrc2; |
︙ | ︙ | |||
2285 2286 2287 2288 2289 2290 2291 | ** assumed that there is a SHARED or greater lock on the file ** already. */ int failed = 0; assert( 0!=pFile->locktype ); if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { /* Acquire a RESERVED lock */ | | | | | | 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 | ** assumed that there is a SHARED or greater lock on the file ** already. */ int failed = 0; assert( 0!=pFile->locktype ); if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { /* Acquire a RESERVED lock */ failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1); } if (!failed && locktype == EXCLUSIVE_LOCK) { /* Acquire an EXCLUSIVE lock */ /* Remove the shared lock before trying the range. we'll need to ** reestablish the shared lock if we can't get the afpUnlock */ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + context->sharedByte, 1, 0)) ){ int failed2 = SQLITE_OK; /* now attemmpt to get the exclusive lock range */ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 1); if( failed && (failed2 = afpSetLock(context->dbPath, pFile, SHARED_FIRST + context->sharedByte, 1, 1)) ){ /* Can't reestablish the shared lock. Sqlite can't deal, this is ** a critical I/O error */ rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : SQLITE_IOERR_LOCK; goto afp_end_lock; |
︙ | ︙ | |||
2357 2358 2359 2360 2361 2362 2363 | if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } unixEnterMutex(); if( pFile->locktype>SHARED_LOCK ){ if( pFile->locktype==EXCLUSIVE_LOCK ){ | | | | | | | 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 | if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } unixEnterMutex(); if( pFile->locktype>SHARED_LOCK ){ if( pFile->locktype==EXCLUSIVE_LOCK ){ rc = afpSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); if( rc==SQLITE_OK && locktype==SHARED_LOCK ){ /* only re-establish the shared lock if necessary */ int sharedLockByte = SHARED_FIRST+pCtx->sharedByte; rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 1); } } if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){ rc = afpSetLock(pCtx->dbPath, pFile, PENDING_BYTE, 1, 0); } if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK ){ rc = afpSetLock(pCtx->dbPath, pFile, RESERVED_BYTE, 1, 0); } }else if( locktype==NO_LOCK ){ /* clear the shared lock */ int sharedLockByte = SHARED_FIRST+pCtx->sharedByte; rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0); } if( rc==SQLITE_OK ){ if( locktype==NO_LOCK ){ struct unixOpenCnt *pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); |
︙ | ︙ | |||
2604 2605 2606 2607 2608 2609 2610 | */ /* ** Proxy locking is only available on MacOSX */ #if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE | | | | < | > | | | > > > > | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 | */ /* ** Proxy locking is only available on MacOSX */ #if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE /* ** Forward reference */ static int fillInUnixFile( sqlite3_vfs *pVfs, int h, int dirfd, sqlite3_file *pId, const char *zFilename, int noLock, int isDelete ); #ifdef SQLITE_TEST /* simulate multiple hosts by creating unique hostid file paths */ int sqlite3_hostid_num = 0; #endif /* ** The proxyLockingContext has the path and file structures for the remote ** and local proxy files in it */ typedef struct proxyLockingContext proxyLockingContext; struct proxyLockingContext { unixFile *conchFile; /* Open conch file */ char *conchFilePath; /* Name of the conch file */ unixFile *lockProxy; /* Open proxy lock file */ char *lockProxyPath; /* Name of the proxy lock file */ char *dbPath; /* Name of the open file */ int conchHeld; /* True if the conch is currently held */ void *oldLockingContext; /* Original lockingcontext to restore on close */ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */ }; /* HOSTIDLEN and CONCHLEN both include space for the string ** terminating nul */ #define HOSTIDLEN 128 #define CONCHLEN (MAXPATHLEN+HOSTIDLEN+1) #ifndef HOSTIDPATH # define HOSTIDPATH "/Library/Caches/.com.apple.sqliteConchHostId" #endif /* basically a copy of unixRandomness with different ** test behavior built in */ static int proxyGenerateHostID(char *pHostID){ int pid, fd, i, len; unsigned char *key = (unsigned char *)pHostID; memset(key, 0, HOSTIDLEN); len = 0; fd = open("/dev/urandom", O_RDONLY); if( fd>=0 ){ |
︙ | ︙ | |||
2756 2757 2758 2759 2760 2761 2762 | } } #endif return SQLITE_OK; } /* writes the host id path to path, path should be an pre-allocated buffer | | > | | | | | 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 | } } #endif return SQLITE_OK; } /* writes the host id path to path, path should be an pre-allocated buffer ** with enough space for a path */ static int proxyGetHostIDPath(char *path, size_t len){ strlcpy(path, HOSTIDPATH, len); #ifdef SQLITE_TEST if( sqlite3_hostid_num>0 ){ char suffix[2] = "1"; suffix[0] = suffix[0] + sqlite3_hostid_num; strlcat(path, suffix, len); } #endif OSTRACE3("GETHOSTIDPATH %s pid=%d\n", path, getpid()); } /* get the host ID from a sqlite hostid file stored in the ** user-specific tmp directory, create the ID if it's not there already */ static int proxyGetHostID(char *pHostID, int *pError){ int fd; char path[MAXPATHLEN]; size_t len; int rc=SQLITE_OK; proxyGetHostIDPath(path, MAXPATHLEN); /* try to create the host ID file, if it already exists read the contents */ fd = open(path, O_CREAT|O_WRONLY|O_EXCL, 0644); if( fd<0 ){ int err=errno; if( err!=EEXIST ){ #ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */ |
︙ | ︙ | |||
2815 2816 2817 2818 2819 2820 2821 | } close(fd); /* silently leak the fd if it fails */ OSTRACE3("GETHOSTID read %s pid=%d\n", pHostID, getpid()); return rc; }else{ int i; /* we're creating the host ID file (use a random string of bytes) */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 | } close(fd); /* silently leak the fd if it fails */ OSTRACE3("GETHOSTID read %s pid=%d\n", pHostID, getpid()); return rc; }else{ int i; /* we're creating the host ID file (use a random string of bytes) */ proxyGenerateHostID(pHostID); len = pwrite(fd, pHostID, HOSTIDLEN, 0); if( len<0 ){ *pError = errno; rc = SQLITE_IOERR_WRITE; }else if( len<HOSTIDLEN ){ *pError = 0; rc = SQLITE_IOERR_WRITE; } close(fd); /* silently leak the fd if it fails */ OSTRACE3("GETHOSTID wrote %s pid=%d\n", pHostID, getpid()); return rc; } } static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){ int len; int dbLen; int i; #ifdef LOCKPROXYDIR len = strlcpy(lPath, LOCKPROXYDIR, maxLen); #else # ifdef _CS_DARWIN_USER_TEMP_DIR { char utdir[MAXPATHLEN]; confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen); len = strlcat(lPath, "sqliteplocks", maxLen); if( mkdir(lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){ /* if mkdir fails, handle as lock file creation failure */ int err = errno; # ifdef SQLITE_DEBUG if( err!=EEXIST ){ fprintf(stderr, "proxyGetLockPath: mkdir(%s,0%o) error %d %s\n", lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS, err, strerror(err)); } # endif }else{ OSTRACE3("GETLOCKPATH mkdir %s pid=%d\n", lPath, getpid()); } } # else len = strlcpy(lPath, "/tmp/", maxLen); # endif #endif if( lPath[len-1]!='/' ){ len = strlcat(lPath, "/", maxLen); } /* transform the db path to a unique cache name */ dbLen = strlen(dbPath); for( i=0; i<dbLen && (i+len+7)<maxLen; i++){ char c = dbPath[i]; lPath[i+len] = (c=='/')?'_':c; } lPath[i+len]='\0'; strlcat(lPath, ":auto:", maxLen); return SQLITE_OK; } /* ** Create a new VFS file descriptor (stored in memory obtained from ** sqlite3_malloc) and open the file named "path" in the file descriptor. ** ** The caller is responsible not only for closing the file descriptor ** but also for freeing the memory associated with the file descriptor. */ static int proxyCreateUnixFile(const char *path, unixFile **ppFile) { int fd; int dirfd = -1; unixFile *pNew; int rc = SQLITE_OK; fd = open(path, O_RDWR | O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS); if( fd<0 ){ return SQLITE_CANTOPEN; } pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile)); if( pNew==NULL ){ rc = SQLITE_NOMEM; goto end_create_proxy; } memset(pNew, 0, sizeof(unixFile)); rc = fillInUnixFile(NULL, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0); if( rc==SQLITE_OK ){ *ppFile = pNew; return SQLITE_OK; } end_create_proxy: close(fd); /* silently leak fd if error, we're already in error */ sqlite3_free(pNew); return rc; } /* takes the conch by taking a shared lock and read the contents conch, if ** lockPath is non-NULL, the host ID and lock file path must match. A NULL ** lockPath means that the lockPath in the conch file will be used if the ** host IDs match, or a new lock path will be generated automatically ** and written to the conch file. */ static int proxyTakeConch(unixFile *pFile){ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; if( pCtx->conchHeld>0 ){ return SQLITE_OK; }else{ unixFile *conchFile = pCtx->conchFile; char testValue[CONCHLEN]; char conchValue[CONCHLEN]; char lockPath[MAXPATHLEN]; char *tLockPath = NULL; int rc = SQLITE_OK; int readRc = SQLITE_OK; int syncPerms = 0; OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h, (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()); rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK); if( rc==SQLITE_OK ){ int pError = 0; memset(testValue, 0, CONCHLEN); // conch is fixed size rc = proxyGetHostID(testValue, &pError); if( rc&SQLITE_IOERR==SQLITE_IOERR ){ pFile->lastErrno = pError; } if( pCtx->lockProxyPath ){ strlcpy(&testValue[HOSTIDLEN], pCtx->lockProxyPath, MAXPATHLEN); } } if( rc!=SQLITE_OK ){ goto end_takeconch; } |
︙ | ︙ | |||
2904 2905 2906 2907 2908 2909 2910 | ** we'll try to match the current on-disk permissions of the database */ syncPerms = 1; } /* either conch was emtpy or didn't match */ if( !pCtx->lockProxyPath ){ | | | 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 | ** we'll try to match the current on-disk permissions of the database */ syncPerms = 1; } /* either conch was emtpy or didn't match */ if( !pCtx->lockProxyPath ){ proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN); tLockPath = lockPath; strlcpy(&testValue[HOSTIDLEN], lockPath, MAXPATHLEN); } /* update conch with host and path (this will fail if other process ** has a shared lock already) */ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK); |
︙ | ︙ | |||
2960 2961 2962 2963 2964 2965 2966 | pFile->h = -1; int fd = open(pCtx->dbPath, pFile->openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); OSTRACE2("TRANSPROXY: OPEN %d\n", fd); if( fd>=0 ){ pFile->h = fd; }else{ | | | | > > > | > | < | > > > > > > > > > > > > > | | | | | > > | | < < < < | | | < < < < | < < < < | < < < < < < < | < < < | < < < | < < < < < < < < < < < < < < < < < < < < < | 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 | pFile->h = -1; int fd = open(pCtx->dbPath, pFile->openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); OSTRACE2("TRANSPROXY: OPEN %d\n", fd); if( fd>=0 ){ pFile->h = fd; }else{ rc=SQLITE_CANTOPEN; // SQLITE_BUSY? proxyTakeConch called during locking } } if( rc==SQLITE_OK && !pCtx->lockProxy ){ char *path = tLockPath ? tLockPath : pCtx->lockProxyPath; // ACS: Need to make a copy of path sometimes rc = proxyCreateUnixFile(path, &pCtx->lockProxy); } if( rc==SQLITE_OK ){ pCtx->conchHeld = 1; if( tLockPath ){ pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath); if( pCtx->lockProxy->pMethod == &afpIoMethods ){ ((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath = pCtx->lockProxyPath; } } } else { conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); } OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed"); return rc; } } /* ** If pFile holds a lock on a conch file, then release that lock. */ static int proxyReleaseConch(unixFile *pFile){ int rc; /* Subroutine return code */ proxyLockingContext *pCtx; /* The locking context for the proxy lock */ unixFile *conchFile; /* Name of the conch file */ pCtx = (proxyLockingContext *)pFile->lockingContext; conchFile = pCtx->conchFile; OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h, (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()); pCtx->conchHeld = 0; rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK); OSTRACE3("RELEASECONCH %d %s\n", conchFile->h, (rc==SQLITE_OK ? "ok" : "failed")); return rc; } /* ** Given the name of a database file, compute the name of its conch file. ** Store the conch filename in memory obtained from sqlite3_malloc(). ** Make *pConchPath point to the new name. Return SQLITE_OK on success ** or SQLITE_NOMEM if unable to obtain memory. ** ** The caller is responsible for ensuring that the allocated memory ** space is eventually freed. ** ** *pConchPath is set to NULL if a memory allocation error occurs. */ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){ int i; /* Loop counter */ int len = strlen(dbPath); /* Length of database filename - dbPath */ char *conchPath; /* buffer in which to construct conch name */ /* Allocate space for the conch filename and initialize the name to ** the name of the original database file. */ *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8); if( conchPath==0 ){ return SQLITE_NOMEM; } memcpy(conchPath, dbPath, len+1); /* now insert a "." before the last / character */ for( i=(len-1); i>=0; i-- ){ if( conchPath[i]=='/' ){ i++; break; } } conchPath[i]='.'; while ( i<len ){ conchPath[i+1]=dbPath[i]; i++; } /* append the "-conch" suffix to the file */ memcpy(&conchPath[i+1], "-conch", 7); assert( strlen(conchPath) == len+7 ); return SQLITE_OK; } /* Takes a fully configured proxy locking-style unix file and switches ** the local lock file path */ static int switchLockProxyPath(unixFile *pFile, const char *path) { proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; char *oldPath = pCtx->lockProxyPath; |
︙ | ︙ | |||
3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 | } sqlite3_free(oldPath); pCtx->lockProxyPath = sqlite3DbStrDup(0, path); } return rc; } /* ** Takes an already filled in unix file and alters it so all file locking ** will be performed on the local proxy lock file. The following fields ** are preserved in the locking context so that they can be restored and ** the unix structure properly cleaned up at close time: ** ->lockingContext ** ->pMethod */ static int transformUnixFileForLockProxy(unixFile *pFile, const char *path) { proxyLockingContext *pCtx; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 | } sqlite3_free(oldPath); pCtx->lockProxyPath = sqlite3DbStrDup(0, path); } return rc; } /* ** pFile is a file that has been opened by a prior xOpen call. dbPath ** is a string buffer at least MAXPATHLEN+1 characters in size. ** ** This routine find the filename associated with pFile and writes it ** int dbPath. */ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){ #if defined(__DARWIN__) if( pFile->pMethod == &afpIoMethods ){ /* afp style keeps a reference to the db path in the filePath field ** of the struct */ assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath) }else #endif if( pFile->pMethod == &dotlockIoMethods ){ /* dot lock style uses the locking context to store the dot lock ** file path */ int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX); memcpy(dbPath, (char *)pFile->lockingContext, len + 1); }else{ /* all other styles use the locking context to store the db file path */ assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN ); strcpy(dbPath, (char *)pFile->lockingContext); } return SQLITE_OK; } /* ** Takes an already filled in unix file and alters it so all file locking ** will be performed on the local proxy lock file. The following fields ** are preserved in the locking context so that they can be restored and ** the unix structure properly cleaned up at close time: ** ->lockingContext ** ->pMethod */ static int transformUnixFileForLockProxy(unixFile *pFile, const char *path) { proxyLockingContext *pCtx; char dbPath[MAXPATHLEN+1]; /* Name of the database file */ char *lockPath=NULL; int rc = SQLITE_OK; if( pFile->locktype!=NO_LOCK ){ return SQLITE_BUSY; } proxyGetDbPathForUnixFile(pFile, dbPath); if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){ lockPath=NULL; }else{ lockPath=(char *)path; } OSTRACE4("TRANSPROXY %d for %s pid=%d\n", pFile->h, (lockPath ? lockPath : ":auto:"), getpid()); pCtx = sqlite3_malloc( sizeof(*pCtx) ); if( pCtx==0 ){ return SQLITE_NOMEM; } memset(pCtx, 0, sizeof(*pCtx)); rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath); if( rc==SQLITE_OK ){ rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile); } if( rc==SQLITE_OK && lockPath ){ pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath); } end_transform_file: if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
3175 3176 3177 3178 3179 3180 3181 | } sqlite3_free(pCtx->conchFilePath); sqlite3_free(pCtx); } OSTRACE3("TRANSPROXY %d %s\n", pFile->h, (rc==SQLITE_OK ? "ok" : "failed")); return rc; | | > > > > > | | > > > > > > | | > | > > > | < < | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < | < | | | > > > > > > > | > > > | > > > | | | > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > | > > > > > > | > | 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 | } sqlite3_free(pCtx->conchFilePath); sqlite3_free(pCtx); } OSTRACE3("TRANSPROXY %d %s\n", pFile->h, (rc==SQLITE_OK ? "ok" : "failed")); return rc; } /* ** Within this division (the proxying locking implementation) the procedures ** above this point are all utilities. The lock-related methods of the ** proxy-locking sqlite3_io_method object follow. */ /* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, set *pResOut ** to a non-zero value otherwise *pResOut is set to zero. The return value ** is set to SQLITE_OK unless an I/O error occurs during lock checking. */ static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) { unixFile *pFile = (unixFile*)id; int rc = proxyTakeConch(pFile); if( rc==SQLITE_OK ){ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *proxy = pCtx->lockProxy; return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut); } return rc; } /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: ** ** (1) SHARED_LOCK ** (2) RESERVED_LOCK ** (3) PENDING_LOCK ** (4) EXCLUSIVE_LOCK ** ** Sometimes when requesting one lock state, additional lock states ** are inserted in between. The locking might fail on one of the later ** transitions leaving the lock state different from what it started but ** still short of its goal. The following chart shows the allowed ** transitions and the inserted intermediate states: ** ** UNLOCKED -> SHARED ** SHARED -> RESERVED ** SHARED -> (PENDING) -> EXCLUSIVE ** RESERVED -> (PENDING) -> EXCLUSIVE ** PENDING -> EXCLUSIVE ** ** This routine will only increase a lock. Use the sqlite3OsUnlock() ** routine to lower a locking level. */ static int proxyLock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; int rc = proxyTakeConch(pFile); if( rc==SQLITE_OK ){ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *proxy = pCtx->lockProxy; rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype); pFile->locktype = proxy->locktype; } return rc; } /* ** Lower the locking level on file descriptor pFile to locktype. locktype ** must be either NO_LOCK or SHARED_LOCK. ** ** If the locking level of the file descriptor is already at or below ** the requested locking level, this routine is a no-op. */ static int proxyUnlock(sqlite3_file *id, int locktype) { unixFile *pFile = (unixFile*)id; int rc = proxyTakeConch(pFile); if( rc==SQLITE_OK ){ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *proxy = pCtx->lockProxy; rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype); pFile->locktype = proxy->locktype; } return rc; } /* ** Close a file that uses proxy locks. */ static int proxyClose(sqlite3_file *id) { if( id ){ unixFile *pFile = (unixFile*)id; proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext; unixFile *lockProxy = pCtx->lockProxy; unixFile *conchFile = pCtx->conchFile; int rc = SQLITE_OK; if( lockProxy ){ rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK); if( rc ) return rc; rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy); if( rc ) return rc; sqlite3_free(lockProxy); pCtx->lockProxy = 0; } if( conchFile ){ if( pCtx->conchHeld ){ rc = proxyReleaseConch(pFile); if( rc ) return rc; } rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile); if( rc ) return rc; sqlite3_free(conchFile); } sqlite3_free(pCtx->lockProxyPath); sqlite3_free(pCtx->conchFilePath); sqlite3_free(pCtx->dbPath); /* restore the original locking context and pMethod then close it */ pFile->lockingContext = pCtx->oldLockingContext; pFile->pMethod = pCtx->pOldMethod; sqlite3_free(pCtx); return pFile->pMethod->xClose(id); } return SQLITE_OK; } #endif /* defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE */ /* ** The proxy locking style is intended for use with AFP filesystems. ** And since AFP is only supported on MacOSX, the proxy locking is also ** restricted to MacOSX. |
︙ | ︙ | |||
3371 3372 3373 3374 3375 3376 3377 | } return SQLITE_OK; } #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test | | | 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 | } return SQLITE_OK; } #ifdef SQLITE_TEST /* ** Count the number of fullsyncs and normal syncs. This is used to test ** that syncs and fullsyncs are occurring at the right times. */ int sqlite3_sync_count = 0; int sqlite3_fullsync_count = 0; #endif /* ** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined. |
︙ | ︙ | |||
3446 3447 3448 3449 3450 3451 3452 | #elif HAVE_FULLFSYNC if( fullSync ){ rc = fcntl(fd, F_FULLFSYNC, 0); }else{ rc = 1; } /* If the FULLFSYNC failed, fall back to attempting an fsync(). | | | | | | | | | 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 | #elif HAVE_FULLFSYNC if( fullSync ){ rc = fcntl(fd, F_FULLFSYNC, 0); }else{ rc = 1; } /* If the FULLFSYNC failed, fall back to attempting an fsync(). ** It shouldn't be possible for fullfsync to fail on the local ** file system (on OSX), so failure indicates that FULLFSYNC ** isn't supported for this file system. So, attempt an fsync ** and (for now) ignore the overhead of a superfluous fcntl call. ** It'd be better to detect fullfsync support once and avoid ** the fcntl call every time sync is called. */ if( rc ) rc = fsync(fd); #else if( dataOnly ){ rc = fdatasync(fd); if( OS_VXWORKS && rc==-1 && errno==ENOTSUP ){ rc = fsync(fd); |
︙ | ︙ | |||
3605 3606 3607 3608 3609 3610 3611 | return SQLITE_OK; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) case SQLITE_GET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; if( pFile->pMethod == &proxyIoMethods ){ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; | | | 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 | return SQLITE_OK; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) case SQLITE_GET_LOCKPROXYFILE: { unixFile *pFile = (unixFile*)id; if( pFile->pMethod == &proxyIoMethods ){ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext; proxyTakeConch(pFile); if( pCtx->lockProxyPath ){ *(const char **)pArg = pCtx->lockProxyPath; }else{ *(const char **)pArg = ":auto: (not held)"; } } else { *(const char **)pArg = NULL; |
︙ | ︙ | |||
3648 3649 3650 3651 3652 3653 3654 | }else{ /* turn on proxy file locking */ rc = transformUnixFileForLockProxy(pFile, proxyPath); } } return rc; } | | | 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 | }else{ /* turn on proxy file locking */ rc = transformUnixFileForLockProxy(pFile, proxyPath); } } return rc; } #endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) */ } return SQLITE_ERROR; } /* ** Return the sector size in bytes of the underlying block device for ** the specified file. This is almost always 512 bytes, but may be |
︙ | ︙ | |||
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 | /* ** Here ends the implementation of all sqlite3_file methods. ** ********************** End sqlite3_file Methods ******************************* ******************************************************************************/ /* ** Each instance of this macro generates two objects: ** ** * A constant sqlite3_io_methods object call METHOD that has locking ** methods CLOSE, LOCK, UNLOCK, CKRESLOCK. ** ** * An I/O method finder function called FINDER that returns a pointer ** to the METHOD object in the previous bullet. | > > > > > > > > > > > > > | 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 | /* ** Here ends the implementation of all sqlite3_file methods. ** ********************** End sqlite3_file Methods ******************************* ******************************************************************************/ /* ** This division contains definitions of sqlite3_io_methods objects that ** implement various file locking strategies. It also contains definitions ** of "finder" functions. A finder-function is used to locate the appropriate ** sqlite3_io_methods object for a particular database file. The pAppData ** field of the sqlite3_vfs VFS objects are initialized to be pointers to ** the correct finder-function for that VFS. ** ** Most finder functions return a pointer to a fixed sqlite3_io_methods ** object. The only interesting finder-function is autolockIoFinder, which ** looks at the filesystem type and tries to guess the best locking ** strategy from that. ** ** ** Each instance of this macro generates two objects: ** ** * A constant sqlite3_io_methods object call METHOD that has locking ** methods CLOSE, LOCK, UNLOCK, CKRESLOCK. ** ** * An I/O method finder function called FINDER that returns a pointer ** to the METHOD object in the previous bullet. |
︙ | ︙ | |||
3786 3787 3788 3789 3790 3791 3792 | proxyCheckReservedLock /* xCheckReservedLock method */ ); #endif #if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE /* | | | | | > > | 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 | proxyCheckReservedLock /* xCheckReservedLock method */ ); #endif #if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE /* ** This "finder" function attempts to determine the best locking strategy ** for the database file "filePath". It then returns the sqlite3_io_methods ** object that implements that strategy. ** ** This is for MacOSX only. */ static const sqlite3_io_methods *autolockIoFinder( const char *filePath, /* name of the database file */ int fd /* file descriptor open on the database file */ ){ static const struct Mapping { const char *zFilesystem; /* Filesystem type name */ const sqlite3_io_methods *pMethods; /* Appropriate locking method */ } aMap[] = { { "hfs", &posixIoMethods }, { "ufs", &posixIoMethods }, { "afpfs", &afpIoMethods }, #ifdef SQLITE_ENABLE_AFP_LOCKING_SMB { "smbfs", &afpIoMethods }, #else { "smbfs", &flockIoMethods }, #endif { "webdav", &nolockIoMethods }, { 0, 0 } }; int i; struct statfs fsInfo; struct flock lockInfo; if( !filePath ){ /* If filePath==NULL that means we are dealing with a transient file ** that does not need to be locked. */ return &nolockIoMethods; } if( statfs(filePath, &fsInfo) != -1 ){ if( fsInfo.f_flags & MNT_RDONLY ){ return &nolockIoMethods; } for(i=0; aMap[i].zFilesystem; i++){ |
︙ | ︙ | |||
4004 4005 4006 4007 4008 4009 4010 | }else{ pNew->pMethod = pLockingStyle; OpenCounter(+1); } return rc; } | < < < < < < < < < < < < < < < < < < < < < < < < | 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 | }else{ pNew->pMethod = pLockingStyle; OpenCounter(+1); } return rc; } /* ** Open a file descriptor to the directory containing file zFilename. ** If successful, *pFd is set to the opened file descriptor and ** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM ** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined ** value. ** |
︙ | ︙ | |||
4144 4145 4146 4147 4148 4149 4150 | ** The old OpenExclusive() accepted a boolean argument - "delFlag". If ** true, the file was configured to be automatically deleted when the ** file handle closed. To achieve the same effect using this new ** interface, add the DELETEONCLOSE flag to those specified above for ** OpenExclusive(). */ static int unixOpen( | | | | | | | | 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 | ** The old OpenExclusive() accepted a boolean argument - "delFlag". If ** true, the file was configured to be automatically deleted when the ** file handle closed. To achieve the same effect using this new ** interface, add the DELETEONCLOSE flag to those specified above for ** OpenExclusive(). */ static int unixOpen( sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */ const char *zPath, /* Pathname of file to be opened */ sqlite3_file *pFile, /* The file descriptor to be filled in */ int flags, /* Input flags to control the opening */ int *pOutFlags /* Output flags returned to SQLite core */ ){ int fd = 0; /* File descriptor returned by open() */ int dirfd = -1; /* Directory file descriptor */ int openFlags = 0; /* Flags to pass to open() */ int eType = flags&0xFFFFFF00; /* Type of file to open */ int noLock; /* True to omit locking primitives */ int rc = SQLITE_OK; int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); int isCreate = (flags & SQLITE_OPEN_CREATE); |
︙ | ︙ | |||
4300 4301 4302 4303 4304 4305 4306 | return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); } /* ** Delete the file at zPath. If the dirSync argument is true, fsync() ** the directory after deleting the file. */ | | > > > > | 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 | return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); } /* ** Delete the file at zPath. If the dirSync argument is true, fsync() ** the directory after deleting the file. */ static int unixDelete( sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ const char *zPath, /* Name of file to be deleted */ int dirSync /* If true, fsync() directory after deleting file */ ){ int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); unlink(zPath); #ifndef SQLITE_DISABLE_DIRSYNC if( dirSync ){ int fd; |
︙ | ︙ | |||
4338 4339 4340 4341 4342 4343 4344 | ** SQLITE_ACCESS_EXISTS: Return 1 if the file exists ** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable. ** SQLITE_ACCESS_READONLY: Return 1 if the file is readable. ** ** Otherwise return 0. */ static int unixAccess( | | | | | | 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 | ** SQLITE_ACCESS_EXISTS: Return 1 if the file exists ** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable. ** SQLITE_ACCESS_READONLY: Return 1 if the file is readable. ** ** Otherwise return 0. */ static int unixAccess( sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */ const char *zPath, /* Path of the file to examine */ int flags, /* What do we want to learn about the zPath file? */ int *pResOut /* Write result boolean here */ ){ int amode = 0; UNUSED_PARAMETER(NotUsed); SimulateIOError( return SQLITE_IOERR_ACCESS; ); switch( flags ){ case SQLITE_ACCESS_EXISTS: amode = F_OK; |
︙ | ︙ | |||
4384 4385 4386 4387 4388 4389 4390 | int nOut, /* Size of output buffer in bytes */ char *zOut /* Output buffer */ ){ /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this ** function failing. This function could fail if, for example, the | | | 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 | int nOut, /* Size of output buffer in bytes */ char *zOut /* Output buffer */ ){ /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this ** function failing. This function could fail if, for example, the ** current working directory has been unlinked. */ SimulateIOError( return SQLITE_ERROR ); assert( pVfs->mxPathname==MAX_PATHNAME ); UNUSED_PARAMETER(pVfs); zOut[nOut-1] = '\0'; |
︙ | ︙ | |||
4519 4520 4521 4522 4523 4524 4525 | sleep(seconds); return seconds*1000000; #endif UNUSED_PARAMETER(NotUsed); } /* | | > | | | 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 | sleep(seconds); return seconds*1000000; #endif UNUSED_PARAMETER(NotUsed); } /* ** The following variable, if set to a non-zero value, is interpreted as ** the number of seconds since 1970 and is used to set the result of ** sqlite3OsCurrentTime() during testing. */ #ifdef SQLITE_TEST int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ #endif /* ** Find the current time (in Universal Coordinated Time). Write the ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ |
︙ | ︙ | |||
4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 | *prNow = sqlite3_current_time/86400.0 + 2440587.5; } #endif UNUSED_PARAMETER(NotUsed); return 0; } static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ UNUSED_PARAMETER(NotUsed); UNUSED_PARAMETER(NotUsed2); UNUSED_PARAMETER(NotUsed3); return 0; } /* ************************ End of sqlite3_vfs methods *************************** ******************************************************************************/ /* ** Initialize the operating system interface. ** ** This routine registers all VFS implementations for unix-like operating ** systems. This routine, and the sqlite3_os_end() routine that follows, ** should be the only routines in this file that are visible from other ** files. */ int sqlite3_os_init(void){ | > > > > > > > > > > > > > | > | > | > > | > > > > > | 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 | *prNow = sqlite3_current_time/86400.0 + 2440587.5; } #endif UNUSED_PARAMETER(NotUsed); return 0; } /* ** We added the xGetLastError() method with the intention of providing ** better low-level error messages when operating-system problems come up ** during SQLite operation. But so far, none of that has been implemented ** in the core. So this routine is never called. For now, it is merely ** a place-holder. */ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ UNUSED_PARAMETER(NotUsed); UNUSED_PARAMETER(NotUsed2); UNUSED_PARAMETER(NotUsed3); return 0; } /* ************************ End of sqlite3_vfs methods *************************** ******************************************************************************/ /* ** Initialize the operating system interface. ** ** This routine registers all VFS implementations for unix-like operating ** systems. This routine, and the sqlite3_os_end() routine that follows, ** should be the only routines in this file that are visible from other ** files. ** ** This routine is called once during SQLite initialization and by a ** single thread. The memory allocation and mutex subsystems have not ** necessarily been initialized when this routine is called, and so they ** should not be used. */ int sqlite3_os_init(void){ /* ** The following macro defines an initializer for an sqlite3_vfs object. ** The name of the VFS is NAME. The pAppData is a pointer to a "finder" ** function. The FINDER parameter to this macro is the name of the ** finder-function. The finder-function returns a pointer to the ** sqlite_io_methods object that implements the desired locking ** behaviors. See the division above that contains the IOMETHODS ** macro for addition information on finder-functions. ** ** Most finders simply return a pointer to a fixed sqlite3_io_methods ** object. But the "autolockIoFinder" available on MacOSX does a little ** more than that; it looks at the filesystem type that hosts the ** database file and tries to choose an locking method appropriate for ** that filesystem time. */ #define UNIXVFS(VFSNAME, FINDER) { \ 1, /* iVersion */ \ sizeof(unixFile), /* szOsFile */ \ MAX_PATHNAME, /* mxPathname */ \ 0, /* pNext */ \ VFSNAME, /* zName */ \ |
︙ | ︙ | |||
4601 4602 4603 4604 4605 4606 4607 | unixDlClose, /* xDlClose */ \ unixRandomness, /* xRandomness */ \ unixSleep, /* xSleep */ \ unixCurrentTime, /* xCurrentTime */ \ unixGetLastError /* xGetLastError */ \ } | > > > > > | > > > > | > > > > | 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 | unixDlClose, /* xDlClose */ \ unixRandomness, /* xRandomness */ \ unixSleep, /* xSleep */ \ unixCurrentTime, /* xCurrentTime */ \ unixGetLastError /* xGetLastError */ \ } /* ** All default VFSes for unix are contained in the following array. ** ** Note that the sqlite3_vfs.pNext field of the VFS object is modified ** by the SQLite core when the VFS is registered. So the following ** array cannot be const. */ static sqlite3_vfs aVfs[] = { #if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) UNIXVFS("unix", autolockIoFinder ), #else UNIXVFS("unix", posixIoFinder ), #endif UNIXVFS("unix-none", nolockIoFinder ), UNIXVFS("unix-dotfile", dotlockIoFinder ), #if OS_VXWORKS UNIXVFS("unix-namedsem", semIoFinder ), #endif #if SQLITE_ENABLE_LOCKING_STYLE UNIXVFS("unix-posix", posixIoFinder ), UNIXVFS("unix-flock", flockIoFinder ), #endif #if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) UNIXVFS("unix-afp", afpIoFinder ), UNIXVFS("unix-proxy", proxyIoFinder ), #endif }; unsigned int i; /* Loop counter */ /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } return SQLITE_OK; } /* ** Shutdown the operating system interface. ** ** Some operating systems might need to do some cleanup in this routine, ** to release dynamically allocated objects. But not on unix. ** This routine is a no-op for unix. */ int sqlite3_os_end(void){ return SQLITE_OK; } #endif /* SQLITE_OS_UNIX */ |