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 code that is specific to windows. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqliteInt.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WIN /* This file is used for windows only */ 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A Note About Memory Allocation: 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This driver uses malloc()/free() directly rather than going through 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are designed for use on embedded systems where memory is scarce and 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** malloc failures happen frequently. Win32 does not typically run on 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** embedded systems, and when it does the developers normally have bigger 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** problems to worry about than running out of memory. So there is not 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a compelling need to use the wrappers. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** But there is a good reason to not use the wrappers. If we use the 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** wrappers then we will get simulated malloc() failures within this 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** driver. And that causes all kinds of problems for our tests. We 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** could enhance SQLite to deal with simulated malloc failures within 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the OS driver, but the code to deal with those failure would not 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** be exercised on Linux (which does not need to malloc() in the driver) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and so we would have difficulty writing coverage tests for that 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** code. Better to leave the code out, we think. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The point of this discussion is as follows: When creating a new 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** OS layer for an embedded system, if you use this file as an example, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** avoid the use of malloc()/free(). Those routines work ok on windows 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** desktops but not so well in embedded systems. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winbase.h> 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __CYGWIN__ 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <sys/cygwin.h> 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Macros used to determine whether or not to use threads. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(THREADSAFE) && THREADSAFE 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define SQLITE_W32_THREADS 1 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Include code that is common to all os_*.c files 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "os_common.h" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Some microsoft compilers lack this definition. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef INVALID_FILE_ATTRIBUTES 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Determine if we are dealing with WindowsCE - which has a much 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** reduced API. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define AreFileApisANSI() 1 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define FormatMessageW(a,b,c,d,e,f,g) 0 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Forward references */ 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winShm winShm; /* A connection to shared-memory */ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winShmNode winShmNode; /* A region of shared-memory */ 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** WinCE lacks native support for file locking so we have to fake it 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with some code of our own. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winceLock { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nReaders; /* Number of reader locks obtained */ 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bPending; /* Indicates a pending lock has been obtained */ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bReserved; /* Indicates a reserved lock has been obtained */ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} winceLock; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The winFile structure is a subclass of sqlite3_file* specific to the win32 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** portability layer. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winFile winFile; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winFile { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sqlite3_io_methods *pMethod; /*** Must be first ***/ 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs *pVfs; /* The VFS used to open this file */ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE h; /* Handle for accessing the file */ 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char locktype; /* Type of lock currently held on this file */ 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) short sharedLockByte; /* Randomly chosen byte used as a shared lock */ 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD lastErrno; /* The Windows errno from the last I/O error */ 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD sectorSize; /* Sector size of the device file is on */ 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm *pShm; /* Instance of shared memory on this file */ 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zPath; /* Full pathname of this file */ 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hMutex; /* Mutex used to control access to shared lock */ 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hShared; /* Shared memory segment used for locking */ 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceLock local; /* Locks obtained by this instance of winFile */ 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceLock *shared; /* Global shared lock memory for the file */ 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Forward prototypes. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getSectorSize( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs *pVfs, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zRelative /* UTF-8 file name */ 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following variable is (normally) set once and never changes 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** thereafter. It records whether the operating system is Win95 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or WinNT. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 0: Operating system unknown. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1: Operating system is Win95. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2: Operating system is WinNT. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** In order to facilitate testing on a WinNT system, the test fixture 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** can manually set this value to 1 to emulate Win98 behavior. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_type = 0; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int sqlite3_os_type = 0; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or WinCE. Return false (zero) for Win95, Win98, or WinME. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Here is an interesting observation: Win95, Win98, and WinME lack 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the LockFileEx() API. But we can still statically link against that 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** API as long as we don't call it when running Win95/98/ME. A call to 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this routine is used to determine if the host is Win95/98/ME or 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** WinNT/2K/XP so that we will know whether or not we can safely call 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the LockFileEx() API. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define isNT() (1) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int isNT(void){ 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sqlite3_os_type==0 ){ 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSVERSIONINFO sInfo; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sInfo.dwOSVersionInfoSize = sizeof(sInfo); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetVersionEx(&sInfo); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sqlite3_os_type==2; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_WINCE */ 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert a UTF-8 string to microsoft unicode (UTF-16?). 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Space to hold the returned string is obtained from malloc. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WCHAR *utf8ToUnicode(const char *zFilename){ 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nChar; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zWideFilename; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) ); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zWideFilename==0 ){ 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nChar==0 ){ 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zWideFilename); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zWideFilename = 0; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zWideFilename; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert microsoft unicode to UTF-8. Space to hold the returned string is 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** obtained from malloc(). 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *unicodeToUtf8(const WCHAR *zWideFilename){ 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nByte; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zFilename; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zFilename = malloc( nByte ); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zFilename==0 ){ 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nByte == 0 ){ 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zFilename); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zFilename = 0; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zFilename; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert an ansi string to microsoft unicode, based on the 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** current codepage settings for file apis. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Space to hold the returned string is obtained 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** from malloc. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WCHAR *mbcsToUnicode(const char *zFilename){ 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nByte; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zMbcsFilename; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) ); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zMbcsFilename==0 ){ 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nByte==0 ){ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zMbcsFilename); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zMbcsFilename = 0; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zMbcsFilename; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert microsoft unicode to multibyte character string, based on the 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** user's Ansi codepage. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Space to hold the returned string is obtained from 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** malloc(). 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *unicodeToMbcs(const WCHAR *zWideFilename){ 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nByte; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zFilename; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zFilename = malloc( nByte ); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zFilename==0 ){ 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nByte == 0 ){ 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zFilename); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zFilename = 0; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zFilename; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert multibyte character string to UTF-8. Space to hold the 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returned string is obtained from malloc(). 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zFilenameUtf8; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zTmpWide; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zTmpWide = mbcsToUnicode(zFilename); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zTmpWide==0 ){ 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zFilenameUtf8 = unicodeToUtf8(zTmpWide); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zTmpWide); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zFilenameUtf8; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert UTF-8 to multibyte character string. Space to hold the 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returned string is obtained from malloc(). 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *utf8ToMbcs(const char *zFilename){ 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zFilenameMbcs; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zTmpWide; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zTmpWide = utf8ToUnicode(zFilename); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zTmpWide==0 ){ 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zFilenameMbcs = unicodeToMbcs(zTmpWide); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zTmpWide); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zFilenameMbcs; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/************************************************************************* 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This section contains code for WinCE only. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** WindowsCE does not have a localtime() function. So create a 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** substitute. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct tm *__cdecl localtime(const time_t *t) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static struct tm y; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME uTm, lTm; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEMTIME pTm; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_int64 t64; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t64 = *t; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t64 = (t64 + 11644473600)*10000000; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uTm.dwHighDateTime= (DWORD)(t64 >> 32); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileTimeToLocalFileTime(&uTm,&lTm); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileTimeToSystemTime(&lTm,&pTm); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y.tm_year = pTm.wYear - 1900; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y.tm_mon = pTm.wMonth - 1; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y.tm_wday = pTm.wDayOfWeek; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y.tm_mday = pTm.wDay; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y.tm_hour = pTm.wHour; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y.tm_min = pTm.wMinute; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y.tm_sec = pTm.wSecond; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &y; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This will never be called, but defined to make the code compile */ 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetTempPathA(a,b) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Acquire a lock on the handle h 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winceMutexAcquire(HANDLE h){ 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwErr; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwErr = WaitForSingleObject(h, INFINITE); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Release a lock acquired by winceMutexAcquire() 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define winceMutexRelease(h) ReleaseMutex(h) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Create the mutex and shared memory used for locking in the file 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** descriptor pFile 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zTok; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zName = utf8ToUnicode(zFilename); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bInit = TRUE; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Initialize the local lockdata */ 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZeroMemory(&pFile->local, sizeof(pFile->local)); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Replace the backslashes from the filename and lowercase it 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** to derive a mutex name. */ 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zTok = CharLowerW(zName); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;*zTok;zTok++){ 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*zTok == '\\') *zTok = '_'; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create/open the named mutex */ 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->hMutex = CreateMutexW(NULL, FALSE, zName); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pFile->hMutex){ 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zName); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Acquire the mutex before continuing */ 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexAcquire(pFile->hMutex); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Since the names of named mutexes, semaphores, file mappings etc are 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** case-sensitive, take advantage of that by uppercasing the mutex name 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** and using that as the shared filemapping name. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CharUpperW(zName); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PAGE_READWRITE, 0, sizeof(winceLock), 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zName); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set a flag that indicates we're the first to create the memory so it 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** must be zero-initialized */ 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetLastError() == ERROR_ALREADY_EXISTS){ 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bInit = FALSE; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zName); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we succeeded in making the shared memory handle, map it. */ 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->hShared){ 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If mapping failed, close the shared memory handle and erase it */ 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pFile->shared){ 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(pFile->hShared); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->hShared = NULL; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If shared memory could not be created, then close the mutex and fail */ 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->hShared == NULL){ 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexRelease(pFile->hMutex); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(pFile->hMutex); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->hMutex = NULL; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Initialize the shared memory if we're supposed to */ 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bInit) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZeroMemory(pFile->shared, sizeof(winceLock)); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexRelease(pFile->hMutex); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Destroy the part of winFile that deals with wince locks 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winceDestroyLock(winFile *pFile){ 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->hMutex){ 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Acquire the mutex */ 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexAcquire(pFile->hMutex); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The following blocks should probably assert in debug mode, but they 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) are to cleanup in case any locks remained open */ 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.nReaders){ 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->nReaders --; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.bReserved){ 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bReserved = FALSE; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.bPending){ 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bPending = FALSE; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.bExclusive){ 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bExclusive = FALSE; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* De-reference and close our copy of the shared memory handle */ 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnmapViewOfFile(pFile->shared); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(pFile->hShared); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Done with the mutex */ 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexRelease(pFile->hMutex); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(pFile->hMutex); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->hMutex = NULL; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An implementation of the LockFile() API of windows for wince 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceLockFile( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE *phFile, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwFileOffsetLow, 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwFileOffsetHigh, 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nNumberOfBytesToLockLow, 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nNumberOfBytesToLockHigh 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = HANDLE_TO_WINFILE(phFile); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bReturn = FALSE; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(dwFileOffsetHigh); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(nNumberOfBytesToLockHigh); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pFile->hMutex) return TRUE; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexAcquire(pFile->hMutex); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Wanting an exclusive lock? */ 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dwFileOffsetLow == (DWORD)SHARED_FIRST 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bExclusive = TRUE; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.bExclusive = TRUE; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Want a read-only lock? */ 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nNumberOfBytesToLockLow == 1){ 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->shared->bExclusive == 0){ 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.nReaders ++; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.nReaders == 1){ 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->nReaders ++; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Want a pending lock? */ 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){ 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If no pending lock has been acquired, then acquire it */ 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->shared->bPending == 0) { 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bPending = TRUE; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.bPending = TRUE; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Want a reserved lock? */ 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->shared->bReserved == 0) { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bReserved = TRUE; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.bReserved = TRUE; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexRelease(pFile->hMutex); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bReturn; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An implementation of the UnlockFile API of windows for wince 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceUnlockFile( 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE *phFile, 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwFileOffsetLow, 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwFileOffsetHigh, 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nNumberOfBytesToUnlockLow, 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nNumberOfBytesToUnlockHigh 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = HANDLE_TO_WINFILE(phFile); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bReturn = FALSE; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(dwFileOffsetHigh); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pFile->hMutex) return TRUE; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexAcquire(pFile->hMutex); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Releasing a reader lock or an exclusive lock */ 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Did we have an exclusive lock? */ 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.bExclusive){ 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.bExclusive = FALSE; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bExclusive = FALSE; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Did we just have a reader lock? */ 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (pFile->local.nReaders){ 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.nReaders --; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.nReaders == 0) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->nReaders --; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Releasing a pending lock */ 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.bPending){ 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.bPending = FALSE; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bPending = FALSE; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Releasing a reserved lock */ 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pFile->local.bReserved) { 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->local.bReserved = FALSE; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->shared->bReserved = FALSE; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bReturn = TRUE; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceMutexRelease(pFile->hMutex); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bReturn; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An implementation of the LockFileEx() API of windows for wince 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceLockFileEx( 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE *phFile, 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwFlags, 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwReserved, 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nNumberOfBytesToLockLow, 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nNumberOfBytesToLockHigh, 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPOVERLAPPED lpOverlapped 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(dwReserved); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(nNumberOfBytesToLockHigh); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the caller wants a shared read lock, forward this call 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** to winceLockFile */ 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lpOverlapped->Offset == (DWORD)SHARED_FIRST && 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlags == 1 && 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** End of the special code for wince 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*****************************************************************************/ 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_WINCE */ 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/***************************************************************************** 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The next group of routines implement the I/O methods specified 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by the sqlite3_io_methods object. 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/ 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Some microsoft compilers lack this definition. 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef INVALID_SET_FILE_POINTER 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define INVALID_SET_FILE_POINTER ((DWORD)-1) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Move the current position of the file handle passed as the first 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** argument to offset iOffset within the file. If successful, return 0. 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, set pFile->lastErrno and return non-zero. 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){ 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONG upperBits; /* Most sig. 32 bits of new offset */ 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LONG lowerBits; /* Least sig. 32 bits of new offset */ 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwRet; /* Value returned by SetFilePointer() */ 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upperBits = (LONG)((iOffset>>32) & 0x7fffffff); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lowerBits = (LONG)(iOffset & 0xffffffff); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* API oddity: If successful, SetFilePointer() returns a dword 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** containing the lower 32-bits of the new file-offset. Or, if it fails, 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** whether an error has actually occured, it is also necessary to call 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** GetLastError(). 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){ 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file. 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is reported that an attempt to close a handle might sometimes 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** fail. This is a very unreasonable result, but windows is notorious 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for being unreasonable so I do not doubt that it might happen. If 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the close fails, we pause for 100 milliseconds and try again. As 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** giving up and returning an error. 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MX_CLOSE_ATTEMPT 3 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winClose(sqlite3_file *id){ 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc, cnt = 0; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( id!=0 ); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile->pShm==0 ); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("CLOSE %d\n", pFile->h)); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do{ 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = CloseHandle(pFile->h); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WINCE_DELETION_ATTEMPTS 3 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winceDestroyLock(pFile); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pFile->zDeleteOnClose ){ 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cnt = 0; 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while( 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteFileW(pFile->zDeleteOnClose)==0 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && cnt++ < WINCE_DELETION_ATTEMPTS 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ){ 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sleep(100); /* Wait a little before trying again */ 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(pFile->zDeleteOnClose); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed")); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenCounter(-1); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc ? SQLITE_OK : SQLITE_IOERR; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from a file into a buffer. Return SQLITE_OK if all 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes were read successfully and SQLITE_IOERR if anything goes 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** wrong. 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winRead( 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_file *id, /* File to read from */ 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *pBuf, /* Write content into this buffer */ 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int amt, /* Number of bytes to read */ 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_int64 offset /* Begin reading at this offset */ 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; /* file handle */ 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nRead; /* Number of bytes actually read from file */ 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( id!=0 ); 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError(return SQLITE_IOERR_READ); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype)); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( seekWinFile(pFile, offset) ){ 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_FULL; 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOERR_READ; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nRead<(DWORD)amt ){ 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Unread parts of the buffer must be zero-filled */ 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&((char*)pBuf)[nRead], 0, amt-nRead); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOERR_SHORT_READ; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data from a buffer into a file. Return SQLITE_OK on success 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or some other error code on failure. 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winWrite( 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_file *id, /* File to write into */ 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void *pBuf, /* The bytes to be written */ 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int amt, /* Number of bytes to write */ 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_int64 offset /* Offset into the file to begin writing at */ 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc; /* True if error has occured, else false */ 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; /* File handle */ 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( amt>0 ); 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile ); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError(return SQLITE_IOERR_WRITE); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateDiskfullError(return SQLITE_FULL); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype)); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = seekWinFile(pFile, offset); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc==0 ){ 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nRem = amt; /* Number of bytes yet to be written */ 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nWrite; /* Bytes written by each WriteFile() call */ 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){ 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aRem += nWrite; 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nRem -= nWrite; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( nRem>0 ){ 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = 1; 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc ){ 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){ 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_FULL; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOERR_WRITE; 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate an open file to a specified size 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; /* File handle object */ 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = SQLITE_OK; /* Return code for this function */ 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile ); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte)); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError(return SQLITE_IOERR_TRUNCATE); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the user has configured a chunk-size for this file, truncate the 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** file so that it consists of an integer number of chunks (i.e. the 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** actual file size after the operation may be larger than the requested 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** size). 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pFile->szChunk ){ 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( seekWinFile(pFile, nByte) ){ 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR_TRUNCATE; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else if( 0==SetEndOfFile(pFile->h) ){ 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR_TRUNCATE; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok")); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Count the number of fullsyncs and normal syncs. This is used to test 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that syncs and fullsyncs are occuring at the right times. 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_sync_count = 0; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_fullsync_count = 0; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Make sure all writes to a particular file are committed to disk. 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winSync(sqlite3_file *id, int flags){ 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(id); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile ); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((flags&0x0F)==SQLITE_SYNC_NORMAL 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || (flags&0x0F)==SQLITE_SYNC_FULL 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype)); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_TEST 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(flags); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( flags & SQLITE_SYNC_FULL ){ 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_fullsync_count++; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_sync_count++; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Unix cannot, but some systems may return SQLITE_FULL from here. This 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** line is to test that doing so does not cause any problems. 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateDiskfullError( return SQLITE_FULL ); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError( return SQLITE_IOERR; ); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** no-op 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_NO_SYNC 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( FlushFileBuffers(pFile->h) ){ 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOERR; 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Determine the current size of a file in bytes 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD upperBits; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD lowerBits; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD error; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( id!=0 ); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError(return SQLITE_IOERR_FSTAT); 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lowerBits = GetFileSize(pFile->h, &upperBits); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (lowerBits == INVALID_FILE_SIZE) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && ((error = GetLastError()) != NO_ERROR) ) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = error; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOERR_FSTAT; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef LOCKFILE_FAIL_IMMEDIATELY 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define LOCKFILE_FAIL_IMMEDIATELY 1 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Acquire a reader lock. 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Different API routines are called depending on whether or not this 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is Win95 or WinNT. 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getReadLock(winFile *pFile){ 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OVERLAPPED ovlp; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ovlp.Offset = SHARED_FIRST; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ovlp.OffsetHigh = 0; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ovlp.hEvent = 0; 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, SHARED_SIZE, 0, &ovlp); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int lk; 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_randomness(sizeof(lk), &lk); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( res == 0 ){ 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return res; 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Undo a readlock 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unlockReadLock(winFile *pFile){ 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( res == 0 ){ 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return res; 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter locktype - one 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following: 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (1) SHARED_LOCK 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (2) RESERVED_LOCK 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (3) PENDING_LOCK 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** (4) EXCLUSIVE_LOCK 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between. The locking might fail on one of the later 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal. The following chart shows the allowed 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states: 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** UNLOCKED -> SHARED 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SHARED -> RESERVED 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SHARED -> (PENDING) -> EXCLUSIVE 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** RESERVED -> (PENDING) -> EXCLUSIVE 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** PENDING -> EXCLUSIVE 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock. The winUnlock() routine 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** erases all locks at once and returns us immediately to locking level 0. 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is not possible to lower the locking level one step at a time. You 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must go straight to locking level 0. 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winLock(sqlite3_file *id, int locktype){ 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = SQLITE_OK; /* Return code from subroutines */ 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res = 1; /* Result of a windows lock call */ 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int newLocktype; /* Set pFile->locktype to this value before exiting */ 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD error = NO_ERROR; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( id!=0 ); 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("LOCK %d %d was %d(%d)\n", 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->h, locktype, pFile->locktype, pFile->sharedLockByte)); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If there is already a lock of this type or more restrictive on the 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** OsFile, do nothing. Don't use the end_lock: exit path, as 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** sqlite3OsEnterMutex() hasn't been called yet. 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pFile->locktype>=locktype ){ 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure the locking sequence is correct 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( locktype!=PENDING_LOCK ); 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the PENDING_LOCK byte is temporary. 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLocktype = pFile->locktype; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (pFile->locktype==NO_LOCK) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || ( (locktype==EXCLUSIVE_LOCK) 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && (pFile->locktype==RESERVED_LOCK)) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ){ 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cnt = 3; 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Try 3 times to get the pending lock. The pending lock might be 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** held by another reader process who will release it momentarily. 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt)); 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sleep(1); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gotPendingLock = res; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !res ){ 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = GetLastError(); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Acquire a shared lock 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locktype==SHARED_LOCK && res ){ 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile->locktype==NO_LOCK ); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = getReadLock(pFile); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( res ){ 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLocktype = SHARED_LOCK; 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = GetLastError(); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Acquire a RESERVED lock 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locktype==RESERVED_LOCK && res ){ 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile->locktype==SHARED_LOCK ); 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( res ){ 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLocktype = RESERVED_LOCK; 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = GetLastError(); 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Acquire a PENDING lock 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locktype==EXCLUSIVE_LOCK && res ){ 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLocktype = PENDING_LOCK; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gotPendingLock = 0; 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Acquire an EXCLUSIVE lock 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locktype==EXCLUSIVE_LOCK && res ){ 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile->locktype>=SHARED_LOCK ); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = unlockReadLock(pFile); 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("unreadlock = %d\n", res)); 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( res ){ 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newLocktype = EXCLUSIVE_LOCK; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = GetLastError(); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("error-code = %d\n", error)); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getReadLock(pFile); 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we are holding a PENDING lock that ought to be released, then 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** release it now. 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( gotPendingLock && locktype==SHARED_LOCK ){ 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Update the state of the lock has held in the file descriptor then 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** return the appropriate result code. 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( res ){ 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_OK; 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h, 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) locktype, newLocktype)); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = error; 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_BUSY; 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->locktype = (u8)newLocktype; 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, return 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** non-zero, otherwise zero. 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc; 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( id!=0 ); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pFile->locktype>=RESERVED_LOCK ){ 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = 1; 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc)); 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc ){ 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = !rc; 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc)); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pResOut = rc; 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor id to locktype. locktype 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK. 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op. 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is not possible for this routine to fail if the second argument 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is NO_LOCK. If the second argument is SHARED_LOCK then this routine 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** might return SQLITE_IOERR; 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winUnlock(sqlite3_file *id, int locktype){ 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type; 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = SQLITE_OK; 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pFile!=0 ); 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( locktype<=SHARED_LOCK ); 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->locktype, pFile->sharedLockByte)); 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) type = pFile->locktype; 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( type>=EXCLUSIVE_LOCK ){ 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This should never happen. We should always be able to 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** reacquire the read lock */ 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR_UNLOCK; 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( type>=RESERVED_LOCK ){ 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( locktype==NO_LOCK && type>=SHARED_LOCK ){ 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unlockReadLock(pFile); 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( type>=PENDING_LOCK ){ 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->locktype = (u8)locktype; 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Control and query of the open file handle. 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winFileControl(sqlite3_file *id, int op, void *pArg){ 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch( op ){ 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_FCNTL_LOCKSTATE: { 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(int*)pArg = ((winFile*)id)->locktype; 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_LAST_ERRNO: { 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(int*)pArg = (int)((winFile*)id)->lastErrno; 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_FCNTL_CHUNK_SIZE: { 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((winFile*)id)->szChunk = *(int *)pArg; 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_FCNTL_SIZE_HINT: { 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_int64 sz = *(sqlite3_int64*)pArg; 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(1); 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winTruncate(id, sz); 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(0); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_FCNTL_SYNC_OMITTED: { 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOTFOUND; 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the sector size in bytes of the underlying block device for 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the specified file. This is almost always 512 bytes, but may be 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** larger for some devices. 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLite code assumes this function cannot fail. It also assumes that 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** if two files are created in the same file-system directory (i.e. 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a database and its journal file) that the sector size will be the 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** same for both. 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winSectorSize(sqlite3_file *id){ 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( id!=0 ); 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (int)(((winFile*)id)->sectorSize); 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return a vector of device characteristics. 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winDeviceCharacteristics(sqlite3_file *id){ 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(id); 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_WAL 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Windows will only let you create file view mappings 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on allocation size granularity boundaries. 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** During sqlite3_os_init() we do a GetSystemInfo() 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to get the granularity size. 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SYSTEM_INFO winSysInfo; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Helper functions to obtain and relinquish the global mutex. The 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** global mutex is used to protect the winLockInfo objects used by 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this file, all of which may be shared by multiple threads. 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Function winShmMutexHeld() is used to assert() that the global mutex 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is held when required. This function is only used as part of assert() 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** statements. e.g. 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShmEnterMutex() 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** assert( winShmMutexHeld() ); 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShmLeaveMutex() 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmEnterMutex(void){ 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmLeaveMutex(void){ 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmMutexHeld(void) { 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Object used to represent a single file opened and mmapped to provide 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** shared memory. When multiple threads all reference the same 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** log-summary, each thread has its own winFile object, but they all 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** point to a single instance of this object. In other words, each 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** log-summary is opened only once per process. 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShmMutexHeld() must be true when creating or destroying 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this object or while reading or writing the following fields: 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** nRef 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pNext 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following fields are read-only after the object is created: 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** fid 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** zFilename 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Either winShmNode.mutex must be held or winShmNode.nRef==0 and 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShmMutexHeld() is true when reading or writing any other field 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in this structure. 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winShmNode { 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex *mutex; /* Mutex to access this object */ 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zFilename; /* Name of the file */ 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile hFile; /* File handle from winOpen */ 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int szRegion; /* Size of shared-memory regions */ 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nRegion; /* Size of array apRegion */ 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ShmRegion { 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hMap; /* File handle from CreateFileMapping */ 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *pMap; 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } *aRegion; 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD lastErrno; /* The Windows errno from the last I/O error */ 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nRef; /* Number of winShm objects pointing to this */ 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm *pFirst; /* All winShm objects pointing to this */ 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode *pNext; /* Next in list of all winShmNode objects */ 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 nextShmId; /* Next available winShm.id value */ 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A global array of all winShmNode objects. 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The winShmMutexHeld() must be true while reading or writing this list. 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static winShmNode *winShmNodeList = 0; 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Structure used internally by this VFS to record the state of an 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** open shared memory connection. 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following fields are initialized when this object is created and 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are read-only thereafter: 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShm.pShmNode 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShm.id 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All other fields are read/write. The winShm.pShmNode->mutex must be held 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** while accessing any read/write fields. 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winShm { 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode *pShmNode; /* The underlying winShmNode object */ 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm *pNext; /* Next winShm with the same winShmNode */ 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 hasMutex; /* True if holding the winShmNode mutex */ 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 sharedMask; /* Mask of shared locks held */ 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 exclMask; /* Mask of exclusive locks held */ 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u8 id; /* Id of this connection with its winShmNode */ 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Constants used for locking 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Apply advisory locks for all n bytes beginning at ofst. 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _SHM_UNLCK 1 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _SHM_RDLCK 2 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _SHM_WRLCK 3 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmSystemLock( 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode *pFile, /* Apply locks to this open shared-memory segment */ 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */ 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ofst, /* Offset to first byte to be locked/unlocked */ 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nByte /* Number of bytes to lock or unlock */ 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OVERLAPPED ovlp; 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwFlags; 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = 0; /* Result code form Lock/UnlockFileEx() */ 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Access to the winShmNode object is serialized by the caller */ 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Initialize the locking parameters */ 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlags = LOCKFILE_FAIL_IMMEDIATELY; 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&ovlp, 0, sizeof(OVERLAPPED)); 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ovlp.Offset = ofst; 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Release/Acquire the system-level lock */ 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( lockType==_SHM_UNLCK ){ 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = UnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp); 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = LockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp); 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc!= 0 ){ 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_OK; 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_BUSY; 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n", 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->hFile.h, 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc==SQLITE_OK ? "ok" : "failed", 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx", 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno)); 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Forward references to VFS methods */ 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winDelete(sqlite3_vfs *,const char*,int); 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This is not a VFS shared-memory method; it is a utility function called 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by VFS shared-memory methods. 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode **pp; 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode *p; 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL bRc; 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( winShmMutexHeld() ); 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = &winShmNodeList; 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while( (p = *pp)!=0 ){ 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( p->nRef==0 ){ 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( p->mutex ) sqlite3_mutex_free(p->mutex); 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<p->nRegion; i++){ 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bRc = UnmapViewOfFile(p->aRegion[i].pMap); 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n", 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)GetCurrentProcessId(), i, 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bRc ? "ok" : "failed")); 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bRc = CloseHandle(p->aRegion[i].hMap); 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n", 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)GetCurrentProcessId(), i, 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bRc ? "ok" : "failed")); 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( p->hFile.h != INVALID_HANDLE_VALUE ){ 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(1); 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winClose((sqlite3_file *)&p->hFile); 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(0); 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( deleteFlag ){ 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(1); 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winDelete(pVfs, p->zFilename, 0); 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(0); 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pp = p->pNext; 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_free(p->aRegion); 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_free(p); 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = &p->pNext; 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open the shared-memory area associated with database file pDbFd. 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When opening a new shared-memory file, if no other instances of that 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file are currently open, in this process or in other processes, then 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the file must be truncated to zero length or have its header cleared. 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winOpenSharedMemory(winFile *pDbFd){ 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct winShm *p; /* The connection to be opened */ 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc; /* Result code */ 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct winShmNode *pNew; /* Newly allocated winShmNode */ 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nName; /* Size of zName in bytes */ 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pDbFd->pShm==0 ); /* Not previously opened */ 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Allocate space for the new sqlite3_shm object. Also speculatively 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** allocate space for a new winShmNode and filename. 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = sqlite3_malloc( sizeof(*p) ); 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( p==0 ) return SQLITE_NOMEM; 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(p, 0, sizeof(*p)); 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nName = sqlite3Strlen30(pDbFd->zPath); 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 15 ); 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pNew==0 ){ 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_free(p); 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(pNew, 0, sizeof(*pNew)); 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNew->zFilename = (char*)&pNew[1]; 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Look to see if there is an existing winShmNode that can be used. 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** If no matching winShmNode currently exists, create a new one. 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmEnterMutex(); 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* TBD need to come up with better match here. Perhaps 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** use FILE_ID_BOTH_DIR_INFO Structure. 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pShmNode ){ 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_free(pNew); 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode = pNew; 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pNew = 0; 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->pNext = winShmNodeList; 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNodeList = pShmNode; 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pShmNode->mutex==0 ){ 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_NOMEM; 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto shm_open_err; 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winOpen(pDbFd->pVfs, 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->zFilename, /* Name of the file (UTF-8) */ 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (sqlite3_file*)&pShmNode->hFile, /* File handle here */ 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */ 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( SQLITE_OK!=rc ){ 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_CANTOPEN_BKPT; 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto shm_open_err; 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check to see if another process is holding the dead-man switch. 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** If not, truncate the file to zero length. 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc!=SQLITE_OK ){ 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR_SHMOPEN; 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc==SQLITE_OK ){ 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc ) goto shm_open_err; 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make the new connection a child of the winShmNode */ 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->pShmNode = pShmNode; 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->id = pShmNode->nextShmId++; 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->nRef++; 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pDbFd->pShm = p; 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmLeaveMutex(); 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The reference count on pShmNode has already been incremented under 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the cover of the winShmEnterMutex() mutex and the pointer from the 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** new (struct winShm) object to the pShmNode has been set. All that is 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** left to do is to link the new object into the linked list starting 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** mutex. 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_enter(pShmNode->mutex); 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->pNext = pShmNode->pFirst; 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->pFirst = p; 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_leave(pShmNode->mutex); 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Jump here on any error */ 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)shm_open_err: 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_free(p); 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_free(pNew); 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmLeaveMutex(); 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a connection to shared-memory. Delete the underlying 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** storage if deleteFlag is true. 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmUnmap( 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_file *fd, /* Database holding shared memory */ 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int deleteFlag /* Delete after closing if true */ 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pDbFd; /* Database holding shared-memory */ 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm *p; /* The connection to be closed */ 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode *pShmNode; /* The underlying shared-memory file */ 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm **pp; /* For looping over sibling connections */ 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pDbFd = (winFile*)fd; 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = pDbFd->pShm; 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( p==0 ) return SQLITE_OK; 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode = p->pShmNode; 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove connection p from the set of connections associated 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** with pShmNode */ 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_enter(pShmNode->mutex); 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pp = p->pNext; 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Free the connection p */ 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_free(p); 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pDbFd->pShm = 0; 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_leave(pShmNode->mutex); 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If pShmNode->nRef has reached 0, then close the underlying 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** shared-memory file, too */ 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmEnterMutex(); 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( pShmNode->nRef>0 ); 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->nRef--; 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pShmNode->nRef==0 ){ 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmPurge(pDbFd->pVfs, deleteFlag); 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmLeaveMutex(); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Change the lock state for a shared-memory segment. 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmLock( 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_file *fd, /* Database file holding the shared memory */ 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ofst, /* First lock to acquire or release */ 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n, /* Number of locks to acquire or release */ 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags /* What to do with the lock */ 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm *p = pDbFd->pShm; /* The shared memory being locked */ 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm *pX; /* For looping over all siblings */ 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode *pShmNode = p->pShmNode; 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = SQLITE_OK; /* Result code */ 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 mask; /* Mask of locks to take or release */ 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( n>=1 ); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( n>1 || mask==(1<<ofst) ); 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_enter(pShmNode->mutex); 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( flags & SQLITE_SHM_UNLOCK ){ 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 allMask = 0; /* Mask of locks held by siblings */ 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* See if any siblings hold this same lock */ 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pX==p ) continue; 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allMask |= pX->sharedMask; 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Unlock the system-level locks */ 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (mask & allMask)==0 ){ 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n); 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_OK; 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Undo the local locks */ 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc==SQLITE_OK ){ 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->exclMask &= ~mask; 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->sharedMask &= ~mask; 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else if( flags & SQLITE_SHM_SHARED ){ 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u16 allShared = 0; /* Union of locks held by connections other than "p" */ 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Find out which shared locks are already held by sibling connections. 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** If any sibling already holds an exclusive lock, go ahead and return 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** SQLITE_BUSY. 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (pX->exclMask & mask)!=0 ){ 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_BUSY; 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allShared |= pX->sharedMask; 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get shared locks at the system level, if necessary */ 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc==SQLITE_OK ){ 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (allShared & mask)==0 ){ 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n); 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_OK; 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get the local shared locks */ 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc==SQLITE_OK ){ 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->sharedMask |= mask; 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure no sibling connections hold locks that will block this 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** lock. If any do, return SQLITE_BUSY right away. 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_BUSY; 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Get the exclusive locks at the system level. Then if successful 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** also mark the local connection as being locked. 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc==SQLITE_OK ){ 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n); 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc==SQLITE_OK ){ 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( (p->sharedMask & mask)==0 ); 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->exclMask |= mask; 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_leave(pShmNode->mutex); 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n", 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask, 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc ? "failed" : "ok")); 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implement a memory barrier or memory fence on shared memory. 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All loads and stores begun before the barrier must complete before 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** any load or store begun after the barrier. 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmBarrier( 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_file *fd /* Database holding the shared memory */ 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(fd); 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* MemoryBarrier(); // does not work -- do not know why not */ 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmEnterMutex(); 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmLeaveMutex(); 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called to obtain a pointer to region iRegion of the 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** shared-memory associated with the database file fd. Shared-memory regions 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are numbered starting from zero. Each shared-memory region is szRegion 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes in size. 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If an error occurs, an error code is returned and *pp is set to NULL. 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, if the isWrite parameter is 0 and the requested shared-memory 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** region has not been allocated (by any client, including one running in a 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** separate process), then *pp is set to NULL and SQLITE_OK returned. If 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** isWrite is non-zero and the requested shared-memory region has not yet 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** been allocated, it is allocated by this function. 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the shared-memory region has already been allocated or is allocated by 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this call as described above, then it is mapped into this processes 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** address space (if it is not already), *pp is set to point to the mapped 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** memory and SQLITE_OK returned. 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmMap( 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_file *fd, /* Handle open on database file */ 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iRegion, /* Region to retrieve */ 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int szRegion, /* Size of regions */ 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isWrite, /* True to extend file if necessary */ 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void volatile **pp /* OUT: Mapped memory */ 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pDbFd = (winFile*)fd; 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShm *p = pDbFd->pShm; 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmNode *pShmNode; 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = SQLITE_OK; 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !p ){ 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winOpenSharedMemory(pDbFd); 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc!=SQLITE_OK ) return rc; 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = pDbFd->pShm; 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode = p->pShmNode; 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_enter(pShmNode->mutex); 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pShmNode->nRegion<=iRegion ){ 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ShmRegion *apNew; /* New aRegion[] array */ 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_int64 sz; /* Current size of wal-index file */ 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->szRegion = szRegion; 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The requested region is not mapped into this processes address space. 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Check to see if it has been allocated (i.e. if the wal-index file is 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** large enough to contain the requested region). 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc!=SQLITE_OK ){ 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR_SHMSIZE; 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto shmpage_out; 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sz<nByte ){ 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The requested memory region does not exist. If isWrite is set to 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned. 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** the requested memory region. 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !isWrite ) goto shmpage_out; 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte); 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc!=SQLITE_OK ){ 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR_SHMSIZE; 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto shmpage_out; 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Map the requested memory region into this processes address space. */ 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) apNew = (struct ShmRegion *)sqlite3_realloc( 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !apNew ){ 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR_NOMEM; 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto shmpage_out; 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->aRegion = apNew; 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while( pShmNode->nRegion<=iRegion ){ 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hMap; /* file-mapping handle */ 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *pMap = 0; /* Mapped memory region */ 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hMap = CreateFileMapping(pShmNode->hFile.h, 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, PAGE_READWRITE, 0, nByte, NULL 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n", 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)GetCurrentProcessId(), pShmNode->nRegion, nByte, 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hMap ? "ok" : "failed")); 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( hMap ){ 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iOffset = pShmNode->nRegion*szRegion; 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pMap = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, iOffset - iOffsetShift, szRegion + iOffsetShift 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n", 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int)GetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion, 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pMap ? "ok" : "failed")); 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !pMap ){ 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->lastErrno = GetLastError(); 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = SQLITE_IOERR; 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( hMap ) CloseHandle(hMap); 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto shmpage_out; 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->aRegion[pShmNode->nRegion].pMap = pMap; 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->aRegion[pShmNode->nRegion].hMap = hMap; 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pShmNode->nRegion++; 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)shmpage_out: 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pShmNode->nRegion>iRegion ){ 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iOffset = iRegion*szRegion; 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p = (char *)pShmNode->aRegion[iRegion].pMap; 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pp = (void *)&p[iOffsetShift]; 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pp = 0; 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_mutex_leave(pShmNode->mutex); 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmMap 0 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmLock 0 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmBarrier 0 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmUnmap 0 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* #ifndef SQLITE_OMIT_WAL */ 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Here ends the implementation of all sqlite3_file methods. 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)********************** End sqlite3_file Methods ******************************* 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/ 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This vector defines all the methods that can operate on an 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_file for win32. 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods winIoMethod = { 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2, /* iVersion */ 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winClose, /* xClose */ 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winRead, /* xRead */ 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winWrite, /* xWrite */ 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winTruncate, /* xTruncate */ 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winSync, /* xSync */ 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFileSize, /* xFileSize */ 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winLock, /* xLock */ 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winUnlock, /* xUnlock */ 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winCheckReservedLock, /* xCheckReservedLock */ 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFileControl, /* xFileControl */ 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winSectorSize, /* xSectorSize */ 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winDeviceCharacteristics, /* xDeviceCharacteristics */ 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmMap, /* xShmMap */ 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmLock, /* xShmLock */ 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmBarrier, /* xShmBarrier */ 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winShmUnmap /* xShmUnmap */ 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**************************************************************************** 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**************************** sqlite3_vfs methods **************************** 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This division contains the implementation of methods on the 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_vfs object. 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert a UTF-8 filename into whatever form the underlying 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** operating system wants filenames in. Space to hold the result 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is obtained from malloc and must be freed by the calling 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** function. 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *convertUtf8Filename(const char *zFilename){ 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *zConverted = 0; 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zConverted = utf8ToUnicode(zFilename); 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zConverted = utf8ToMbcs(zFilename); 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* caller will handle out of memory */ 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return zConverted; 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Create a temporary file name in zBuf. zBuf must be big enough to 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** hold at pVfs->mxPathname characters. 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getTempname(int nBuf, char *zBuf){ 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static char zChars[] = 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "abcdefghijklmnopqrstuvwxyz" 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "0123456789"; 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t i, j; 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char zTempPath[MAX_PATH+1]; 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* It's odd to simulate an io-error here, but really this is just 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** using the io-error infrastructure to test that SQLite handles this 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** function failing. 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError( return SQLITE_IOERR ); 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sqlite3_temp_directory ){ 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else if( isNT() ){ 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zMulti; 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR zWidePath[MAX_PATH]; 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTempPathW(MAX_PATH-30, zWidePath); 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zMulti = unicodeToUtf8(zWidePath); 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zMulti ){ 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zMulti); 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE, 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds. 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zUtf8; 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char zMbcsPath[MAX_PATH]; 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetTempPathA(MAX_PATH-30, zMbcsPath); 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zUtf8 ){ 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zUtf8); 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check that the output buffer is large enough for the temporary file 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** name. If it is not, return SQLITE_ERROR. 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){ 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_ERROR; 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zTempPath[i] = 0; 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(nBuf-17, zBuf, 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = sqlite3Strlen30(zBuf); 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_randomness(15, &zBuf[j]); 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(i=0; i<15; i++, j++){ 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zBuf[j] = 0; 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("TEMP FILENAME: %s\n", zBuf)); 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The return value of getLastErrorMsg 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is zero if the error message fits in the buffer, or non-zero 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** otherwise (if the message was truncated). 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getLastErrorMsg(int nBuf, char *zBuf){ 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* FormatMessage returns 0 on failure. Otherwise it 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** returns the number of TCHARs written to the output 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** buffer, excluding the terminating null char. 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD error = GetLastError(); 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwLen = 0; 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zOut = 0; 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zTempWide = NULL; 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error, 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (LPWSTR) &zTempWide, 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( dwLen > 0 ){ 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* allocate a buffer and convert to UTF8 */ 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zOut = unicodeToUtf8(zTempWide); 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* free the system buffer allocated by FormatMessage */ 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(zTempWide); 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE, 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds. 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zTemp = NULL; 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error, 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (LPSTR) &zTemp, 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( dwLen > 0 ){ 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* allocate a buffer and convert to UTF8 */ 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zOut = sqlite3_win32_mbcs_to_utf8(zTemp); 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* free the system buffer allocated by FormatMessage */ 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocalFree(zTemp); 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( 0 == dwLen ){ 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* copy a maximum of nBuf chars to output buffer */ 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(nBuf, zBuf, "%s", zOut); 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* free the UTF8 buffer */ 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zOut); 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a file. 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winOpen( 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs *pVfs, /* Not used */ 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zName, /* Name of the file (UTF-8) */ 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_file *id, /* Write the SQLite file handle here */ 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, /* Open mode flags */ 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *pOutFlags /* Status return flags */ 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE h; 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwDesiredAccess; 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwShareMode; 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwCreationDisposition; 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwFlagsAndAttributes = 0; 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isTemp = 0; 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile *pFile = (winFile*)id; 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *zConverted; /* Filename in OS encoding */ 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If argument zPath is a NULL pointer, this function is required to open 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** a temporary file. Use this buffer to store the file name in. 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = SQLITE_OK; /* Function Return Code */ 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(NDEBUG) || SQLITE_OS_WINCE 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int eType = flags&0xFFFFFF00; /* Type of file to open */ 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isCreate = (flags & SQLITE_OPEN_CREATE); 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isReadonly = (flags & SQLITE_OPEN_READONLY); 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isReadWrite = (flags & SQLITE_OPEN_READWRITE); 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int isOpenJournal = (isCreate && ( 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eType==SQLITE_OPEN_MASTER_JOURNAL 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || eType==SQLITE_OPEN_MAIN_JOURNAL 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || eType==SQLITE_OPEN_WAL 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) )); 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check the following statements are true: 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** (a) Exactly one of the READWRITE and READONLY flags must be set, and 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** (b) if CREATE is set, then READWRITE must also be set, and 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** (c) if EXCLUSIVE is set, then CREATE must also be set. 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** (d) if DELETEONCLOSE is set, then CREATE must also be set. 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(isCreate==0 || isReadWrite); 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(isExclusive==0 || isCreate); 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(isDelete==0 || isCreate); 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The main DB, main journal, WAL file and master journal are never 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** automatically deleted. Nor are they ever temporary files. */ 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Assert that the upper layer has set one of the "file-type" flags. */ 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert( id!=0 ); 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->h = INVALID_HANDLE_VALUE; 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the second argument to this function is NULL, generate a 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** temporary file name to use 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !zUtf8Name ){ 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(isDelete && !isOpenJournal); 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = getTempname(MAX_PATH+1, zTmpname); 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc!=SQLITE_OK ){ 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zUtf8Name = zTmpname; 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Convert the filename to the system encoding. */ 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zConverted = convertUtf8Filename(zUtf8Name); 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zConverted==0 ){ 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isReadWrite ){ 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwDesiredAccess = GENERIC_READ; 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** created. SQLite doesn't use it to indicate "exclusive access" 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** as it is usually understood. 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isExclusive ){ 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Creates a new file, only if it does not already exist. */ 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the file exists, it fails. */ 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwCreationDisposition = CREATE_NEW; 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else if( isCreate ){ 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Open existing file, or create if it doesn't exist */ 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwCreationDisposition = OPEN_ALWAYS; 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Opens a file, only if it exists. */ 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwCreationDisposition = OPEN_EXISTING; 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isDelete ){ 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isTemp = 1; 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) | FILE_ATTRIBUTE_HIDDEN 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) | FILE_FLAG_DELETE_ON_CLOSE; 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Reports from the internet are that performance is always 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h = CreateFileW((WCHAR*)zConverted, 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwDesiredAccess, 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwShareMode, 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwCreationDisposition, 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlagsAndAttributes, 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE, 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds. 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h = CreateFileA((char*)zConverted, 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwDesiredAccess, 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwShareMode, 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwCreationDisposition, 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwFlagsAndAttributes, 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("OPEN %d %s 0x%lx %s\n", 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h, zName, dwDesiredAccess, 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h==INVALID_HANDLE_VALUE ? "failed" : "ok")); 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( h==INVALID_HANDLE_VALUE ){ 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = GetLastError(); 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isReadWrite ){ 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return winOpen(pVfs, zName, id, 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags); 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_CANTOPEN_BKPT; 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( pOutFlags ){ 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isReadWrite ){ 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pOutFlags = SQLITE_OPEN_READWRITE; 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pOutFlags = SQLITE_OPEN_READONLY; 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(pFile, 0, sizeof(*pFile)); 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->pMethod = &winIoMethod; 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->h = h; 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->lastErrno = NO_ERROR; 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->pVfs = pVfs; 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->pShm = 0; 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->zPath = zName; 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->sectorSize = getSectorSize(pVfs, zUtf8Name); 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && !winceCreateLock(zName, pFile) 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ){ 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(h); 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_CANTOPEN_BKPT; 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isTemp ){ 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pFile->zDeleteOnClose = zConverted; 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenCounter(+1); 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the named file. 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Note that windows does not allow a file to be deleted if some other 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** process has it open. Sometimes a virus scanner or indexing program 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will open a journal file shortly after it is created in order to do 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** whatever it does. While this other process is holding the 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file open, we will be unable to delete it. To work around this 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** problem, we delay 100 milliseconds and try to delete again. Up 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to MX_DELETION_ATTEMPTs deletion attempts are run before giving 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** up and returning an error. 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MX_DELETION_ATTEMPTS 5 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winDelete( 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs *pVfs, /* Not used on win32 */ 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zFilename, /* Name of file to delete */ 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int syncDir /* Not used on win32 */ 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cnt = 0; 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD rc; 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD error = 0; 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *zConverted; 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(syncDir); 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError(return SQLITE_IOERR_DELETE); 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zConverted = convertUtf8Filename(zFilename); 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zConverted==0 ){ 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do{ 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteFileW(zConverted); 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES) 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && (++cnt < MX_DELETION_ATTEMPTS) 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && (Sleep(100), 1) ); 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE, 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds. 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do{ 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteFileA(zConverted); 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES) 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && (++cnt < MX_DELETION_ATTEMPTS) 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && (Sleep(100), 1) ); 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSTRACE(("DELETE \"%s\" %s\n", zFilename, 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ? 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ok" : "failed" )); 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ( (rc == INVALID_FILE_ATTRIBUTES) 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE; 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Check the existance and status of a file. 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winAccess( 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs *pVfs, /* Not used on win32 */ 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zFilename, /* Name of file to check */ 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, /* Type of test to make on this file */ 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *pResOut /* OUT: Result */ 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD attr; 23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc = 0; 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *zConverted; 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError( return SQLITE_IOERR_ACCESS; ); 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zConverted = convertUtf8Filename(zFilename); 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zConverted==0 ){ 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WIN32_FILE_ATTRIBUTE_DATA sAttrData; 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&sAttrData, 0, sizeof(sAttrData)); 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( GetFileAttributesExW((WCHAR*)zConverted, 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFileExInfoStandard, 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &sAttrData) ){ 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** as if it does not exist. 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( flags==SQLITE_ACCESS_EXISTS 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && sAttrData.nFileSizeHigh==0 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && sAttrData.nFileSizeLow==0 ){ 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr = INVALID_FILE_ATTRIBUTES; 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr = sAttrData.dwFileAttributes; 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( GetLastError()!=ERROR_FILE_NOT_FOUND ){ 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOERR_ACCESS; 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr = INVALID_FILE_ATTRIBUTES; 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE, 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds. 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr = GetFileAttributesA((char*)zConverted); 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch( flags ){ 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_ACCESS_READ: 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_ACCESS_EXISTS: 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = attr!=INVALID_FILE_ATTRIBUTES; 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SQLITE_ACCESS_READWRITE: 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = (attr & FILE_ATTRIBUTE_READONLY)==0; 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!"Invalid flags argument"); 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pResOut = rc; 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Turn a relative pathname into a full pathname. Write the full 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes in size. 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winFullPathname( 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs *pVfs, /* Pointer to vfs object */ 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zRelative, /* Possibly relative input path */ 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nFull, /* Size of output buffer in bytes */ 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zFull /* Output buffer */ 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__CYGWIN__) 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError( return SQLITE_ERROR ); 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(nFull); 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cygwin_conv_to_full_win32_path(zRelative, zFull); 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError( return SQLITE_ERROR ); 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(nFull); 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* WinCE has no concept of a relative pathname, or so I am told. */ 24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !SQLITE_OS_WINCE && !defined(__CYGWIN__) 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nByte; 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *zConverted; 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zOut; 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* It's odd to simulate an io-error here, but really this is just 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** using the io-error infrastructure to test that SQLite handles this 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** function failing. This function could fail if, for example, the 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** current working directory has been unlinked. 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOError( return SQLITE_ERROR ); 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(nFull); 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zConverted = convertUtf8Filename(zRelative); 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *zTemp; 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zTemp = malloc( nByte*sizeof(zTemp[0]) ); 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zTemp==0 ){ 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zOut = unicodeToUtf8(zTemp); 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zTemp); 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE, 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds. 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *zTemp; 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zTemp = malloc( nByte*sizeof(zTemp[0]) ); 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zTemp==0 ){ 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zOut = sqlite3_win32_mbcs_to_utf8(zTemp); 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zTemp); 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zOut ){ 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zOut); 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_NOMEM; 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Get the sector size of the device used to store 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file. 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getSectorSize( 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs *pVfs, 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *zRelative /* UTF-8 file name */ 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){ 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* GetDiskFreeSpace is not supported under WINCE */ 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(zRelative); 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char zFullpath[MAX_PATH+1]; 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc; 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwRet = 0; 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD dwDummy; 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** We need to get the full path name of the file 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** to get the drive letter to look up the sector 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** size. 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(1); 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winFullPathname(pVfs, zRelative, MAX_PATH, zFullpath); 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SimulateIOErrorBenign(0); 24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( rc == SQLITE_OK ) 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *zConverted = convertUtf8Filename(zFullpath); 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zConverted ){ 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* trim path to just drive reference */ 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WCHAR *p = zConverted; 24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(;*p;p++){ 24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( *p == '\\' ){ 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '\0'; 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwRet = GetDiskFreeSpaceW((WCHAR*)zConverted, 25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dwDummy, 25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bytesPerSector, 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dwDummy, 25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dwDummy); 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* trim path to just drive reference */ 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p = (char *)zConverted; 25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for(;*p;p++){ 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( *p == '\\' ){ 25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '\0'; 25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dwRet = GetDiskFreeSpaceA((char*)zConverted, 25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dwDummy, 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &bytesPerSector, 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dwDummy, 25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &dwDummy); 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !dwRet ){ 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (int) bytesPerSector; 25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_LOAD_EXTENSION 25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Interfaces for opening a shared library, finding entry points 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** within the shared library, and closing the shared library. 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Interfaces for opening a shared library, finding entry points 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** within the shared library, and closing the shared library. 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE h; 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *zConverted = convertUtf8Filename(zFilename); 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( zConverted==0 ){ 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( isNT() ){ 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h = LoadLibraryW((WCHAR*)zConverted); 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE, 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds. 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }else{ 25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) h = LoadLibraryA((char*)zConverted); 25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(zConverted); 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (void*)h; 25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ 25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getLastErrorMsg(nBuf, zBufOut); 25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){ 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The GetProcAddressA() routine is only available on wince. */ 25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (void(*)(void))GetProcAddressA((HANDLE)pHandle, zSymbol); 25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* All other windows platforms expect GetProcAddress() to take 25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** an Ansi string regardless of the _UNICODE setting */ 25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (void(*)(void))GetProcAddress((HANDLE)pHandle, zSymbol); 25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ 25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FreeLibrary((HANDLE)pHandle); 25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define winDlOpen 0 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define winDlError 0 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define winDlSym 0 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define winDlClose 0 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write up to nBuf bytes of randomness into zBuf. 25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n = 0; 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SQLITE_TEST) 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n = nBuf; 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(zBuf, 0, nBuf); 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sizeof(SYSTEMTIME)<=nBuf-n ){ 26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEMTIME x; 26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSystemTime(&x); 26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&zBuf[n], &x, sizeof(x)); 26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n += sizeof(x); 26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sizeof(DWORD)<=nBuf-n ){ 26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD pid = GetCurrentProcessId(); 26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&zBuf[n], &pid, sizeof(pid)); 26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n += sizeof(pid); 26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sizeof(DWORD)<=nBuf-n ){ 26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD cnt = GetTickCount(); 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&zBuf[n], &cnt, sizeof(cnt)); 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n += sizeof(cnt); 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sizeof(LARGE_INTEGER)<=nBuf-n ){ 26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LARGE_INTEGER i; 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QueryPerformanceCounter(&i); 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&zBuf[n], &i, sizeof(i)); 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n += sizeof(i); 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return n; 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sleep for a little while. Return the amount of time slept. 26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winSleep(sqlite3_vfs *pVfs, int microsec){ 26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Sleep((microsec+999)/1000); 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((microsec+999)/1000)*1000; 26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following variable, if set to a non-zero value, is interpreted as 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the number of seconds since 1970 and is used to set the result of 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3OsCurrentTime() during testing. 26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST 26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ 26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Find the current time (in Universal Coordinated Time). Write into *piNow 26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the current time and date as a Julian Day number times 86_400_000. In 26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** other words, write into *piNow the number of milliseconds since the Julian 26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** epoch of noon in Greenwich on November 24, 4714 B.C according to the 26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** proleptic Gregorian calendar. 26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** On success, return 0. Return 1 if the time and date cannot be found. 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* FILETIME structure is a 64-bit value representing the number of 26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILETIME ft; 26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; 26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST 26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; 26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2^32 - to avoid use of LL and warnings in gcc */ 26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const sqlite3_int64 max32BitValue = 26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296; 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE 26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEMTIME time; 26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSystemTime(&time); 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if SystemTimeToFileTime() fails, it returns zero. */ 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SystemTimeToFileTime(&time,&ft)){ 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSystemTimeAsFileTime( &ft ); 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *piNow = winFiletimeEpoch + 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000; 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( sqlite3_current_time ){ 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Find the current time (in Universal Coordinated Time). Write the 26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** current time and date as a Julian Day number into *prNow and 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** return 0. Return 1 if the time and date cannot be found. 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc; 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_int64 i; 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = winCurrentTimeInt64(pVfs, &i); 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if( !rc ){ 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *prNow = i/86400000.0; 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The idea is that this function works like a combination of 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** GetLastError() and FormatMessage() on windows (or errno and 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** strerror_r() on unix). After an error is returned by an OS 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** function, SQLite calls this function with zBuf pointing to 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a buffer of nBuf bytes. The OS layer should populate the 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** buffer with a nul-terminated UTF-8 encoded error message 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** describing the last IO error to have occurred within the calling 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** thread. 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the error message is too large for the supplied buffer, 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it should be truncated. The return value of xGetLastError 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is zero if the error message fits in the buffer, or non-zero 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** otherwise (if the message was truncated). If non-zero is returned, 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** then it is not necessary to include the nul-terminator character 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the output buffer. 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Not supplying an error message will have no adverse effect 27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on SQLite. It is fine to have an implementation that never 27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returns an error message: 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ 27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** assert(zBuf[0]=='\0'); 27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** return 0; 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** } 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** However if an error message is supplied, it will be incorporated 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by sqlite into the error message available to the user using 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_errmsg(), possibly making IO errors easier to debug. 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNUSED_PARAMETER(pVfs); 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return getLastErrorMsg(nBuf, zBuf); 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Initialize and deinitialize the operating system interface. 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_init(void){ 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static sqlite3_vfs winVfs = { 27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3, /* iVersion */ 27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(winFile), /* szOsFile */ 27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAX_PATH, /* mxPathname */ 27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, /* pNext */ 27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "win32", /* zName */ 27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, /* pAppData */ 27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winOpen, /* xOpen */ 27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winDelete, /* xDelete */ 27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winAccess, /* xAccess */ 27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFullPathname, /* xFullPathname */ 27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winDlOpen, /* xDlOpen */ 27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winDlError, /* xDlError */ 27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winDlSym, /* xDlSym */ 27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winDlClose, /* xDlClose */ 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winRandomness, /* xRandomness */ 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winSleep, /* xSleep */ 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winCurrentTime, /* xCurrentTime */ 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winGetLastError, /* xGetLastError */ 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winCurrentTimeInt64, /* xCurrentTimeInt64 */ 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, /* xSetSystemCall */ 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, /* xGetSystemCall */ 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, /* xNextSystemCall */ 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_WAL 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* get memory map allocation granularity */ 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSystemInfo(&winSysInfo); 27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(winSysInfo.dwAllocationGranularity > 0); 27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sqlite3_vfs_register(&winVfs, 1); 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_end(void){ 27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void chromium_sqlite3_initialize_win_sqlite3_file(sqlite3_file* file, HANDLE handle) { 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winFile* winSQLite3File = (winFile*)file; 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(file, 0, sizeof(*file)); 27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winSQLite3File->pMethod = &winIoMethod; 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) winSQLite3File->h = handle; 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_WIN */ 2795