OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ** 2004 May 22 |
| 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: |
| 6 ** |
| 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. |
| 10 ** |
| 11 ****************************************************************************** |
| 12 ** |
| 13 ** This file contains code that is specific to windows. |
| 14 */ |
| 15 #include "sqliteInt.h" |
| 16 #if SQLITE_OS_WIN /* This file is used for windows only */ |
| 17 |
| 18 |
| 19 /* |
| 20 ** A Note About Memory Allocation: |
| 21 ** |
| 22 ** This driver uses malloc()/free() directly rather than going through |
| 23 ** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers |
| 24 ** are designed for use on embedded systems where memory is scarce and |
| 25 ** malloc failures happen frequently. Win32 does not typically run on |
| 26 ** embedded systems, and when it does the developers normally have bigger |
| 27 ** problems to worry about than running out of memory. So there is not |
| 28 ** a compelling need to use the wrappers. |
| 29 ** |
| 30 ** But there is a good reason to not use the wrappers. If we use the |
| 31 ** wrappers then we will get simulated malloc() failures within this |
| 32 ** driver. And that causes all kinds of problems for our tests. We |
| 33 ** could enhance SQLite to deal with simulated malloc failures within |
| 34 ** the OS driver, but the code to deal with those failure would not |
| 35 ** be exercised on Linux (which does not need to malloc() in the driver) |
| 36 ** and so we would have difficulty writing coverage tests for that |
| 37 ** code. Better to leave the code out, we think. |
| 38 ** |
| 39 ** The point of this discussion is as follows: When creating a new |
| 40 ** OS layer for an embedded system, if you use this file as an example, |
| 41 ** avoid the use of malloc()/free(). Those routines work ok on windows |
| 42 ** desktops but not so well in embedded systems. |
| 43 */ |
| 44 |
| 45 #include <winbase.h> |
| 46 |
| 47 #ifdef __CYGWIN__ |
| 48 # include <sys/cygwin.h> |
| 49 #endif |
| 50 |
| 51 /* |
| 52 ** Macros used to determine whether or not to use threads. |
| 53 */ |
| 54 #if defined(THREADSAFE) && THREADSAFE |
| 55 # define SQLITE_W32_THREADS 1 |
| 56 #endif |
| 57 |
| 58 /* |
| 59 ** Include code that is common to all os_*.c files |
| 60 */ |
| 61 #include "os_common.h" |
| 62 |
| 63 /* |
| 64 ** Some microsoft compilers lack this definition. |
| 65 */ |
| 66 #ifndef INVALID_FILE_ATTRIBUTES |
| 67 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) |
| 68 #endif |
| 69 |
| 70 /* |
| 71 ** Determine if we are dealing with WindowsCE - which has a much |
| 72 ** reduced API. |
| 73 */ |
| 74 #if SQLITE_OS_WINCE |
| 75 # define AreFileApisANSI() 1 |
| 76 # define FormatMessageW(a,b,c,d,e,f,g) 0 |
| 77 #endif |
| 78 |
| 79 /* Forward references */ |
| 80 typedef struct winShm winShm; /* A connection to shared-memory */ |
| 81 typedef struct winShmNode winShmNode; /* A region of shared-memory */ |
| 82 |
| 83 /* |
| 84 ** WinCE lacks native support for file locking so we have to fake it |
| 85 ** with some code of our own. |
| 86 */ |
| 87 #if SQLITE_OS_WINCE |
| 88 typedef struct winceLock { |
| 89 int nReaders; /* Number of reader locks obtained */ |
| 90 BOOL bPending; /* Indicates a pending lock has been obtained */ |
| 91 BOOL bReserved; /* Indicates a reserved lock has been obtained */ |
| 92 BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ |
| 93 } winceLock; |
| 94 #endif |
| 95 |
| 96 /* |
| 97 ** The winFile structure is a subclass of sqlite3_file* specific to the win32 |
| 98 ** portability layer. |
| 99 */ |
| 100 typedef struct winFile winFile; |
| 101 struct winFile { |
| 102 const sqlite3_io_methods *pMethod; /*** Must be first ***/ |
| 103 sqlite3_vfs *pVfs; /* The VFS used to open this file */ |
| 104 HANDLE h; /* Handle for accessing the file */ |
| 105 unsigned char locktype; /* Type of lock currently held on this file */ |
| 106 short sharedLockByte; /* Randomly chosen byte used as a shared lock */ |
| 107 DWORD lastErrno; /* The Windows errno from the last I/O error */ |
| 108 DWORD sectorSize; /* Sector size of the device file is on */ |
| 109 winShm *pShm; /* Instance of shared memory on this file */ |
| 110 const char *zPath; /* Full pathname of this file */ |
| 111 int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ |
| 112 #if SQLITE_OS_WINCE |
| 113 WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ |
| 114 HANDLE hMutex; /* Mutex used to control access to shared lock */ |
| 115 HANDLE hShared; /* Shared memory segment used for locking */ |
| 116 winceLock local; /* Locks obtained by this instance of winFile */ |
| 117 winceLock *shared; /* Global shared lock memory for the file */ |
| 118 #endif |
| 119 }; |
| 120 |
| 121 /* |
| 122 ** Forward prototypes. |
| 123 */ |
| 124 static int getSectorSize( |
| 125 sqlite3_vfs *pVfs, |
| 126 const char *zRelative /* UTF-8 file name */ |
| 127 ); |
| 128 |
| 129 /* |
| 130 ** The following variable is (normally) set once and never changes |
| 131 ** thereafter. It records whether the operating system is Win95 |
| 132 ** or WinNT. |
| 133 ** |
| 134 ** 0: Operating system unknown. |
| 135 ** 1: Operating system is Win95. |
| 136 ** 2: Operating system is WinNT. |
| 137 ** |
| 138 ** In order to facilitate testing on a WinNT system, the test fixture |
| 139 ** can manually set this value to 1 to emulate Win98 behavior. |
| 140 */ |
| 141 #ifdef SQLITE_TEST |
| 142 int sqlite3_os_type = 0; |
| 143 #else |
| 144 static int sqlite3_os_type = 0; |
| 145 #endif |
| 146 |
| 147 /* |
| 148 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, |
| 149 ** or WinCE. Return false (zero) for Win95, Win98, or WinME. |
| 150 ** |
| 151 ** Here is an interesting observation: Win95, Win98, and WinME lack |
| 152 ** the LockFileEx() API. But we can still statically link against that |
| 153 ** API as long as we don't call it when running Win95/98/ME. A call to |
| 154 ** this routine is used to determine if the host is Win95/98/ME or |
| 155 ** WinNT/2K/XP so that we will know whether or not we can safely call |
| 156 ** the LockFileEx() API. |
| 157 */ |
| 158 #if SQLITE_OS_WINCE |
| 159 # define isNT() (1) |
| 160 #else |
| 161 static int isNT(void){ |
| 162 if( sqlite3_os_type==0 ){ |
| 163 OSVERSIONINFO sInfo; |
| 164 sInfo.dwOSVersionInfoSize = sizeof(sInfo); |
| 165 GetVersionEx(&sInfo); |
| 166 sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; |
| 167 } |
| 168 return sqlite3_os_type==2; |
| 169 } |
| 170 #endif /* SQLITE_OS_WINCE */ |
| 171 |
| 172 /* |
| 173 ** Convert a UTF-8 string to microsoft unicode (UTF-16?). |
| 174 ** |
| 175 ** Space to hold the returned string is obtained from malloc. |
| 176 */ |
| 177 static WCHAR *utf8ToUnicode(const char *zFilename){ |
| 178 int nChar; |
| 179 WCHAR *zWideFilename; |
| 180 |
| 181 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); |
| 182 zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) ); |
| 183 if( zWideFilename==0 ){ |
| 184 return 0; |
| 185 } |
| 186 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); |
| 187 if( nChar==0 ){ |
| 188 free(zWideFilename); |
| 189 zWideFilename = 0; |
| 190 } |
| 191 return zWideFilename; |
| 192 } |
| 193 |
| 194 /* |
| 195 ** Convert microsoft unicode to UTF-8. Space to hold the returned string is |
| 196 ** obtained from malloc(). |
| 197 */ |
| 198 static char *unicodeToUtf8(const WCHAR *zWideFilename){ |
| 199 int nByte; |
| 200 char *zFilename; |
| 201 |
| 202 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); |
| 203 zFilename = malloc( nByte ); |
| 204 if( zFilename==0 ){ |
| 205 return 0; |
| 206 } |
| 207 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, |
| 208 0, 0); |
| 209 if( nByte == 0 ){ |
| 210 free(zFilename); |
| 211 zFilename = 0; |
| 212 } |
| 213 return zFilename; |
| 214 } |
| 215 |
| 216 /* |
| 217 ** Convert an ansi string to microsoft unicode, based on the |
| 218 ** current codepage settings for file apis. |
| 219 ** |
| 220 ** Space to hold the returned string is obtained |
| 221 ** from malloc. |
| 222 */ |
| 223 static WCHAR *mbcsToUnicode(const char *zFilename){ |
| 224 int nByte; |
| 225 WCHAR *zMbcsFilename; |
| 226 int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; |
| 227 |
| 228 nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); |
| 229 zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) ); |
| 230 if( zMbcsFilename==0 ){ |
| 231 return 0; |
| 232 } |
| 233 nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); |
| 234 if( nByte==0 ){ |
| 235 free(zMbcsFilename); |
| 236 zMbcsFilename = 0; |
| 237 } |
| 238 return zMbcsFilename; |
| 239 } |
| 240 |
| 241 /* |
| 242 ** Convert microsoft unicode to multibyte character string, based on the |
| 243 ** user's Ansi codepage. |
| 244 ** |
| 245 ** Space to hold the returned string is obtained from |
| 246 ** malloc(). |
| 247 */ |
| 248 static char *unicodeToMbcs(const WCHAR *zWideFilename){ |
| 249 int nByte; |
| 250 char *zFilename; |
| 251 int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; |
| 252 |
| 253 nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); |
| 254 zFilename = malloc( nByte ); |
| 255 if( zFilename==0 ){ |
| 256 return 0; |
| 257 } |
| 258 nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, |
| 259 0, 0); |
| 260 if( nByte == 0 ){ |
| 261 free(zFilename); |
| 262 zFilename = 0; |
| 263 } |
| 264 return zFilename; |
| 265 } |
| 266 |
| 267 /* |
| 268 ** Convert multibyte character string to UTF-8. Space to hold the |
| 269 ** returned string is obtained from malloc(). |
| 270 */ |
| 271 char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ |
| 272 char *zFilenameUtf8; |
| 273 WCHAR *zTmpWide; |
| 274 |
| 275 zTmpWide = mbcsToUnicode(zFilename); |
| 276 if( zTmpWide==0 ){ |
| 277 return 0; |
| 278 } |
| 279 zFilenameUtf8 = unicodeToUtf8(zTmpWide); |
| 280 free(zTmpWide); |
| 281 return zFilenameUtf8; |
| 282 } |
| 283 |
| 284 /* |
| 285 ** Convert UTF-8 to multibyte character string. Space to hold the |
| 286 ** returned string is obtained from malloc(). |
| 287 */ |
| 288 static char *utf8ToMbcs(const char *zFilename){ |
| 289 char *zFilenameMbcs; |
| 290 WCHAR *zTmpWide; |
| 291 |
| 292 zTmpWide = utf8ToUnicode(zFilename); |
| 293 if( zTmpWide==0 ){ |
| 294 return 0; |
| 295 } |
| 296 zFilenameMbcs = unicodeToMbcs(zTmpWide); |
| 297 free(zTmpWide); |
| 298 return zFilenameMbcs; |
| 299 } |
| 300 |
| 301 #if SQLITE_OS_WINCE |
| 302 /************************************************************************* |
| 303 ** This section contains code for WinCE only. |
| 304 */ |
| 305 /* |
| 306 ** WindowsCE does not have a localtime() function. So create a |
| 307 ** substitute. |
| 308 */ |
| 309 #include <time.h> |
| 310 struct tm *__cdecl localtime(const time_t *t) |
| 311 { |
| 312 static struct tm y; |
| 313 FILETIME uTm, lTm; |
| 314 SYSTEMTIME pTm; |
| 315 sqlite3_int64 t64; |
| 316 t64 = *t; |
| 317 t64 = (t64 + 11644473600)*10000000; |
| 318 uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); |
| 319 uTm.dwHighDateTime= (DWORD)(t64 >> 32); |
| 320 FileTimeToLocalFileTime(&uTm,&lTm); |
| 321 FileTimeToSystemTime(&lTm,&pTm); |
| 322 y.tm_year = pTm.wYear - 1900; |
| 323 y.tm_mon = pTm.wMonth - 1; |
| 324 y.tm_wday = pTm.wDayOfWeek; |
| 325 y.tm_mday = pTm.wDay; |
| 326 y.tm_hour = pTm.wHour; |
| 327 y.tm_min = pTm.wMinute; |
| 328 y.tm_sec = pTm.wSecond; |
| 329 return &y; |
| 330 } |
| 331 |
| 332 /* This will never be called, but defined to make the code compile */ |
| 333 #define GetTempPathA(a,b) |
| 334 |
| 335 #define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) |
| 336 #define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) |
| 337 #define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) |
| 338 |
| 339 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] |
| 340 |
| 341 /* |
| 342 ** Acquire a lock on the handle h |
| 343 */ |
| 344 static void winceMutexAcquire(HANDLE h){ |
| 345 DWORD dwErr; |
| 346 do { |
| 347 dwErr = WaitForSingleObject(h, INFINITE); |
| 348 } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); |
| 349 } |
| 350 /* |
| 351 ** Release a lock acquired by winceMutexAcquire() |
| 352 */ |
| 353 #define winceMutexRelease(h) ReleaseMutex(h) |
| 354 |
| 355 /* |
| 356 ** Create the mutex and shared memory used for locking in the file |
| 357 ** descriptor pFile |
| 358 */ |
| 359 static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ |
| 360 WCHAR *zTok; |
| 361 WCHAR *zName = utf8ToUnicode(zFilename); |
| 362 BOOL bInit = TRUE; |
| 363 |
| 364 /* Initialize the local lockdata */ |
| 365 ZeroMemory(&pFile->local, sizeof(pFile->local)); |
| 366 |
| 367 /* Replace the backslashes from the filename and lowercase it |
| 368 ** to derive a mutex name. */ |
| 369 zTok = CharLowerW(zName); |
| 370 for (;*zTok;zTok++){ |
| 371 if (*zTok == '\\') *zTok = '_'; |
| 372 } |
| 373 |
| 374 /* Create/open the named mutex */ |
| 375 pFile->hMutex = CreateMutexW(NULL, FALSE, zName); |
| 376 if (!pFile->hMutex){ |
| 377 pFile->lastErrno = GetLastError(); |
| 378 free(zName); |
| 379 return FALSE; |
| 380 } |
| 381 |
| 382 /* Acquire the mutex before continuing */ |
| 383 winceMutexAcquire(pFile->hMutex); |
| 384 |
| 385 /* Since the names of named mutexes, semaphores, file mappings etc are |
| 386 ** case-sensitive, take advantage of that by uppercasing the mutex name |
| 387 ** and using that as the shared filemapping name. |
| 388 */ |
| 389 CharUpperW(zName); |
| 390 pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, |
| 391 PAGE_READWRITE, 0, sizeof(winceLock), |
| 392 zName); |
| 393 |
| 394 /* Set a flag that indicates we're the first to create the memory so it |
| 395 ** must be zero-initialized */ |
| 396 if (GetLastError() == ERROR_ALREADY_EXISTS){ |
| 397 bInit = FALSE; |
| 398 } |
| 399 |
| 400 free(zName); |
| 401 |
| 402 /* If we succeeded in making the shared memory handle, map it. */ |
| 403 if (pFile->hShared){ |
| 404 pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, |
| 405 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); |
| 406 /* If mapping failed, close the shared memory handle and erase it */ |
| 407 if (!pFile->shared){ |
| 408 pFile->lastErrno = GetLastError(); |
| 409 CloseHandle(pFile->hShared); |
| 410 pFile->hShared = NULL; |
| 411 } |
| 412 } |
| 413 |
| 414 /* If shared memory could not be created, then close the mutex and fail */ |
| 415 if (pFile->hShared == NULL){ |
| 416 winceMutexRelease(pFile->hMutex); |
| 417 CloseHandle(pFile->hMutex); |
| 418 pFile->hMutex = NULL; |
| 419 return FALSE; |
| 420 } |
| 421 |
| 422 /* Initialize the shared memory if we're supposed to */ |
| 423 if (bInit) { |
| 424 ZeroMemory(pFile->shared, sizeof(winceLock)); |
| 425 } |
| 426 |
| 427 winceMutexRelease(pFile->hMutex); |
| 428 return TRUE; |
| 429 } |
| 430 |
| 431 /* |
| 432 ** Destroy the part of winFile that deals with wince locks |
| 433 */ |
| 434 static void winceDestroyLock(winFile *pFile){ |
| 435 if (pFile->hMutex){ |
| 436 /* Acquire the mutex */ |
| 437 winceMutexAcquire(pFile->hMutex); |
| 438 |
| 439 /* The following blocks should probably assert in debug mode, but they |
| 440 are to cleanup in case any locks remained open */ |
| 441 if (pFile->local.nReaders){ |
| 442 pFile->shared->nReaders --; |
| 443 } |
| 444 if (pFile->local.bReserved){ |
| 445 pFile->shared->bReserved = FALSE; |
| 446 } |
| 447 if (pFile->local.bPending){ |
| 448 pFile->shared->bPending = FALSE; |
| 449 } |
| 450 if (pFile->local.bExclusive){ |
| 451 pFile->shared->bExclusive = FALSE; |
| 452 } |
| 453 |
| 454 /* De-reference and close our copy of the shared memory handle */ |
| 455 UnmapViewOfFile(pFile->shared); |
| 456 CloseHandle(pFile->hShared); |
| 457 |
| 458 /* Done with the mutex */ |
| 459 winceMutexRelease(pFile->hMutex); |
| 460 CloseHandle(pFile->hMutex); |
| 461 pFile->hMutex = NULL; |
| 462 } |
| 463 } |
| 464 |
| 465 /* |
| 466 ** An implementation of the LockFile() API of windows for wince |
| 467 */ |
| 468 static BOOL winceLockFile( |
| 469 HANDLE *phFile, |
| 470 DWORD dwFileOffsetLow, |
| 471 DWORD dwFileOffsetHigh, |
| 472 DWORD nNumberOfBytesToLockLow, |
| 473 DWORD nNumberOfBytesToLockHigh |
| 474 ){ |
| 475 winFile *pFile = HANDLE_TO_WINFILE(phFile); |
| 476 BOOL bReturn = FALSE; |
| 477 |
| 478 UNUSED_PARAMETER(dwFileOffsetHigh); |
| 479 UNUSED_PARAMETER(nNumberOfBytesToLockHigh); |
| 480 |
| 481 if (!pFile->hMutex) return TRUE; |
| 482 winceMutexAcquire(pFile->hMutex); |
| 483 |
| 484 /* Wanting an exclusive lock? */ |
| 485 if (dwFileOffsetLow == (DWORD)SHARED_FIRST |
| 486 && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ |
| 487 if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ |
| 488 pFile->shared->bExclusive = TRUE; |
| 489 pFile->local.bExclusive = TRUE; |
| 490 bReturn = TRUE; |
| 491 } |
| 492 } |
| 493 |
| 494 /* Want a read-only lock? */ |
| 495 else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && |
| 496 nNumberOfBytesToLockLow == 1){ |
| 497 if (pFile->shared->bExclusive == 0){ |
| 498 pFile->local.nReaders ++; |
| 499 if (pFile->local.nReaders == 1){ |
| 500 pFile->shared->nReaders ++; |
| 501 } |
| 502 bReturn = TRUE; |
| 503 } |
| 504 } |
| 505 |
| 506 /* Want a pending lock? */ |
| 507 else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow ==
1){ |
| 508 /* If no pending lock has been acquired, then acquire it */ |
| 509 if (pFile->shared->bPending == 0) { |
| 510 pFile->shared->bPending = TRUE; |
| 511 pFile->local.bPending = TRUE; |
| 512 bReturn = TRUE; |
| 513 } |
| 514 } |
| 515 |
| 516 /* Want a reserved lock? */ |
| 517 else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow ==
1){ |
| 518 if (pFile->shared->bReserved == 0) { |
| 519 pFile->shared->bReserved = TRUE; |
| 520 pFile->local.bReserved = TRUE; |
| 521 bReturn = TRUE; |
| 522 } |
| 523 } |
| 524 |
| 525 winceMutexRelease(pFile->hMutex); |
| 526 return bReturn; |
| 527 } |
| 528 |
| 529 /* |
| 530 ** An implementation of the UnlockFile API of windows for wince |
| 531 */ |
| 532 static BOOL winceUnlockFile( |
| 533 HANDLE *phFile, |
| 534 DWORD dwFileOffsetLow, |
| 535 DWORD dwFileOffsetHigh, |
| 536 DWORD nNumberOfBytesToUnlockLow, |
| 537 DWORD nNumberOfBytesToUnlockHigh |
| 538 ){ |
| 539 winFile *pFile = HANDLE_TO_WINFILE(phFile); |
| 540 BOOL bReturn = FALSE; |
| 541 |
| 542 UNUSED_PARAMETER(dwFileOffsetHigh); |
| 543 UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); |
| 544 |
| 545 if (!pFile->hMutex) return TRUE; |
| 546 winceMutexAcquire(pFile->hMutex); |
| 547 |
| 548 /* Releasing a reader lock or an exclusive lock */ |
| 549 if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ |
| 550 /* Did we have an exclusive lock? */ |
| 551 if (pFile->local.bExclusive){ |
| 552 assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); |
| 553 pFile->local.bExclusive = FALSE; |
| 554 pFile->shared->bExclusive = FALSE; |
| 555 bReturn = TRUE; |
| 556 } |
| 557 |
| 558 /* Did we just have a reader lock? */ |
| 559 else if (pFile->local.nReaders){ |
| 560 assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesTo
UnlockLow == 1); |
| 561 pFile->local.nReaders --; |
| 562 if (pFile->local.nReaders == 0) |
| 563 { |
| 564 pFile->shared->nReaders --; |
| 565 } |
| 566 bReturn = TRUE; |
| 567 } |
| 568 } |
| 569 |
| 570 /* Releasing a pending lock */ |
| 571 else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow =
= 1){ |
| 572 if (pFile->local.bPending){ |
| 573 pFile->local.bPending = FALSE; |
| 574 pFile->shared->bPending = FALSE; |
| 575 bReturn = TRUE; |
| 576 } |
| 577 } |
| 578 /* Releasing a reserved lock */ |
| 579 else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow
== 1){ |
| 580 if (pFile->local.bReserved) { |
| 581 pFile->local.bReserved = FALSE; |
| 582 pFile->shared->bReserved = FALSE; |
| 583 bReturn = TRUE; |
| 584 } |
| 585 } |
| 586 |
| 587 winceMutexRelease(pFile->hMutex); |
| 588 return bReturn; |
| 589 } |
| 590 |
| 591 /* |
| 592 ** An implementation of the LockFileEx() API of windows for wince |
| 593 */ |
| 594 static BOOL winceLockFileEx( |
| 595 HANDLE *phFile, |
| 596 DWORD dwFlags, |
| 597 DWORD dwReserved, |
| 598 DWORD nNumberOfBytesToLockLow, |
| 599 DWORD nNumberOfBytesToLockHigh, |
| 600 LPOVERLAPPED lpOverlapped |
| 601 ){ |
| 602 UNUSED_PARAMETER(dwReserved); |
| 603 UNUSED_PARAMETER(nNumberOfBytesToLockHigh); |
| 604 |
| 605 /* If the caller wants a shared read lock, forward this call |
| 606 ** to winceLockFile */ |
| 607 if (lpOverlapped->Offset == (DWORD)SHARED_FIRST && |
| 608 dwFlags == 1 && |
| 609 nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ |
| 610 return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); |
| 611 } |
| 612 return FALSE; |
| 613 } |
| 614 /* |
| 615 ** End of the special code for wince |
| 616 *****************************************************************************/ |
| 617 #endif /* SQLITE_OS_WINCE */ |
| 618 |
| 619 /***************************************************************************** |
| 620 ** The next group of routines implement the I/O methods specified |
| 621 ** by the sqlite3_io_methods object. |
| 622 ******************************************************************************/ |
| 623 |
| 624 /* |
| 625 ** Some microsoft compilers lack this definition. |
| 626 */ |
| 627 #ifndef INVALID_SET_FILE_POINTER |
| 628 # define INVALID_SET_FILE_POINTER ((DWORD)-1) |
| 629 #endif |
| 630 |
| 631 /* |
| 632 ** Move the current position of the file handle passed as the first |
| 633 ** argument to offset iOffset within the file. If successful, return 0. |
| 634 ** Otherwise, set pFile->lastErrno and return non-zero. |
| 635 */ |
| 636 static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){ |
| 637 LONG upperBits; /* Most sig. 32 bits of new offset */ |
| 638 LONG lowerBits; /* Least sig. 32 bits of new offset */ |
| 639 DWORD dwRet; /* Value returned by SetFilePointer() */ |
| 640 |
| 641 upperBits = (LONG)((iOffset>>32) & 0x7fffffff); |
| 642 lowerBits = (LONG)(iOffset & 0xffffffff); |
| 643 |
| 644 /* API oddity: If successful, SetFilePointer() returns a dword |
| 645 ** containing the lower 32-bits of the new file-offset. Or, if it fails, |
| 646 ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, |
| 647 ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine |
| 648 ** whether an error has actually occured, it is also necessary to call |
| 649 ** GetLastError(). |
| 650 */ |
| 651 dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); |
| 652 if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){ |
| 653 pFile->lastErrno = GetLastError(); |
| 654 return 1; |
| 655 } |
| 656 |
| 657 return 0; |
| 658 } |
| 659 |
| 660 /* |
| 661 ** Close a file. |
| 662 ** |
| 663 ** It is reported that an attempt to close a handle might sometimes |
| 664 ** fail. This is a very unreasonable result, but windows is notorious |
| 665 ** for being unreasonable so I do not doubt that it might happen. If |
| 666 ** the close fails, we pause for 100 milliseconds and try again. As |
| 667 ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before |
| 668 ** giving up and returning an error. |
| 669 */ |
| 670 #define MX_CLOSE_ATTEMPT 3 |
| 671 static int winClose(sqlite3_file *id){ |
| 672 int rc, cnt = 0; |
| 673 winFile *pFile = (winFile*)id; |
| 674 |
| 675 assert( id!=0 ); |
| 676 assert( pFile->pShm==0 ); |
| 677 OSTRACE(("CLOSE %d\n", pFile->h)); |
| 678 do{ |
| 679 rc = CloseHandle(pFile->h); |
| 680 /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ |
| 681 }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); |
| 682 #if SQLITE_OS_WINCE |
| 683 #define WINCE_DELETION_ATTEMPTS 3 |
| 684 winceDestroyLock(pFile); |
| 685 if( pFile->zDeleteOnClose ){ |
| 686 int cnt = 0; |
| 687 while( |
| 688 DeleteFileW(pFile->zDeleteOnClose)==0 |
| 689 && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff |
| 690 && cnt++ < WINCE_DELETION_ATTEMPTS |
| 691 ){ |
| 692 Sleep(100); /* Wait a little before trying again */ |
| 693 } |
| 694 free(pFile->zDeleteOnClose); |
| 695 } |
| 696 #endif |
| 697 OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed")); |
| 698 OpenCounter(-1); |
| 699 return rc ? SQLITE_OK : SQLITE_IOERR; |
| 700 } |
| 701 |
| 702 /* |
| 703 ** Read data from a file into a buffer. Return SQLITE_OK if all |
| 704 ** bytes were read successfully and SQLITE_IOERR if anything goes |
| 705 ** wrong. |
| 706 */ |
| 707 static int winRead( |
| 708 sqlite3_file *id, /* File to read from */ |
| 709 void *pBuf, /* Write content into this buffer */ |
| 710 int amt, /* Number of bytes to read */ |
| 711 sqlite3_int64 offset /* Begin reading at this offset */ |
| 712 ){ |
| 713 winFile *pFile = (winFile*)id; /* file handle */ |
| 714 DWORD nRead; /* Number of bytes actually read from file */ |
| 715 |
| 716 assert( id!=0 ); |
| 717 SimulateIOError(return SQLITE_IOERR_READ); |
| 718 OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype)); |
| 719 |
| 720 if( seekWinFile(pFile, offset) ){ |
| 721 return SQLITE_FULL; |
| 722 } |
| 723 if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ |
| 724 pFile->lastErrno = GetLastError(); |
| 725 return SQLITE_IOERR_READ; |
| 726 } |
| 727 if( nRead<(DWORD)amt ){ |
| 728 /* Unread parts of the buffer must be zero-filled */ |
| 729 memset(&((char*)pBuf)[nRead], 0, amt-nRead); |
| 730 return SQLITE_IOERR_SHORT_READ; |
| 731 } |
| 732 |
| 733 return SQLITE_OK; |
| 734 } |
| 735 |
| 736 /* |
| 737 ** Write data from a buffer into a file. Return SQLITE_OK on success |
| 738 ** or some other error code on failure. |
| 739 */ |
| 740 static int winWrite( |
| 741 sqlite3_file *id, /* File to write into */ |
| 742 const void *pBuf, /* The bytes to be written */ |
| 743 int amt, /* Number of bytes to write */ |
| 744 sqlite3_int64 offset /* Offset into the file to begin writing at */ |
| 745 ){ |
| 746 int rc; /* True if error has occured, else false */ |
| 747 winFile *pFile = (winFile*)id; /* File handle */ |
| 748 |
| 749 assert( amt>0 ); |
| 750 assert( pFile ); |
| 751 SimulateIOError(return SQLITE_IOERR_WRITE); |
| 752 SimulateDiskfullError(return SQLITE_FULL); |
| 753 |
| 754 OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype)); |
| 755 |
| 756 rc = seekWinFile(pFile, offset); |
| 757 if( rc==0 ){ |
| 758 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ |
| 759 int nRem = amt; /* Number of bytes yet to be written */ |
| 760 DWORD nWrite; /* Bytes written by each WriteFile() call */ |
| 761 |
| 762 while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){ |
| 763 aRem += nWrite; |
| 764 nRem -= nWrite; |
| 765 } |
| 766 if( nRem>0 ){ |
| 767 pFile->lastErrno = GetLastError(); |
| 768 rc = 1; |
| 769 } |
| 770 } |
| 771 |
| 772 if( rc ){ |
| 773 if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){ |
| 774 return SQLITE_FULL; |
| 775 } |
| 776 return SQLITE_IOERR_WRITE; |
| 777 } |
| 778 return SQLITE_OK; |
| 779 } |
| 780 |
| 781 /* |
| 782 ** Truncate an open file to a specified size |
| 783 */ |
| 784 static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ |
| 785 winFile *pFile = (winFile*)id; /* File handle object */ |
| 786 int rc = SQLITE_OK; /* Return code for this function */ |
| 787 |
| 788 assert( pFile ); |
| 789 |
| 790 OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte)); |
| 791 SimulateIOError(return SQLITE_IOERR_TRUNCATE); |
| 792 |
| 793 /* If the user has configured a chunk-size for this file, truncate the |
| 794 ** file so that it consists of an integer number of chunks (i.e. the |
| 795 ** actual file size after the operation may be larger than the requested |
| 796 ** size). |
| 797 */ |
| 798 if( pFile->szChunk ){ |
| 799 nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; |
| 800 } |
| 801 |
| 802 /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ |
| 803 if( seekWinFile(pFile, nByte) ){ |
| 804 rc = SQLITE_IOERR_TRUNCATE; |
| 805 }else if( 0==SetEndOfFile(pFile->h) ){ |
| 806 pFile->lastErrno = GetLastError(); |
| 807 rc = SQLITE_IOERR_TRUNCATE; |
| 808 } |
| 809 |
| 810 OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok")); |
| 811 return rc; |
| 812 } |
| 813 |
| 814 #ifdef SQLITE_TEST |
| 815 /* |
| 816 ** Count the number of fullsyncs and normal syncs. This is used to test |
| 817 ** that syncs and fullsyncs are occuring at the right times. |
| 818 */ |
| 819 int sqlite3_sync_count = 0; |
| 820 int sqlite3_fullsync_count = 0; |
| 821 #endif |
| 822 |
| 823 /* |
| 824 ** Make sure all writes to a particular file are committed to disk. |
| 825 */ |
| 826 static int winSync(sqlite3_file *id, int flags){ |
| 827 #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG) |
| 828 winFile *pFile = (winFile*)id; |
| 829 #else |
| 830 UNUSED_PARAMETER(id); |
| 831 #endif |
| 832 |
| 833 assert( pFile ); |
| 834 /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ |
| 835 assert((flags&0x0F)==SQLITE_SYNC_NORMAL |
| 836 || (flags&0x0F)==SQLITE_SYNC_FULL |
| 837 ); |
| 838 |
| 839 OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype)); |
| 840 |
| 841 #ifndef SQLITE_TEST |
| 842 UNUSED_PARAMETER(flags); |
| 843 #else |
| 844 if( flags & SQLITE_SYNC_FULL ){ |
| 845 sqlite3_fullsync_count++; |
| 846 } |
| 847 sqlite3_sync_count++; |
| 848 #endif |
| 849 |
| 850 /* Unix cannot, but some systems may return SQLITE_FULL from here. This |
| 851 ** line is to test that doing so does not cause any problems. |
| 852 */ |
| 853 SimulateDiskfullError( return SQLITE_FULL ); |
| 854 SimulateIOError( return SQLITE_IOERR; ); |
| 855 |
| 856 /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a |
| 857 ** no-op |
| 858 */ |
| 859 #ifdef SQLITE_NO_SYNC |
| 860 return SQLITE_OK; |
| 861 #else |
| 862 if( FlushFileBuffers(pFile->h) ){ |
| 863 return SQLITE_OK; |
| 864 }else{ |
| 865 pFile->lastErrno = GetLastError(); |
| 866 return SQLITE_IOERR; |
| 867 } |
| 868 #endif |
| 869 } |
| 870 |
| 871 /* |
| 872 ** Determine the current size of a file in bytes |
| 873 */ |
| 874 static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ |
| 875 DWORD upperBits; |
| 876 DWORD lowerBits; |
| 877 winFile *pFile = (winFile*)id; |
| 878 DWORD error; |
| 879 |
| 880 assert( id!=0 ); |
| 881 SimulateIOError(return SQLITE_IOERR_FSTAT); |
| 882 lowerBits = GetFileSize(pFile->h, &upperBits); |
| 883 if( (lowerBits == INVALID_FILE_SIZE) |
| 884 && ((error = GetLastError()) != NO_ERROR) ) |
| 885 { |
| 886 pFile->lastErrno = error; |
| 887 return SQLITE_IOERR_FSTAT; |
| 888 } |
| 889 *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; |
| 890 return SQLITE_OK; |
| 891 } |
| 892 |
| 893 /* |
| 894 ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. |
| 895 */ |
| 896 #ifndef LOCKFILE_FAIL_IMMEDIATELY |
| 897 # define LOCKFILE_FAIL_IMMEDIATELY 1 |
| 898 #endif |
| 899 |
| 900 /* |
| 901 ** Acquire a reader lock. |
| 902 ** Different API routines are called depending on whether or not this |
| 903 ** is Win95 or WinNT. |
| 904 */ |
| 905 static int getReadLock(winFile *pFile){ |
| 906 int res; |
| 907 if( isNT() ){ |
| 908 OVERLAPPED ovlp; |
| 909 ovlp.Offset = SHARED_FIRST; |
| 910 ovlp.OffsetHigh = 0; |
| 911 ovlp.hEvent = 0; |
| 912 res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, |
| 913 0, SHARED_SIZE, 0, &ovlp); |
| 914 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 915 */ |
| 916 #if SQLITE_OS_WINCE==0 |
| 917 }else{ |
| 918 int lk; |
| 919 sqlite3_randomness(sizeof(lk), &lk); |
| 920 pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); |
| 921 res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); |
| 922 #endif |
| 923 } |
| 924 if( res == 0 ){ |
| 925 pFile->lastErrno = GetLastError(); |
| 926 } |
| 927 return res; |
| 928 } |
| 929 |
| 930 /* |
| 931 ** Undo a readlock |
| 932 */ |
| 933 static int unlockReadLock(winFile *pFile){ |
| 934 int res; |
| 935 if( isNT() ){ |
| 936 res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |
| 937 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 938 */ |
| 939 #if SQLITE_OS_WINCE==0 |
| 940 }else{ |
| 941 res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); |
| 942 #endif |
| 943 } |
| 944 if( res == 0 ){ |
| 945 pFile->lastErrno = GetLastError(); |
| 946 } |
| 947 return res; |
| 948 } |
| 949 |
| 950 /* |
| 951 ** Lock the file with the lock specified by parameter locktype - one |
| 952 ** of the following: |
| 953 ** |
| 954 ** (1) SHARED_LOCK |
| 955 ** (2) RESERVED_LOCK |
| 956 ** (3) PENDING_LOCK |
| 957 ** (4) EXCLUSIVE_LOCK |
| 958 ** |
| 959 ** Sometimes when requesting one lock state, additional lock states |
| 960 ** are inserted in between. The locking might fail on one of the later |
| 961 ** transitions leaving the lock state different from what it started but |
| 962 ** still short of its goal. The following chart shows the allowed |
| 963 ** transitions and the inserted intermediate states: |
| 964 ** |
| 965 ** UNLOCKED -> SHARED |
| 966 ** SHARED -> RESERVED |
| 967 ** SHARED -> (PENDING) -> EXCLUSIVE |
| 968 ** RESERVED -> (PENDING) -> EXCLUSIVE |
| 969 ** PENDING -> EXCLUSIVE |
| 970 ** |
| 971 ** This routine will only increase a lock. The winUnlock() routine |
| 972 ** erases all locks at once and returns us immediately to locking level 0. |
| 973 ** It is not possible to lower the locking level one step at a time. You |
| 974 ** must go straight to locking level 0. |
| 975 */ |
| 976 static int winLock(sqlite3_file *id, int locktype){ |
| 977 int rc = SQLITE_OK; /* Return code from subroutines */ |
| 978 int res = 1; /* Result of a windows lock call */ |
| 979 int newLocktype; /* Set pFile->locktype to this value before exiting */ |
| 980 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ |
| 981 winFile *pFile = (winFile*)id; |
| 982 DWORD error = NO_ERROR; |
| 983 |
| 984 assert( id!=0 ); |
| 985 OSTRACE(("LOCK %d %d was %d(%d)\n", |
| 986 pFile->h, locktype, pFile->locktype, pFile->sharedLockByte)); |
| 987 |
| 988 /* If there is already a lock of this type or more restrictive on the |
| 989 ** OsFile, do nothing. Don't use the end_lock: exit path, as |
| 990 ** sqlite3OsEnterMutex() hasn't been called yet. |
| 991 */ |
| 992 if( pFile->locktype>=locktype ){ |
| 993 return SQLITE_OK; |
| 994 } |
| 995 |
| 996 /* Make sure the locking sequence is correct |
| 997 */ |
| 998 assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); |
| 999 assert( locktype!=PENDING_LOCK ); |
| 1000 assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); |
| 1001 |
| 1002 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or |
| 1003 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of |
| 1004 ** the PENDING_LOCK byte is temporary. |
| 1005 */ |
| 1006 newLocktype = pFile->locktype; |
| 1007 if( (pFile->locktype==NO_LOCK) |
| 1008 || ( (locktype==EXCLUSIVE_LOCK) |
| 1009 && (pFile->locktype==RESERVED_LOCK)) |
| 1010 ){ |
| 1011 int cnt = 3; |
| 1012 while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ |
| 1013 /* Try 3 times to get the pending lock. The pending lock might be |
| 1014 ** held by another reader process who will release it momentarily. |
| 1015 */ |
| 1016 OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt)); |
| 1017 Sleep(1); |
| 1018 } |
| 1019 gotPendingLock = res; |
| 1020 if( !res ){ |
| 1021 error = GetLastError(); |
| 1022 } |
| 1023 } |
| 1024 |
| 1025 /* Acquire a shared lock |
| 1026 */ |
| 1027 if( locktype==SHARED_LOCK && res ){ |
| 1028 assert( pFile->locktype==NO_LOCK ); |
| 1029 res = getReadLock(pFile); |
| 1030 if( res ){ |
| 1031 newLocktype = SHARED_LOCK; |
| 1032 }else{ |
| 1033 error = GetLastError(); |
| 1034 } |
| 1035 } |
| 1036 |
| 1037 /* Acquire a RESERVED lock |
| 1038 */ |
| 1039 if( locktype==RESERVED_LOCK && res ){ |
| 1040 assert( pFile->locktype==SHARED_LOCK ); |
| 1041 res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |
| 1042 if( res ){ |
| 1043 newLocktype = RESERVED_LOCK; |
| 1044 }else{ |
| 1045 error = GetLastError(); |
| 1046 } |
| 1047 } |
| 1048 |
| 1049 /* Acquire a PENDING lock |
| 1050 */ |
| 1051 if( locktype==EXCLUSIVE_LOCK && res ){ |
| 1052 newLocktype = PENDING_LOCK; |
| 1053 gotPendingLock = 0; |
| 1054 } |
| 1055 |
| 1056 /* Acquire an EXCLUSIVE lock |
| 1057 */ |
| 1058 if( locktype==EXCLUSIVE_LOCK && res ){ |
| 1059 assert( pFile->locktype>=SHARED_LOCK ); |
| 1060 res = unlockReadLock(pFile); |
| 1061 OSTRACE(("unreadlock = %d\n", res)); |
| 1062 res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |
| 1063 if( res ){ |
| 1064 newLocktype = EXCLUSIVE_LOCK; |
| 1065 }else{ |
| 1066 error = GetLastError(); |
| 1067 OSTRACE(("error-code = %d\n", error)); |
| 1068 getReadLock(pFile); |
| 1069 } |
| 1070 } |
| 1071 |
| 1072 /* If we are holding a PENDING lock that ought to be released, then |
| 1073 ** release it now. |
| 1074 */ |
| 1075 if( gotPendingLock && locktype==SHARED_LOCK ){ |
| 1076 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); |
| 1077 } |
| 1078 |
| 1079 /* Update the state of the lock has held in the file descriptor then |
| 1080 ** return the appropriate result code. |
| 1081 */ |
| 1082 if( res ){ |
| 1083 rc = SQLITE_OK; |
| 1084 }else{ |
| 1085 OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h, |
| 1086 locktype, newLocktype)); |
| 1087 pFile->lastErrno = error; |
| 1088 rc = SQLITE_BUSY; |
| 1089 } |
| 1090 pFile->locktype = (u8)newLocktype; |
| 1091 return rc; |
| 1092 } |
| 1093 |
| 1094 /* |
| 1095 ** This routine checks if there is a RESERVED lock held on the specified |
| 1096 ** file by this or any other process. If such a lock is held, return |
| 1097 ** non-zero, otherwise zero. |
| 1098 */ |
| 1099 static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ |
| 1100 int rc; |
| 1101 winFile *pFile = (winFile*)id; |
| 1102 |
| 1103 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); |
| 1104 |
| 1105 assert( id!=0 ); |
| 1106 if( pFile->locktype>=RESERVED_LOCK ){ |
| 1107 rc = 1; |
| 1108 OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc)); |
| 1109 }else{ |
| 1110 rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |
| 1111 if( rc ){ |
| 1112 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |
| 1113 } |
| 1114 rc = !rc; |
| 1115 OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc)); |
| 1116 } |
| 1117 *pResOut = rc; |
| 1118 return SQLITE_OK; |
| 1119 } |
| 1120 |
| 1121 /* |
| 1122 ** Lower the locking level on file descriptor id to locktype. locktype |
| 1123 ** must be either NO_LOCK or SHARED_LOCK. |
| 1124 ** |
| 1125 ** If the locking level of the file descriptor is already at or below |
| 1126 ** the requested locking level, this routine is a no-op. |
| 1127 ** |
| 1128 ** It is not possible for this routine to fail if the second argument |
| 1129 ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine |
| 1130 ** might return SQLITE_IOERR; |
| 1131 */ |
| 1132 static int winUnlock(sqlite3_file *id, int locktype){ |
| 1133 int type; |
| 1134 winFile *pFile = (winFile*)id; |
| 1135 int rc = SQLITE_OK; |
| 1136 assert( pFile!=0 ); |
| 1137 assert( locktype<=SHARED_LOCK ); |
| 1138 OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, |
| 1139 pFile->locktype, pFile->sharedLockByte)); |
| 1140 type = pFile->locktype; |
| 1141 if( type>=EXCLUSIVE_LOCK ){ |
| 1142 UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |
| 1143 if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ |
| 1144 /* This should never happen. We should always be able to |
| 1145 ** reacquire the read lock */ |
| 1146 rc = SQLITE_IOERR_UNLOCK; |
| 1147 } |
| 1148 } |
| 1149 if( type>=RESERVED_LOCK ){ |
| 1150 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |
| 1151 } |
| 1152 if( locktype==NO_LOCK && type>=SHARED_LOCK ){ |
| 1153 unlockReadLock(pFile); |
| 1154 } |
| 1155 if( type>=PENDING_LOCK ){ |
| 1156 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); |
| 1157 } |
| 1158 pFile->locktype = (u8)locktype; |
| 1159 return rc; |
| 1160 } |
| 1161 |
| 1162 /* |
| 1163 ** Control and query of the open file handle. |
| 1164 */ |
| 1165 static int winFileControl(sqlite3_file *id, int op, void *pArg){ |
| 1166 switch( op ){ |
| 1167 case SQLITE_FCNTL_LOCKSTATE: { |
| 1168 *(int*)pArg = ((winFile*)id)->locktype; |
| 1169 return SQLITE_OK; |
| 1170 } |
| 1171 case SQLITE_LAST_ERRNO: { |
| 1172 *(int*)pArg = (int)((winFile*)id)->lastErrno; |
| 1173 return SQLITE_OK; |
| 1174 } |
| 1175 case SQLITE_FCNTL_CHUNK_SIZE: { |
| 1176 ((winFile*)id)->szChunk = *(int *)pArg; |
| 1177 return SQLITE_OK; |
| 1178 } |
| 1179 case SQLITE_FCNTL_SIZE_HINT: { |
| 1180 sqlite3_int64 sz = *(sqlite3_int64*)pArg; |
| 1181 SimulateIOErrorBenign(1); |
| 1182 winTruncate(id, sz); |
| 1183 SimulateIOErrorBenign(0); |
| 1184 return SQLITE_OK; |
| 1185 } |
| 1186 case SQLITE_FCNTL_SYNC_OMITTED: { |
| 1187 return SQLITE_OK; |
| 1188 } |
| 1189 } |
| 1190 return SQLITE_NOTFOUND; |
| 1191 } |
| 1192 |
| 1193 /* |
| 1194 ** Return the sector size in bytes of the underlying block device for |
| 1195 ** the specified file. This is almost always 512 bytes, but may be |
| 1196 ** larger for some devices. |
| 1197 ** |
| 1198 ** SQLite code assumes this function cannot fail. It also assumes that |
| 1199 ** if two files are created in the same file-system directory (i.e. |
| 1200 ** a database and its journal file) that the sector size will be the |
| 1201 ** same for both. |
| 1202 */ |
| 1203 static int winSectorSize(sqlite3_file *id){ |
| 1204 assert( id!=0 ); |
| 1205 return (int)(((winFile*)id)->sectorSize); |
| 1206 } |
| 1207 |
| 1208 /* |
| 1209 ** Return a vector of device characteristics. |
| 1210 */ |
| 1211 static int winDeviceCharacteristics(sqlite3_file *id){ |
| 1212 UNUSED_PARAMETER(id); |
| 1213 return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; |
| 1214 } |
| 1215 |
| 1216 #ifndef SQLITE_OMIT_WAL |
| 1217 |
| 1218 /* |
| 1219 ** Windows will only let you create file view mappings |
| 1220 ** on allocation size granularity boundaries. |
| 1221 ** During sqlite3_os_init() we do a GetSystemInfo() |
| 1222 ** to get the granularity size. |
| 1223 */ |
| 1224 SYSTEM_INFO winSysInfo; |
| 1225 |
| 1226 /* |
| 1227 ** Helper functions to obtain and relinquish the global mutex. The |
| 1228 ** global mutex is used to protect the winLockInfo objects used by |
| 1229 ** this file, all of which may be shared by multiple threads. |
| 1230 ** |
| 1231 ** Function winShmMutexHeld() is used to assert() that the global mutex |
| 1232 ** is held when required. This function is only used as part of assert() |
| 1233 ** statements. e.g. |
| 1234 ** |
| 1235 ** winShmEnterMutex() |
| 1236 ** assert( winShmMutexHeld() ); |
| 1237 ** winShmLeaveMutex() |
| 1238 */ |
| 1239 static void winShmEnterMutex(void){ |
| 1240 sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); |
| 1241 } |
| 1242 static void winShmLeaveMutex(void){ |
| 1243 sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); |
| 1244 } |
| 1245 #ifdef SQLITE_DEBUG |
| 1246 static int winShmMutexHeld(void) { |
| 1247 return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); |
| 1248 } |
| 1249 #endif |
| 1250 |
| 1251 /* |
| 1252 ** Object used to represent a single file opened and mmapped to provide |
| 1253 ** shared memory. When multiple threads all reference the same |
| 1254 ** log-summary, each thread has its own winFile object, but they all |
| 1255 ** point to a single instance of this object. In other words, each |
| 1256 ** log-summary is opened only once per process. |
| 1257 ** |
| 1258 ** winShmMutexHeld() must be true when creating or destroying |
| 1259 ** this object or while reading or writing the following fields: |
| 1260 ** |
| 1261 ** nRef |
| 1262 ** pNext |
| 1263 ** |
| 1264 ** The following fields are read-only after the object is created: |
| 1265 ** |
| 1266 ** fid |
| 1267 ** zFilename |
| 1268 ** |
| 1269 ** Either winShmNode.mutex must be held or winShmNode.nRef==0 and |
| 1270 ** winShmMutexHeld() is true when reading or writing any other field |
| 1271 ** in this structure. |
| 1272 ** |
| 1273 */ |
| 1274 struct winShmNode { |
| 1275 sqlite3_mutex *mutex; /* Mutex to access this object */ |
| 1276 char *zFilename; /* Name of the file */ |
| 1277 winFile hFile; /* File handle from winOpen */ |
| 1278 |
| 1279 int szRegion; /* Size of shared-memory regions */ |
| 1280 int nRegion; /* Size of array apRegion */ |
| 1281 struct ShmRegion { |
| 1282 HANDLE hMap; /* File handle from CreateFileMapping */ |
| 1283 void *pMap; |
| 1284 } *aRegion; |
| 1285 DWORD lastErrno; /* The Windows errno from the last I/O error */ |
| 1286 |
| 1287 int nRef; /* Number of winShm objects pointing to this */ |
| 1288 winShm *pFirst; /* All winShm objects pointing to this */ |
| 1289 winShmNode *pNext; /* Next in list of all winShmNode objects */ |
| 1290 #ifdef SQLITE_DEBUG |
| 1291 u8 nextShmId; /* Next available winShm.id value */ |
| 1292 #endif |
| 1293 }; |
| 1294 |
| 1295 /* |
| 1296 ** A global array of all winShmNode objects. |
| 1297 ** |
| 1298 ** The winShmMutexHeld() must be true while reading or writing this list. |
| 1299 */ |
| 1300 static winShmNode *winShmNodeList = 0; |
| 1301 |
| 1302 /* |
| 1303 ** Structure used internally by this VFS to record the state of an |
| 1304 ** open shared memory connection. |
| 1305 ** |
| 1306 ** The following fields are initialized when this object is created and |
| 1307 ** are read-only thereafter: |
| 1308 ** |
| 1309 ** winShm.pShmNode |
| 1310 ** winShm.id |
| 1311 ** |
| 1312 ** All other fields are read/write. The winShm.pShmNode->mutex must be held |
| 1313 ** while accessing any read/write fields. |
| 1314 */ |
| 1315 struct winShm { |
| 1316 winShmNode *pShmNode; /* The underlying winShmNode object */ |
| 1317 winShm *pNext; /* Next winShm with the same winShmNode */ |
| 1318 u8 hasMutex; /* True if holding the winShmNode mutex */ |
| 1319 u16 sharedMask; /* Mask of shared locks held */ |
| 1320 u16 exclMask; /* Mask of exclusive locks held */ |
| 1321 #ifdef SQLITE_DEBUG |
| 1322 u8 id; /* Id of this connection with its winShmNode */ |
| 1323 #endif |
| 1324 }; |
| 1325 |
| 1326 /* |
| 1327 ** Constants used for locking |
| 1328 */ |
| 1329 #define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ |
| 1330 #define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ |
| 1331 |
| 1332 /* |
| 1333 ** Apply advisory locks for all n bytes beginning at ofst. |
| 1334 */ |
| 1335 #define _SHM_UNLCK 1 |
| 1336 #define _SHM_RDLCK 2 |
| 1337 #define _SHM_WRLCK 3 |
| 1338 static int winShmSystemLock( |
| 1339 winShmNode *pFile, /* Apply locks to this open shared-memory segment */ |
| 1340 int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */ |
| 1341 int ofst, /* Offset to first byte to be locked/unlocked */ |
| 1342 int nByte /* Number of bytes to lock or unlock */ |
| 1343 ){ |
| 1344 OVERLAPPED ovlp; |
| 1345 DWORD dwFlags; |
| 1346 int rc = 0; /* Result code form Lock/UnlockFileEx() */ |
| 1347 |
| 1348 /* Access to the winShmNode object is serialized by the caller */ |
| 1349 assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); |
| 1350 |
| 1351 /* Initialize the locking parameters */ |
| 1352 dwFlags = LOCKFILE_FAIL_IMMEDIATELY; |
| 1353 if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; |
| 1354 |
| 1355 memset(&ovlp, 0, sizeof(OVERLAPPED)); |
| 1356 ovlp.Offset = ofst; |
| 1357 |
| 1358 /* Release/Acquire the system-level lock */ |
| 1359 if( lockType==_SHM_UNLCK ){ |
| 1360 rc = UnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp); |
| 1361 }else{ |
| 1362 rc = LockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp); |
| 1363 } |
| 1364 |
| 1365 if( rc!= 0 ){ |
| 1366 rc = SQLITE_OK; |
| 1367 }else{ |
| 1368 pFile->lastErrno = GetLastError(); |
| 1369 rc = SQLITE_BUSY; |
| 1370 } |
| 1371 |
| 1372 OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n", |
| 1373 pFile->hFile.h, |
| 1374 rc==SQLITE_OK ? "ok" : "failed", |
| 1375 lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx", |
| 1376 pFile->lastErrno)); |
| 1377 |
| 1378 return rc; |
| 1379 } |
| 1380 |
| 1381 /* Forward references to VFS methods */ |
| 1382 static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); |
| 1383 static int winDelete(sqlite3_vfs *,const char*,int); |
| 1384 |
| 1385 /* |
| 1386 ** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. |
| 1387 ** |
| 1388 ** This is not a VFS shared-memory method; it is a utility function called |
| 1389 ** by VFS shared-memory methods. |
| 1390 */ |
| 1391 static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ |
| 1392 winShmNode **pp; |
| 1393 winShmNode *p; |
| 1394 BOOL bRc; |
| 1395 assert( winShmMutexHeld() ); |
| 1396 pp = &winShmNodeList; |
| 1397 while( (p = *pp)!=0 ){ |
| 1398 if( p->nRef==0 ){ |
| 1399 int i; |
| 1400 if( p->mutex ) sqlite3_mutex_free(p->mutex); |
| 1401 for(i=0; i<p->nRegion; i++){ |
| 1402 bRc = UnmapViewOfFile(p->aRegion[i].pMap); |
| 1403 OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n", |
| 1404 (int)GetCurrentProcessId(), i, |
| 1405 bRc ? "ok" : "failed")); |
| 1406 bRc = CloseHandle(p->aRegion[i].hMap); |
| 1407 OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n", |
| 1408 (int)GetCurrentProcessId(), i, |
| 1409 bRc ? "ok" : "failed")); |
| 1410 } |
| 1411 if( p->hFile.h != INVALID_HANDLE_VALUE ){ |
| 1412 SimulateIOErrorBenign(1); |
| 1413 winClose((sqlite3_file *)&p->hFile); |
| 1414 SimulateIOErrorBenign(0); |
| 1415 } |
| 1416 if( deleteFlag ){ |
| 1417 SimulateIOErrorBenign(1); |
| 1418 winDelete(pVfs, p->zFilename, 0); |
| 1419 SimulateIOErrorBenign(0); |
| 1420 } |
| 1421 *pp = p->pNext; |
| 1422 sqlite3_free(p->aRegion); |
| 1423 sqlite3_free(p); |
| 1424 }else{ |
| 1425 pp = &p->pNext; |
| 1426 } |
| 1427 } |
| 1428 } |
| 1429 |
| 1430 /* |
| 1431 ** Open the shared-memory area associated with database file pDbFd. |
| 1432 ** |
| 1433 ** When opening a new shared-memory file, if no other instances of that |
| 1434 ** file are currently open, in this process or in other processes, then |
| 1435 ** the file must be truncated to zero length or have its header cleared. |
| 1436 */ |
| 1437 static int winOpenSharedMemory(winFile *pDbFd){ |
| 1438 struct winShm *p; /* The connection to be opened */ |
| 1439 struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ |
| 1440 int rc; /* Result code */ |
| 1441 struct winShmNode *pNew; /* Newly allocated winShmNode */ |
| 1442 int nName; /* Size of zName in bytes */ |
| 1443 |
| 1444 assert( pDbFd->pShm==0 ); /* Not previously opened */ |
| 1445 |
| 1446 /* Allocate space for the new sqlite3_shm object. Also speculatively |
| 1447 ** allocate space for a new winShmNode and filename. |
| 1448 */ |
| 1449 p = sqlite3_malloc( sizeof(*p) ); |
| 1450 if( p==0 ) return SQLITE_NOMEM; |
| 1451 memset(p, 0, sizeof(*p)); |
| 1452 nName = sqlite3Strlen30(pDbFd->zPath); |
| 1453 pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 15 ); |
| 1454 if( pNew==0 ){ |
| 1455 sqlite3_free(p); |
| 1456 return SQLITE_NOMEM; |
| 1457 } |
| 1458 memset(pNew, 0, sizeof(*pNew)); |
| 1459 pNew->zFilename = (char*)&pNew[1]; |
| 1460 sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); |
| 1461 |
| 1462 /* Look to see if there is an existing winShmNode that can be used. |
| 1463 ** If no matching winShmNode currently exists, create a new one. |
| 1464 */ |
| 1465 winShmEnterMutex(); |
| 1466 for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ |
| 1467 /* TBD need to come up with better match here. Perhaps |
| 1468 ** use FILE_ID_BOTH_DIR_INFO Structure. |
| 1469 */ |
| 1470 if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; |
| 1471 } |
| 1472 if( pShmNode ){ |
| 1473 sqlite3_free(pNew); |
| 1474 }else{ |
| 1475 pShmNode = pNew; |
| 1476 pNew = 0; |
| 1477 ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; |
| 1478 pShmNode->pNext = winShmNodeList; |
| 1479 winShmNodeList = pShmNode; |
| 1480 |
| 1481 pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); |
| 1482 if( pShmNode->mutex==0 ){ |
| 1483 rc = SQLITE_NOMEM; |
| 1484 goto shm_open_err; |
| 1485 } |
| 1486 |
| 1487 rc = winOpen(pDbFd->pVfs, |
| 1488 pShmNode->zFilename, /* Name of the file (UTF-8) */ |
| 1489 (sqlite3_file*)&pShmNode->hFile, /* File handle here */ |
| 1490 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /
* Mode flags */ |
| 1491 0); |
| 1492 if( SQLITE_OK!=rc ){ |
| 1493 rc = SQLITE_CANTOPEN_BKPT; |
| 1494 goto shm_open_err; |
| 1495 } |
| 1496 |
| 1497 /* Check to see if another process is holding the dead-man switch. |
| 1498 ** If not, truncate the file to zero length. |
| 1499 */ |
| 1500 if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ |
| 1501 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); |
| 1502 if( rc!=SQLITE_OK ){ |
| 1503 rc = SQLITE_IOERR_SHMOPEN; |
| 1504 } |
| 1505 } |
| 1506 if( rc==SQLITE_OK ){ |
| 1507 winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); |
| 1508 rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); |
| 1509 } |
| 1510 if( rc ) goto shm_open_err; |
| 1511 } |
| 1512 |
| 1513 /* Make the new connection a child of the winShmNode */ |
| 1514 p->pShmNode = pShmNode; |
| 1515 #ifdef SQLITE_DEBUG |
| 1516 p->id = pShmNode->nextShmId++; |
| 1517 #endif |
| 1518 pShmNode->nRef++; |
| 1519 pDbFd->pShm = p; |
| 1520 winShmLeaveMutex(); |
| 1521 |
| 1522 /* The reference count on pShmNode has already been incremented under |
| 1523 ** the cover of the winShmEnterMutex() mutex and the pointer from the |
| 1524 ** new (struct winShm) object to the pShmNode has been set. All that is |
| 1525 ** left to do is to link the new object into the linked list starting |
| 1526 ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex |
| 1527 ** mutex. |
| 1528 */ |
| 1529 sqlite3_mutex_enter(pShmNode->mutex); |
| 1530 p->pNext = pShmNode->pFirst; |
| 1531 pShmNode->pFirst = p; |
| 1532 sqlite3_mutex_leave(pShmNode->mutex); |
| 1533 return SQLITE_OK; |
| 1534 |
| 1535 /* Jump here on any error */ |
| 1536 shm_open_err: |
| 1537 winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); |
| 1538 winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ |
| 1539 sqlite3_free(p); |
| 1540 sqlite3_free(pNew); |
| 1541 winShmLeaveMutex(); |
| 1542 return rc; |
| 1543 } |
| 1544 |
| 1545 /* |
| 1546 ** Close a connection to shared-memory. Delete the underlying |
| 1547 ** storage if deleteFlag is true. |
| 1548 */ |
| 1549 static int winShmUnmap( |
| 1550 sqlite3_file *fd, /* Database holding shared memory */ |
| 1551 int deleteFlag /* Delete after closing if true */ |
| 1552 ){ |
| 1553 winFile *pDbFd; /* Database holding shared-memory */ |
| 1554 winShm *p; /* The connection to be closed */ |
| 1555 winShmNode *pShmNode; /* The underlying shared-memory file */ |
| 1556 winShm **pp; /* For looping over sibling connections */ |
| 1557 |
| 1558 pDbFd = (winFile*)fd; |
| 1559 p = pDbFd->pShm; |
| 1560 if( p==0 ) return SQLITE_OK; |
| 1561 pShmNode = p->pShmNode; |
| 1562 |
| 1563 /* Remove connection p from the set of connections associated |
| 1564 ** with pShmNode */ |
| 1565 sqlite3_mutex_enter(pShmNode->mutex); |
| 1566 for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} |
| 1567 *pp = p->pNext; |
| 1568 |
| 1569 /* Free the connection p */ |
| 1570 sqlite3_free(p); |
| 1571 pDbFd->pShm = 0; |
| 1572 sqlite3_mutex_leave(pShmNode->mutex); |
| 1573 |
| 1574 /* If pShmNode->nRef has reached 0, then close the underlying |
| 1575 ** shared-memory file, too */ |
| 1576 winShmEnterMutex(); |
| 1577 assert( pShmNode->nRef>0 ); |
| 1578 pShmNode->nRef--; |
| 1579 if( pShmNode->nRef==0 ){ |
| 1580 winShmPurge(pDbFd->pVfs, deleteFlag); |
| 1581 } |
| 1582 winShmLeaveMutex(); |
| 1583 |
| 1584 return SQLITE_OK; |
| 1585 } |
| 1586 |
| 1587 /* |
| 1588 ** Change the lock state for a shared-memory segment. |
| 1589 */ |
| 1590 static int winShmLock( |
| 1591 sqlite3_file *fd, /* Database file holding the shared memory */ |
| 1592 int ofst, /* First lock to acquire or release */ |
| 1593 int n, /* Number of locks to acquire or release */ |
| 1594 int flags /* What to do with the lock */ |
| 1595 ){ |
| 1596 winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ |
| 1597 winShm *p = pDbFd->pShm; /* The shared memory being locked */ |
| 1598 winShm *pX; /* For looping over all siblings */ |
| 1599 winShmNode *pShmNode = p->pShmNode; |
| 1600 int rc = SQLITE_OK; /* Result code */ |
| 1601 u16 mask; /* Mask of locks to take or release */ |
| 1602 |
| 1603 assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); |
| 1604 assert( n>=1 ); |
| 1605 assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) |
| 1606 || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) |
| 1607 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) |
| 1608 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); |
| 1609 assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); |
| 1610 |
| 1611 mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); |
| 1612 assert( n>1 || mask==(1<<ofst) ); |
| 1613 sqlite3_mutex_enter(pShmNode->mutex); |
| 1614 if( flags & SQLITE_SHM_UNLOCK ){ |
| 1615 u16 allMask = 0; /* Mask of locks held by siblings */ |
| 1616 |
| 1617 /* See if any siblings hold this same lock */ |
| 1618 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 1619 if( pX==p ) continue; |
| 1620 assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); |
| 1621 allMask |= pX->sharedMask; |
| 1622 } |
| 1623 |
| 1624 /* Unlock the system-level locks */ |
| 1625 if( (mask & allMask)==0 ){ |
| 1626 rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n); |
| 1627 }else{ |
| 1628 rc = SQLITE_OK; |
| 1629 } |
| 1630 |
| 1631 /* Undo the local locks */ |
| 1632 if( rc==SQLITE_OK ){ |
| 1633 p->exclMask &= ~mask; |
| 1634 p->sharedMask &= ~mask; |
| 1635 } |
| 1636 }else if( flags & SQLITE_SHM_SHARED ){ |
| 1637 u16 allShared = 0; /* Union of locks held by connections other than "p" */ |
| 1638 |
| 1639 /* Find out which shared locks are already held by sibling connections. |
| 1640 ** If any sibling already holds an exclusive lock, go ahead and return |
| 1641 ** SQLITE_BUSY. |
| 1642 */ |
| 1643 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 1644 if( (pX->exclMask & mask)!=0 ){ |
| 1645 rc = SQLITE_BUSY; |
| 1646 break; |
| 1647 } |
| 1648 allShared |= pX->sharedMask; |
| 1649 } |
| 1650 |
| 1651 /* Get shared locks at the system level, if necessary */ |
| 1652 if( rc==SQLITE_OK ){ |
| 1653 if( (allShared & mask)==0 ){ |
| 1654 rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n); |
| 1655 }else{ |
| 1656 rc = SQLITE_OK; |
| 1657 } |
| 1658 } |
| 1659 |
| 1660 /* Get the local shared locks */ |
| 1661 if( rc==SQLITE_OK ){ |
| 1662 p->sharedMask |= mask; |
| 1663 } |
| 1664 }else{ |
| 1665 /* Make sure no sibling connections hold locks that will block this |
| 1666 ** lock. If any do, return SQLITE_BUSY right away. |
| 1667 */ |
| 1668 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ |
| 1669 if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ |
| 1670 rc = SQLITE_BUSY; |
| 1671 break; |
| 1672 } |
| 1673 } |
| 1674 |
| 1675 /* Get the exclusive locks at the system level. Then if successful |
| 1676 ** also mark the local connection as being locked. |
| 1677 */ |
| 1678 if( rc==SQLITE_OK ){ |
| 1679 rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n); |
| 1680 if( rc==SQLITE_OK ){ |
| 1681 assert( (p->sharedMask & mask)==0 ); |
| 1682 p->exclMask |= mask; |
| 1683 } |
| 1684 } |
| 1685 } |
| 1686 sqlite3_mutex_leave(pShmNode->mutex); |
| 1687 OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n", |
| 1688 p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask, |
| 1689 rc ? "failed" : "ok")); |
| 1690 return rc; |
| 1691 } |
| 1692 |
| 1693 /* |
| 1694 ** Implement a memory barrier or memory fence on shared memory. |
| 1695 ** |
| 1696 ** All loads and stores begun before the barrier must complete before |
| 1697 ** any load or store begun after the barrier. |
| 1698 */ |
| 1699 static void winShmBarrier( |
| 1700 sqlite3_file *fd /* Database holding the shared memory */ |
| 1701 ){ |
| 1702 UNUSED_PARAMETER(fd); |
| 1703 /* MemoryBarrier(); // does not work -- do not know why not */ |
| 1704 winShmEnterMutex(); |
| 1705 winShmLeaveMutex(); |
| 1706 } |
| 1707 |
| 1708 /* |
| 1709 ** This function is called to obtain a pointer to region iRegion of the |
| 1710 ** shared-memory associated with the database file fd. Shared-memory regions |
| 1711 ** are numbered starting from zero. Each shared-memory region is szRegion |
| 1712 ** bytes in size. |
| 1713 ** |
| 1714 ** If an error occurs, an error code is returned and *pp is set to NULL. |
| 1715 ** |
| 1716 ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory |
| 1717 ** region has not been allocated (by any client, including one running in a |
| 1718 ** separate process), then *pp is set to NULL and SQLITE_OK returned. If |
| 1719 ** isWrite is non-zero and the requested shared-memory region has not yet |
| 1720 ** been allocated, it is allocated by this function. |
| 1721 ** |
| 1722 ** If the shared-memory region has already been allocated or is allocated by |
| 1723 ** this call as described above, then it is mapped into this processes |
| 1724 ** address space (if it is not already), *pp is set to point to the mapped |
| 1725 ** memory and SQLITE_OK returned. |
| 1726 */ |
| 1727 static int winShmMap( |
| 1728 sqlite3_file *fd, /* Handle open on database file */ |
| 1729 int iRegion, /* Region to retrieve */ |
| 1730 int szRegion, /* Size of regions */ |
| 1731 int isWrite, /* True to extend file if necessary */ |
| 1732 void volatile **pp /* OUT: Mapped memory */ |
| 1733 ){ |
| 1734 winFile *pDbFd = (winFile*)fd; |
| 1735 winShm *p = pDbFd->pShm; |
| 1736 winShmNode *pShmNode; |
| 1737 int rc = SQLITE_OK; |
| 1738 |
| 1739 if( !p ){ |
| 1740 rc = winOpenSharedMemory(pDbFd); |
| 1741 if( rc!=SQLITE_OK ) return rc; |
| 1742 p = pDbFd->pShm; |
| 1743 } |
| 1744 pShmNode = p->pShmNode; |
| 1745 |
| 1746 sqlite3_mutex_enter(pShmNode->mutex); |
| 1747 assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); |
| 1748 |
| 1749 if( pShmNode->nRegion<=iRegion ){ |
| 1750 struct ShmRegion *apNew; /* New aRegion[] array */ |
| 1751 int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ |
| 1752 sqlite3_int64 sz; /* Current size of wal-index file */ |
| 1753 |
| 1754 pShmNode->szRegion = szRegion; |
| 1755 |
| 1756 /* The requested region is not mapped into this processes address space. |
| 1757 ** Check to see if it has been allocated (i.e. if the wal-index file is |
| 1758 ** large enough to contain the requested region). |
| 1759 */ |
| 1760 rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); |
| 1761 if( rc!=SQLITE_OK ){ |
| 1762 rc = SQLITE_IOERR_SHMSIZE; |
| 1763 goto shmpage_out; |
| 1764 } |
| 1765 |
| 1766 if( sz<nByte ){ |
| 1767 /* The requested memory region does not exist. If isWrite is set to |
| 1768 ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned. |
| 1769 ** |
| 1770 ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate |
| 1771 ** the requested memory region. |
| 1772 */ |
| 1773 if( !isWrite ) goto shmpage_out; |
| 1774 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte); |
| 1775 if( rc!=SQLITE_OK ){ |
| 1776 rc = SQLITE_IOERR_SHMSIZE; |
| 1777 goto shmpage_out; |
| 1778 } |
| 1779 } |
| 1780 |
| 1781 /* Map the requested memory region into this processes address space. */ |
| 1782 apNew = (struct ShmRegion *)sqlite3_realloc( |
| 1783 pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) |
| 1784 ); |
| 1785 if( !apNew ){ |
| 1786 rc = SQLITE_IOERR_NOMEM; |
| 1787 goto shmpage_out; |
| 1788 } |
| 1789 pShmNode->aRegion = apNew; |
| 1790 |
| 1791 while( pShmNode->nRegion<=iRegion ){ |
| 1792 HANDLE hMap; /* file-mapping handle */ |
| 1793 void *pMap = 0; /* Mapped memory region */ |
| 1794 |
| 1795 hMap = CreateFileMapping(pShmNode->hFile.h, |
| 1796 NULL, PAGE_READWRITE, 0, nByte, NULL |
| 1797 ); |
| 1798 OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n", |
| 1799 (int)GetCurrentProcessId(), pShmNode->nRegion, nByte, |
| 1800 hMap ? "ok" : "failed")); |
| 1801 if( hMap ){ |
| 1802 int iOffset = pShmNode->nRegion*szRegion; |
| 1803 int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; |
| 1804 pMap = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, |
| 1805 0, iOffset - iOffsetShift, szRegion + iOffsetShift |
| 1806 ); |
| 1807 OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n", |
| 1808 (int)GetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegio
n, |
| 1809 pMap ? "ok" : "failed")); |
| 1810 } |
| 1811 if( !pMap ){ |
| 1812 pShmNode->lastErrno = GetLastError(); |
| 1813 rc = SQLITE_IOERR; |
| 1814 if( hMap ) CloseHandle(hMap); |
| 1815 goto shmpage_out; |
| 1816 } |
| 1817 |
| 1818 pShmNode->aRegion[pShmNode->nRegion].pMap = pMap; |
| 1819 pShmNode->aRegion[pShmNode->nRegion].hMap = hMap; |
| 1820 pShmNode->nRegion++; |
| 1821 } |
| 1822 } |
| 1823 |
| 1824 shmpage_out: |
| 1825 if( pShmNode->nRegion>iRegion ){ |
| 1826 int iOffset = iRegion*szRegion; |
| 1827 int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; |
| 1828 char *p = (char *)pShmNode->aRegion[iRegion].pMap; |
| 1829 *pp = (void *)&p[iOffsetShift]; |
| 1830 }else{ |
| 1831 *pp = 0; |
| 1832 } |
| 1833 sqlite3_mutex_leave(pShmNode->mutex); |
| 1834 return rc; |
| 1835 } |
| 1836 |
| 1837 #else |
| 1838 # define winShmMap 0 |
| 1839 # define winShmLock 0 |
| 1840 # define winShmBarrier 0 |
| 1841 # define winShmUnmap 0 |
| 1842 #endif /* #ifndef SQLITE_OMIT_WAL */ |
| 1843 |
| 1844 /* |
| 1845 ** Here ends the implementation of all sqlite3_file methods. |
| 1846 ** |
| 1847 ********************** End sqlite3_file Methods ******************************* |
| 1848 ******************************************************************************/ |
| 1849 |
| 1850 /* |
| 1851 ** This vector defines all the methods that can operate on an |
| 1852 ** sqlite3_file for win32. |
| 1853 */ |
| 1854 static const sqlite3_io_methods winIoMethod = { |
| 1855 2, /* iVersion */ |
| 1856 winClose, /* xClose */ |
| 1857 winRead, /* xRead */ |
| 1858 winWrite, /* xWrite */ |
| 1859 winTruncate, /* xTruncate */ |
| 1860 winSync, /* xSync */ |
| 1861 winFileSize, /* xFileSize */ |
| 1862 winLock, /* xLock */ |
| 1863 winUnlock, /* xUnlock */ |
| 1864 winCheckReservedLock, /* xCheckReservedLock */ |
| 1865 winFileControl, /* xFileControl */ |
| 1866 winSectorSize, /* xSectorSize */ |
| 1867 winDeviceCharacteristics, /* xDeviceCharacteristics */ |
| 1868 winShmMap, /* xShmMap */ |
| 1869 winShmLock, /* xShmLock */ |
| 1870 winShmBarrier, /* xShmBarrier */ |
| 1871 winShmUnmap /* xShmUnmap */ |
| 1872 }; |
| 1873 |
| 1874 /**************************************************************************** |
| 1875 **************************** sqlite3_vfs methods **************************** |
| 1876 ** |
| 1877 ** This division contains the implementation of methods on the |
| 1878 ** sqlite3_vfs object. |
| 1879 */ |
| 1880 |
| 1881 /* |
| 1882 ** Convert a UTF-8 filename into whatever form the underlying |
| 1883 ** operating system wants filenames in. Space to hold the result |
| 1884 ** is obtained from malloc and must be freed by the calling |
| 1885 ** function. |
| 1886 */ |
| 1887 static void *convertUtf8Filename(const char *zFilename){ |
| 1888 void *zConverted = 0; |
| 1889 if( isNT() ){ |
| 1890 zConverted = utf8ToUnicode(zFilename); |
| 1891 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 1892 */ |
| 1893 #if SQLITE_OS_WINCE==0 |
| 1894 }else{ |
| 1895 zConverted = utf8ToMbcs(zFilename); |
| 1896 #endif |
| 1897 } |
| 1898 /* caller will handle out of memory */ |
| 1899 return zConverted; |
| 1900 } |
| 1901 |
| 1902 /* |
| 1903 ** Create a temporary file name in zBuf. zBuf must be big enough to |
| 1904 ** hold at pVfs->mxPathname characters. |
| 1905 */ |
| 1906 static int getTempname(int nBuf, char *zBuf){ |
| 1907 static char zChars[] = |
| 1908 "abcdefghijklmnopqrstuvwxyz" |
| 1909 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 1910 "0123456789"; |
| 1911 size_t i, j; |
| 1912 char zTempPath[MAX_PATH+1]; |
| 1913 |
| 1914 /* It's odd to simulate an io-error here, but really this is just |
| 1915 ** using the io-error infrastructure to test that SQLite handles this |
| 1916 ** function failing. |
| 1917 */ |
| 1918 SimulateIOError( return SQLITE_IOERR ); |
| 1919 |
| 1920 if( sqlite3_temp_directory ){ |
| 1921 sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); |
| 1922 }else if( isNT() ){ |
| 1923 char *zMulti; |
| 1924 WCHAR zWidePath[MAX_PATH]; |
| 1925 GetTempPathW(MAX_PATH-30, zWidePath); |
| 1926 zMulti = unicodeToUtf8(zWidePath); |
| 1927 if( zMulti ){ |
| 1928 sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); |
| 1929 free(zMulti); |
| 1930 }else{ |
| 1931 return SQLITE_NOMEM; |
| 1932 } |
| 1933 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 1934 ** Since the ASCII version of these Windows API do not exist for WINCE, |
| 1935 ** it's important to not reference them for WINCE builds. |
| 1936 */ |
| 1937 #if SQLITE_OS_WINCE==0 |
| 1938 }else{ |
| 1939 char *zUtf8; |
| 1940 char zMbcsPath[MAX_PATH]; |
| 1941 GetTempPathA(MAX_PATH-30, zMbcsPath); |
| 1942 zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); |
| 1943 if( zUtf8 ){ |
| 1944 sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); |
| 1945 free(zUtf8); |
| 1946 }else{ |
| 1947 return SQLITE_NOMEM; |
| 1948 } |
| 1949 #endif |
| 1950 } |
| 1951 |
| 1952 /* Check that the output buffer is large enough for the temporary file |
| 1953 ** name. If it is not, return SQLITE_ERROR. |
| 1954 */ |
| 1955 if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 1
7) >= nBuf ){ |
| 1956 return SQLITE_ERROR; |
| 1957 } |
| 1958 |
| 1959 for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} |
| 1960 zTempPath[i] = 0; |
| 1961 |
| 1962 sqlite3_snprintf(nBuf-17, zBuf, |
| 1963 "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); |
| 1964 j = sqlite3Strlen30(zBuf); |
| 1965 sqlite3_randomness(15, &zBuf[j]); |
| 1966 for(i=0; i<15; i++, j++){ |
| 1967 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; |
| 1968 } |
| 1969 zBuf[j] = 0; |
| 1970 |
| 1971 OSTRACE(("TEMP FILENAME: %s\n", zBuf)); |
| 1972 return SQLITE_OK; |
| 1973 } |
| 1974 |
| 1975 /* |
| 1976 ** The return value of getLastErrorMsg |
| 1977 ** is zero if the error message fits in the buffer, or non-zero |
| 1978 ** otherwise (if the message was truncated). |
| 1979 */ |
| 1980 static int getLastErrorMsg(int nBuf, char *zBuf){ |
| 1981 /* FormatMessage returns 0 on failure. Otherwise it |
| 1982 ** returns the number of TCHARs written to the output |
| 1983 ** buffer, excluding the terminating null char. |
| 1984 */ |
| 1985 DWORD error = GetLastError(); |
| 1986 DWORD dwLen = 0; |
| 1987 char *zOut = 0; |
| 1988 |
| 1989 if( isNT() ){ |
| 1990 WCHAR *zTempWide = NULL; |
| 1991 dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_
SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 1992 NULL, |
| 1993 error, |
| 1994 0, |
| 1995 (LPWSTR) &zTempWide, |
| 1996 0, |
| 1997 0); |
| 1998 if( dwLen > 0 ){ |
| 1999 /* allocate a buffer and convert to UTF8 */ |
| 2000 zOut = unicodeToUtf8(zTempWide); |
| 2001 /* free the system buffer allocated by FormatMessage */ |
| 2002 LocalFree(zTempWide); |
| 2003 } |
| 2004 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 2005 ** Since the ASCII version of these Windows API do not exist for WINCE, |
| 2006 ** it's important to not reference them for WINCE builds. |
| 2007 */ |
| 2008 #if SQLITE_OS_WINCE==0 |
| 2009 }else{ |
| 2010 char *zTemp = NULL; |
| 2011 dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_
SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 2012 NULL, |
| 2013 error, |
| 2014 0, |
| 2015 (LPSTR) &zTemp, |
| 2016 0, |
| 2017 0); |
| 2018 if( dwLen > 0 ){ |
| 2019 /* allocate a buffer and convert to UTF8 */ |
| 2020 zOut = sqlite3_win32_mbcs_to_utf8(zTemp); |
| 2021 /* free the system buffer allocated by FormatMessage */ |
| 2022 LocalFree(zTemp); |
| 2023 } |
| 2024 #endif |
| 2025 } |
| 2026 if( 0 == dwLen ){ |
| 2027 sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); |
| 2028 }else{ |
| 2029 /* copy a maximum of nBuf chars to output buffer */ |
| 2030 sqlite3_snprintf(nBuf, zBuf, "%s", zOut); |
| 2031 /* free the UTF8 buffer */ |
| 2032 free(zOut); |
| 2033 } |
| 2034 return 0; |
| 2035 } |
| 2036 |
| 2037 /* |
| 2038 ** Open a file. |
| 2039 */ |
| 2040 static int winOpen( |
| 2041 sqlite3_vfs *pVfs, /* Not used */ |
| 2042 const char *zName, /* Name of the file (UTF-8) */ |
| 2043 sqlite3_file *id, /* Write the SQLite file handle here */ |
| 2044 int flags, /* Open mode flags */ |
| 2045 int *pOutFlags /* Status return flags */ |
| 2046 ){ |
| 2047 HANDLE h; |
| 2048 DWORD dwDesiredAccess; |
| 2049 DWORD dwShareMode; |
| 2050 DWORD dwCreationDisposition; |
| 2051 DWORD dwFlagsAndAttributes = 0; |
| 2052 #if SQLITE_OS_WINCE |
| 2053 int isTemp = 0; |
| 2054 #endif |
| 2055 winFile *pFile = (winFile*)id; |
| 2056 void *zConverted; /* Filename in OS encoding */ |
| 2057 const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ |
| 2058 |
| 2059 /* If argument zPath is a NULL pointer, this function is required to open |
| 2060 ** a temporary file. Use this buffer to store the file name in. |
| 2061 */ |
| 2062 char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ |
| 2063 |
| 2064 int rc = SQLITE_OK; /* Function Return Code */ |
| 2065 #if !defined(NDEBUG) || SQLITE_OS_WINCE |
| 2066 int eType = flags&0xFFFFFF00; /* Type of file to open */ |
| 2067 #endif |
| 2068 |
| 2069 int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); |
| 2070 int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); |
| 2071 int isCreate = (flags & SQLITE_OPEN_CREATE); |
| 2072 #ifndef NDEBUG |
| 2073 int isReadonly = (flags & SQLITE_OPEN_READONLY); |
| 2074 #endif |
| 2075 int isReadWrite = (flags & SQLITE_OPEN_READWRITE); |
| 2076 |
| 2077 #ifndef NDEBUG |
| 2078 int isOpenJournal = (isCreate && ( |
| 2079 eType==SQLITE_OPEN_MASTER_JOURNAL |
| 2080 || eType==SQLITE_OPEN_MAIN_JOURNAL |
| 2081 || eType==SQLITE_OPEN_WAL |
| 2082 )); |
| 2083 #endif |
| 2084 |
| 2085 /* Check the following statements are true: |
| 2086 ** |
| 2087 ** (a) Exactly one of the READWRITE and READONLY flags must be set, and |
| 2088 ** (b) if CREATE is set, then READWRITE must also be set, and |
| 2089 ** (c) if EXCLUSIVE is set, then CREATE must also be set. |
| 2090 ** (d) if DELETEONCLOSE is set, then CREATE must also be set. |
| 2091 */ |
| 2092 assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); |
| 2093 assert(isCreate==0 || isReadWrite); |
| 2094 assert(isExclusive==0 || isCreate); |
| 2095 assert(isDelete==0 || isCreate); |
| 2096 |
| 2097 /* The main DB, main journal, WAL file and master journal are never |
| 2098 ** automatically deleted. Nor are they ever temporary files. */ |
| 2099 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); |
| 2100 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); |
| 2101 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); |
| 2102 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); |
| 2103 |
| 2104 /* Assert that the upper layer has set one of the "file-type" flags. */ |
| 2105 assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB |
| 2106 || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL |
| 2107 || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL |
| 2108 || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL |
| 2109 ); |
| 2110 |
| 2111 assert( id!=0 ); |
| 2112 UNUSED_PARAMETER(pVfs); |
| 2113 |
| 2114 pFile->h = INVALID_HANDLE_VALUE; |
| 2115 |
| 2116 /* If the second argument to this function is NULL, generate a |
| 2117 ** temporary file name to use |
| 2118 */ |
| 2119 if( !zUtf8Name ){ |
| 2120 assert(isDelete && !isOpenJournal); |
| 2121 rc = getTempname(MAX_PATH+1, zTmpname); |
| 2122 if( rc!=SQLITE_OK ){ |
| 2123 return rc; |
| 2124 } |
| 2125 zUtf8Name = zTmpname; |
| 2126 } |
| 2127 |
| 2128 /* Convert the filename to the system encoding. */ |
| 2129 zConverted = convertUtf8Filename(zUtf8Name); |
| 2130 if( zConverted==0 ){ |
| 2131 return SQLITE_NOMEM; |
| 2132 } |
| 2133 |
| 2134 if( isReadWrite ){ |
| 2135 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; |
| 2136 }else{ |
| 2137 dwDesiredAccess = GENERIC_READ; |
| 2138 } |
| 2139 |
| 2140 /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is |
| 2141 ** created. SQLite doesn't use it to indicate "exclusive access" |
| 2142 ** as it is usually understood. |
| 2143 */ |
| 2144 if( isExclusive ){ |
| 2145 /* Creates a new file, only if it does not already exist. */ |
| 2146 /* If the file exists, it fails. */ |
| 2147 dwCreationDisposition = CREATE_NEW; |
| 2148 }else if( isCreate ){ |
| 2149 /* Open existing file, or create if it doesn't exist */ |
| 2150 dwCreationDisposition = OPEN_ALWAYS; |
| 2151 }else{ |
| 2152 /* Opens a file, only if it exists. */ |
| 2153 dwCreationDisposition = OPEN_EXISTING; |
| 2154 } |
| 2155 |
| 2156 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; |
| 2157 |
| 2158 if( isDelete ){ |
| 2159 #if SQLITE_OS_WINCE |
| 2160 dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; |
| 2161 isTemp = 1; |
| 2162 #else |
| 2163 dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY |
| 2164 | FILE_ATTRIBUTE_HIDDEN |
| 2165 | FILE_FLAG_DELETE_ON_CLOSE; |
| 2166 #endif |
| 2167 }else{ |
| 2168 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; |
| 2169 } |
| 2170 /* Reports from the internet are that performance is always |
| 2171 ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ |
| 2172 #if SQLITE_OS_WINCE |
| 2173 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; |
| 2174 #endif |
| 2175 |
| 2176 if( isNT() ){ |
| 2177 h = CreateFileW((WCHAR*)zConverted, |
| 2178 dwDesiredAccess, |
| 2179 dwShareMode, |
| 2180 NULL, |
| 2181 dwCreationDisposition, |
| 2182 dwFlagsAndAttributes, |
| 2183 NULL |
| 2184 ); |
| 2185 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 2186 ** Since the ASCII version of these Windows API do not exist for WINCE, |
| 2187 ** it's important to not reference them for WINCE builds. |
| 2188 */ |
| 2189 #if SQLITE_OS_WINCE==0 |
| 2190 }else{ |
| 2191 h = CreateFileA((char*)zConverted, |
| 2192 dwDesiredAccess, |
| 2193 dwShareMode, |
| 2194 NULL, |
| 2195 dwCreationDisposition, |
| 2196 dwFlagsAndAttributes, |
| 2197 NULL |
| 2198 ); |
| 2199 #endif |
| 2200 } |
| 2201 |
| 2202 OSTRACE(("OPEN %d %s 0x%lx %s\n", |
| 2203 h, zName, dwDesiredAccess, |
| 2204 h==INVALID_HANDLE_VALUE ? "failed" : "ok")); |
| 2205 |
| 2206 if( h==INVALID_HANDLE_VALUE ){ |
| 2207 pFile->lastErrno = GetLastError(); |
| 2208 free(zConverted); |
| 2209 if( isReadWrite ){ |
| 2210 return winOpen(pVfs, zName, id, |
| 2211 ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READ
WRITE)), pOutFlags); |
| 2212 }else{ |
| 2213 return SQLITE_CANTOPEN_BKPT; |
| 2214 } |
| 2215 } |
| 2216 |
| 2217 if( pOutFlags ){ |
| 2218 if( isReadWrite ){ |
| 2219 *pOutFlags = SQLITE_OPEN_READWRITE; |
| 2220 }else{ |
| 2221 *pOutFlags = SQLITE_OPEN_READONLY; |
| 2222 } |
| 2223 } |
| 2224 |
| 2225 memset(pFile, 0, sizeof(*pFile)); |
| 2226 pFile->pMethod = &winIoMethod; |
| 2227 pFile->h = h; |
| 2228 pFile->lastErrno = NO_ERROR; |
| 2229 pFile->pVfs = pVfs; |
| 2230 pFile->pShm = 0; |
| 2231 pFile->zPath = zName; |
| 2232 pFile->sectorSize = getSectorSize(pVfs, zUtf8Name); |
| 2233 |
| 2234 #if SQLITE_OS_WINCE |
| 2235 if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB |
| 2236 && !winceCreateLock(zName, pFile) |
| 2237 ){ |
| 2238 CloseHandle(h); |
| 2239 free(zConverted); |
| 2240 return SQLITE_CANTOPEN_BKPT; |
| 2241 } |
| 2242 if( isTemp ){ |
| 2243 pFile->zDeleteOnClose = zConverted; |
| 2244 }else |
| 2245 #endif |
| 2246 { |
| 2247 free(zConverted); |
| 2248 } |
| 2249 |
| 2250 OpenCounter(+1); |
| 2251 return rc; |
| 2252 } |
| 2253 |
| 2254 /* |
| 2255 ** Delete the named file. |
| 2256 ** |
| 2257 ** Note that windows does not allow a file to be deleted if some other |
| 2258 ** process has it open. Sometimes a virus scanner or indexing program |
| 2259 ** will open a journal file shortly after it is created in order to do |
| 2260 ** whatever it does. While this other process is holding the |
| 2261 ** file open, we will be unable to delete it. To work around this |
| 2262 ** problem, we delay 100 milliseconds and try to delete again. Up |
| 2263 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving |
| 2264 ** up and returning an error. |
| 2265 */ |
| 2266 #define MX_DELETION_ATTEMPTS 5 |
| 2267 static int winDelete( |
| 2268 sqlite3_vfs *pVfs, /* Not used on win32 */ |
| 2269 const char *zFilename, /* Name of file to delete */ |
| 2270 int syncDir /* Not used on win32 */ |
| 2271 ){ |
| 2272 int cnt = 0; |
| 2273 DWORD rc; |
| 2274 DWORD error = 0; |
| 2275 void *zConverted; |
| 2276 UNUSED_PARAMETER(pVfs); |
| 2277 UNUSED_PARAMETER(syncDir); |
| 2278 |
| 2279 SimulateIOError(return SQLITE_IOERR_DELETE); |
| 2280 zConverted = convertUtf8Filename(zFilename); |
| 2281 if( zConverted==0 ){ |
| 2282 return SQLITE_NOMEM; |
| 2283 } |
| 2284 if( isNT() ){ |
| 2285 do{ |
| 2286 DeleteFileW(zConverted); |
| 2287 }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBU
TES) |
| 2288 || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) |
| 2289 && (++cnt < MX_DELETION_ATTEMPTS) |
| 2290 && (Sleep(100), 1) ); |
| 2291 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 2292 ** Since the ASCII version of these Windows API do not exist for WINCE, |
| 2293 ** it's important to not reference them for WINCE builds. |
| 2294 */ |
| 2295 #if SQLITE_OS_WINCE==0 |
| 2296 }else{ |
| 2297 do{ |
| 2298 DeleteFileA(zConverted); |
| 2299 }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBU
TES) |
| 2300 || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) |
| 2301 && (++cnt < MX_DELETION_ATTEMPTS) |
| 2302 && (Sleep(100), 1) ); |
| 2303 #endif |
| 2304 } |
| 2305 free(zConverted); |
| 2306 OSTRACE(("DELETE \"%s\" %s\n", zFilename, |
| 2307 ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ? |
| 2308 "ok" : "failed" )); |
| 2309 |
| 2310 return ( (rc == INVALID_FILE_ATTRIBUTES) |
| 2311 && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE; |
| 2312 } |
| 2313 |
| 2314 /* |
| 2315 ** Check the existance and status of a file. |
| 2316 */ |
| 2317 static int winAccess( |
| 2318 sqlite3_vfs *pVfs, /* Not used on win32 */ |
| 2319 const char *zFilename, /* Name of file to check */ |
| 2320 int flags, /* Type of test to make on this file */ |
| 2321 int *pResOut /* OUT: Result */ |
| 2322 ){ |
| 2323 DWORD attr; |
| 2324 int rc = 0; |
| 2325 void *zConverted; |
| 2326 UNUSED_PARAMETER(pVfs); |
| 2327 |
| 2328 SimulateIOError( return SQLITE_IOERR_ACCESS; ); |
| 2329 zConverted = convertUtf8Filename(zFilename); |
| 2330 if( zConverted==0 ){ |
| 2331 return SQLITE_NOMEM; |
| 2332 } |
| 2333 if( isNT() ){ |
| 2334 WIN32_FILE_ATTRIBUTE_DATA sAttrData; |
| 2335 memset(&sAttrData, 0, sizeof(sAttrData)); |
| 2336 if( GetFileAttributesExW((WCHAR*)zConverted, |
| 2337 GetFileExInfoStandard, |
| 2338 &sAttrData) ){ |
| 2339 /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file |
| 2340 ** as if it does not exist. |
| 2341 */ |
| 2342 if( flags==SQLITE_ACCESS_EXISTS |
| 2343 && sAttrData.nFileSizeHigh==0 |
| 2344 && sAttrData.nFileSizeLow==0 ){ |
| 2345 attr = INVALID_FILE_ATTRIBUTES; |
| 2346 }else{ |
| 2347 attr = sAttrData.dwFileAttributes; |
| 2348 } |
| 2349 }else{ |
| 2350 if( GetLastError()!=ERROR_FILE_NOT_FOUND ){ |
| 2351 free(zConverted); |
| 2352 return SQLITE_IOERR_ACCESS; |
| 2353 }else{ |
| 2354 attr = INVALID_FILE_ATTRIBUTES; |
| 2355 } |
| 2356 } |
| 2357 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 2358 ** Since the ASCII version of these Windows API do not exist for WINCE, |
| 2359 ** it's important to not reference them for WINCE builds. |
| 2360 */ |
| 2361 #if SQLITE_OS_WINCE==0 |
| 2362 }else{ |
| 2363 attr = GetFileAttributesA((char*)zConverted); |
| 2364 #endif |
| 2365 } |
| 2366 free(zConverted); |
| 2367 switch( flags ){ |
| 2368 case SQLITE_ACCESS_READ: |
| 2369 case SQLITE_ACCESS_EXISTS: |
| 2370 rc = attr!=INVALID_FILE_ATTRIBUTES; |
| 2371 break; |
| 2372 case SQLITE_ACCESS_READWRITE: |
| 2373 rc = (attr & FILE_ATTRIBUTE_READONLY)==0; |
| 2374 break; |
| 2375 default: |
| 2376 assert(!"Invalid flags argument"); |
| 2377 } |
| 2378 *pResOut = rc; |
| 2379 return SQLITE_OK; |
| 2380 } |
| 2381 |
| 2382 |
| 2383 /* |
| 2384 ** Turn a relative pathname into a full pathname. Write the full |
| 2385 ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname |
| 2386 ** bytes in size. |
| 2387 */ |
| 2388 static int winFullPathname( |
| 2389 sqlite3_vfs *pVfs, /* Pointer to vfs object */ |
| 2390 const char *zRelative, /* Possibly relative input path */ |
| 2391 int nFull, /* Size of output buffer in bytes */ |
| 2392 char *zFull /* Output buffer */ |
| 2393 ){ |
| 2394 |
| 2395 #if defined(__CYGWIN__) |
| 2396 SimulateIOError( return SQLITE_ERROR ); |
| 2397 UNUSED_PARAMETER(nFull); |
| 2398 cygwin_conv_to_full_win32_path(zRelative, zFull); |
| 2399 return SQLITE_OK; |
| 2400 #endif |
| 2401 |
| 2402 #if SQLITE_OS_WINCE |
| 2403 SimulateIOError( return SQLITE_ERROR ); |
| 2404 UNUSED_PARAMETER(nFull); |
| 2405 /* WinCE has no concept of a relative pathname, or so I am told. */ |
| 2406 sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); |
| 2407 return SQLITE_OK; |
| 2408 #endif |
| 2409 |
| 2410 #if !SQLITE_OS_WINCE && !defined(__CYGWIN__) |
| 2411 int nByte; |
| 2412 void *zConverted; |
| 2413 char *zOut; |
| 2414 |
| 2415 /* It's odd to simulate an io-error here, but really this is just |
| 2416 ** using the io-error infrastructure to test that SQLite handles this |
| 2417 ** function failing. This function could fail if, for example, the |
| 2418 ** current working directory has been unlinked. |
| 2419 */ |
| 2420 SimulateIOError( return SQLITE_ERROR ); |
| 2421 UNUSED_PARAMETER(nFull); |
| 2422 zConverted = convertUtf8Filename(zRelative); |
| 2423 if( isNT() ){ |
| 2424 WCHAR *zTemp; |
| 2425 nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; |
| 2426 zTemp = malloc( nByte*sizeof(zTemp[0]) ); |
| 2427 if( zTemp==0 ){ |
| 2428 free(zConverted); |
| 2429 return SQLITE_NOMEM; |
| 2430 } |
| 2431 GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); |
| 2432 free(zConverted); |
| 2433 zOut = unicodeToUtf8(zTemp); |
| 2434 free(zTemp); |
| 2435 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 2436 ** Since the ASCII version of these Windows API do not exist for WINCE, |
| 2437 ** it's important to not reference them for WINCE builds. |
| 2438 */ |
| 2439 #if SQLITE_OS_WINCE==0 |
| 2440 }else{ |
| 2441 char *zTemp; |
| 2442 nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; |
| 2443 zTemp = malloc( nByte*sizeof(zTemp[0]) ); |
| 2444 if( zTemp==0 ){ |
| 2445 free(zConverted); |
| 2446 return SQLITE_NOMEM; |
| 2447 } |
| 2448 GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); |
| 2449 free(zConverted); |
| 2450 zOut = sqlite3_win32_mbcs_to_utf8(zTemp); |
| 2451 free(zTemp); |
| 2452 #endif |
| 2453 } |
| 2454 if( zOut ){ |
| 2455 sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); |
| 2456 free(zOut); |
| 2457 return SQLITE_OK; |
| 2458 }else{ |
| 2459 return SQLITE_NOMEM; |
| 2460 } |
| 2461 #endif |
| 2462 } |
| 2463 |
| 2464 /* |
| 2465 ** Get the sector size of the device used to store |
| 2466 ** file. |
| 2467 */ |
| 2468 static int getSectorSize( |
| 2469 sqlite3_vfs *pVfs, |
| 2470 const char *zRelative /* UTF-8 file name */ |
| 2471 ){ |
| 2472 DWORD bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; |
| 2473 /* GetDiskFreeSpace is not supported under WINCE */ |
| 2474 #if SQLITE_OS_WINCE |
| 2475 UNUSED_PARAMETER(pVfs); |
| 2476 UNUSED_PARAMETER(zRelative); |
| 2477 #else |
| 2478 char zFullpath[MAX_PATH+1]; |
| 2479 int rc; |
| 2480 DWORD dwRet = 0; |
| 2481 DWORD dwDummy; |
| 2482 |
| 2483 /* |
| 2484 ** We need to get the full path name of the file |
| 2485 ** to get the drive letter to look up the sector |
| 2486 ** size. |
| 2487 */ |
| 2488 SimulateIOErrorBenign(1); |
| 2489 rc = winFullPathname(pVfs, zRelative, MAX_PATH, zFullpath); |
| 2490 SimulateIOErrorBenign(0); |
| 2491 if( rc == SQLITE_OK ) |
| 2492 { |
| 2493 void *zConverted = convertUtf8Filename(zFullpath); |
| 2494 if( zConverted ){ |
| 2495 if( isNT() ){ |
| 2496 /* trim path to just drive reference */ |
| 2497 WCHAR *p = zConverted; |
| 2498 for(;*p;p++){ |
| 2499 if( *p == '\\' ){ |
| 2500 *p = '\0'; |
| 2501 break; |
| 2502 } |
| 2503 } |
| 2504 dwRet = GetDiskFreeSpaceW((WCHAR*)zConverted, |
| 2505 &dwDummy, |
| 2506 &bytesPerSector, |
| 2507 &dwDummy, |
| 2508 &dwDummy); |
| 2509 }else{ |
| 2510 /* trim path to just drive reference */ |
| 2511 char *p = (char *)zConverted; |
| 2512 for(;*p;p++){ |
| 2513 if( *p == '\\' ){ |
| 2514 *p = '\0'; |
| 2515 break; |
| 2516 } |
| 2517 } |
| 2518 dwRet = GetDiskFreeSpaceA((char*)zConverted, |
| 2519 &dwDummy, |
| 2520 &bytesPerSector, |
| 2521 &dwDummy, |
| 2522 &dwDummy); |
| 2523 } |
| 2524 free(zConverted); |
| 2525 } |
| 2526 if( !dwRet ){ |
| 2527 bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; |
| 2528 } |
| 2529 } |
| 2530 #endif |
| 2531 return (int) bytesPerSector; |
| 2532 } |
| 2533 |
| 2534 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 2535 /* |
| 2536 ** Interfaces for opening a shared library, finding entry points |
| 2537 ** within the shared library, and closing the shared library. |
| 2538 */ |
| 2539 /* |
| 2540 ** Interfaces for opening a shared library, finding entry points |
| 2541 ** within the shared library, and closing the shared library. |
| 2542 */ |
| 2543 static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ |
| 2544 HANDLE h; |
| 2545 void *zConverted = convertUtf8Filename(zFilename); |
| 2546 UNUSED_PARAMETER(pVfs); |
| 2547 if( zConverted==0 ){ |
| 2548 return 0; |
| 2549 } |
| 2550 if( isNT() ){ |
| 2551 h = LoadLibraryW((WCHAR*)zConverted); |
| 2552 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. |
| 2553 ** Since the ASCII version of these Windows API do not exist for WINCE, |
| 2554 ** it's important to not reference them for WINCE builds. |
| 2555 */ |
| 2556 #if SQLITE_OS_WINCE==0 |
| 2557 }else{ |
| 2558 h = LoadLibraryA((char*)zConverted); |
| 2559 #endif |
| 2560 } |
| 2561 free(zConverted); |
| 2562 return (void*)h; |
| 2563 } |
| 2564 static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ |
| 2565 UNUSED_PARAMETER(pVfs); |
| 2566 getLastErrorMsg(nBuf, zBufOut); |
| 2567 } |
| 2568 void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){ |
| 2569 UNUSED_PARAMETER(pVfs); |
| 2570 #if SQLITE_OS_WINCE |
| 2571 /* The GetProcAddressA() routine is only available on wince. */ |
| 2572 return (void(*)(void))GetProcAddressA((HANDLE)pHandle, zSymbol); |
| 2573 #else |
| 2574 /* All other windows platforms expect GetProcAddress() to take |
| 2575 ** an Ansi string regardless of the _UNICODE setting */ |
| 2576 return (void(*)(void))GetProcAddress((HANDLE)pHandle, zSymbol); |
| 2577 #endif |
| 2578 } |
| 2579 void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
| 2580 UNUSED_PARAMETER(pVfs); |
| 2581 FreeLibrary((HANDLE)pHandle); |
| 2582 } |
| 2583 #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ |
| 2584 #define winDlOpen 0 |
| 2585 #define winDlError 0 |
| 2586 #define winDlSym 0 |
| 2587 #define winDlClose 0 |
| 2588 #endif |
| 2589 |
| 2590 |
| 2591 /* |
| 2592 ** Write up to nBuf bytes of randomness into zBuf. |
| 2593 */ |
| 2594 static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ |
| 2595 int n = 0; |
| 2596 UNUSED_PARAMETER(pVfs); |
| 2597 #if defined(SQLITE_TEST) |
| 2598 n = nBuf; |
| 2599 memset(zBuf, 0, nBuf); |
| 2600 #else |
| 2601 if( sizeof(SYSTEMTIME)<=nBuf-n ){ |
| 2602 SYSTEMTIME x; |
| 2603 GetSystemTime(&x); |
| 2604 memcpy(&zBuf[n], &x, sizeof(x)); |
| 2605 n += sizeof(x); |
| 2606 } |
| 2607 if( sizeof(DWORD)<=nBuf-n ){ |
| 2608 DWORD pid = GetCurrentProcessId(); |
| 2609 memcpy(&zBuf[n], &pid, sizeof(pid)); |
| 2610 n += sizeof(pid); |
| 2611 } |
| 2612 if( sizeof(DWORD)<=nBuf-n ){ |
| 2613 DWORD cnt = GetTickCount(); |
| 2614 memcpy(&zBuf[n], &cnt, sizeof(cnt)); |
| 2615 n += sizeof(cnt); |
| 2616 } |
| 2617 if( sizeof(LARGE_INTEGER)<=nBuf-n ){ |
| 2618 LARGE_INTEGER i; |
| 2619 QueryPerformanceCounter(&i); |
| 2620 memcpy(&zBuf[n], &i, sizeof(i)); |
| 2621 n += sizeof(i); |
| 2622 } |
| 2623 #endif |
| 2624 return n; |
| 2625 } |
| 2626 |
| 2627 |
| 2628 /* |
| 2629 ** Sleep for a little while. Return the amount of time slept. |
| 2630 */ |
| 2631 static int winSleep(sqlite3_vfs *pVfs, int microsec){ |
| 2632 Sleep((microsec+999)/1000); |
| 2633 UNUSED_PARAMETER(pVfs); |
| 2634 return ((microsec+999)/1000)*1000; |
| 2635 } |
| 2636 |
| 2637 /* |
| 2638 ** The following variable, if set to a non-zero value, is interpreted as |
| 2639 ** the number of seconds since 1970 and is used to set the result of |
| 2640 ** sqlite3OsCurrentTime() during testing. |
| 2641 */ |
| 2642 #ifdef SQLITE_TEST |
| 2643 int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ |
| 2644 #endif |
| 2645 |
| 2646 /* |
| 2647 ** Find the current time (in Universal Coordinated Time). Write into *piNow |
| 2648 ** the current time and date as a Julian Day number times 86_400_000. In |
| 2649 ** other words, write into *piNow the number of milliseconds since the Julian |
| 2650 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the |
| 2651 ** proleptic Gregorian calendar. |
| 2652 ** |
| 2653 ** On success, return 0. Return 1 if the time and date cannot be found. |
| 2654 */ |
| 2655 static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ |
| 2656 /* FILETIME structure is a 64-bit value representing the number of |
| 2657 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). |
| 2658 */ |
| 2659 FILETIME ft; |
| 2660 static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; |
| 2661 #ifdef SQLITE_TEST |
| 2662 static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; |
| 2663 #endif |
| 2664 /* 2^32 - to avoid use of LL and warnings in gcc */ |
| 2665 static const sqlite3_int64 max32BitValue = |
| 2666 (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294
967296; |
| 2667 |
| 2668 #if SQLITE_OS_WINCE |
| 2669 SYSTEMTIME time; |
| 2670 GetSystemTime(&time); |
| 2671 /* if SystemTimeToFileTime() fails, it returns zero. */ |
| 2672 if (!SystemTimeToFileTime(&time,&ft)){ |
| 2673 return 1; |
| 2674 } |
| 2675 #else |
| 2676 GetSystemTimeAsFileTime( &ft ); |
| 2677 #endif |
| 2678 |
| 2679 *piNow = winFiletimeEpoch + |
| 2680 ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + |
| 2681 (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000; |
| 2682 |
| 2683 #ifdef SQLITE_TEST |
| 2684 if( sqlite3_current_time ){ |
| 2685 *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; |
| 2686 } |
| 2687 #endif |
| 2688 UNUSED_PARAMETER(pVfs); |
| 2689 return 0; |
| 2690 } |
| 2691 |
| 2692 /* |
| 2693 ** Find the current time (in Universal Coordinated Time). Write the |
| 2694 ** current time and date as a Julian Day number into *prNow and |
| 2695 ** return 0. Return 1 if the time and date cannot be found. |
| 2696 */ |
| 2697 int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ |
| 2698 int rc; |
| 2699 sqlite3_int64 i; |
| 2700 rc = winCurrentTimeInt64(pVfs, &i); |
| 2701 if( !rc ){ |
| 2702 *prNow = i/86400000.0; |
| 2703 } |
| 2704 return rc; |
| 2705 } |
| 2706 |
| 2707 /* |
| 2708 ** The idea is that this function works like a combination of |
| 2709 ** GetLastError() and FormatMessage() on windows (or errno and |
| 2710 ** strerror_r() on unix). After an error is returned by an OS |
| 2711 ** function, SQLite calls this function with zBuf pointing to |
| 2712 ** a buffer of nBuf bytes. The OS layer should populate the |
| 2713 ** buffer with a nul-terminated UTF-8 encoded error message |
| 2714 ** describing the last IO error to have occurred within the calling |
| 2715 ** thread. |
| 2716 ** |
| 2717 ** If the error message is too large for the supplied buffer, |
| 2718 ** it should be truncated. The return value of xGetLastError |
| 2719 ** is zero if the error message fits in the buffer, or non-zero |
| 2720 ** otherwise (if the message was truncated). If non-zero is returned, |
| 2721 ** then it is not necessary to include the nul-terminator character |
| 2722 ** in the output buffer. |
| 2723 ** |
| 2724 ** Not supplying an error message will have no adverse effect |
| 2725 ** on SQLite. It is fine to have an implementation that never |
| 2726 ** returns an error message: |
| 2727 ** |
| 2728 ** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ |
| 2729 ** assert(zBuf[0]=='\0'); |
| 2730 ** return 0; |
| 2731 ** } |
| 2732 ** |
| 2733 ** However if an error message is supplied, it will be incorporated |
| 2734 ** by sqlite into the error message available to the user using |
| 2735 ** sqlite3_errmsg(), possibly making IO errors easier to debug. |
| 2736 */ |
| 2737 static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ |
| 2738 UNUSED_PARAMETER(pVfs); |
| 2739 return getLastErrorMsg(nBuf, zBuf); |
| 2740 } |
| 2741 |
| 2742 |
| 2743 |
| 2744 /* |
| 2745 ** Initialize and deinitialize the operating system interface. |
| 2746 */ |
| 2747 int sqlite3_os_init(void){ |
| 2748 static sqlite3_vfs winVfs = { |
| 2749 3, /* iVersion */ |
| 2750 sizeof(winFile), /* szOsFile */ |
| 2751 MAX_PATH, /* mxPathname */ |
| 2752 0, /* pNext */ |
| 2753 "win32", /* zName */ |
| 2754 0, /* pAppData */ |
| 2755 winOpen, /* xOpen */ |
| 2756 winDelete, /* xDelete */ |
| 2757 winAccess, /* xAccess */ |
| 2758 winFullPathname, /* xFullPathname */ |
| 2759 winDlOpen, /* xDlOpen */ |
| 2760 winDlError, /* xDlError */ |
| 2761 winDlSym, /* xDlSym */ |
| 2762 winDlClose, /* xDlClose */ |
| 2763 winRandomness, /* xRandomness */ |
| 2764 winSleep, /* xSleep */ |
| 2765 winCurrentTime, /* xCurrentTime */ |
| 2766 winGetLastError, /* xGetLastError */ |
| 2767 winCurrentTimeInt64, /* xCurrentTimeInt64 */ |
| 2768 0, /* xSetSystemCall */ |
| 2769 0, /* xGetSystemCall */ |
| 2770 0, /* xNextSystemCall */ |
| 2771 }; |
| 2772 |
| 2773 #ifndef SQLITE_OMIT_WAL |
| 2774 /* get memory map allocation granularity */ |
| 2775 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); |
| 2776 GetSystemInfo(&winSysInfo); |
| 2777 assert(winSysInfo.dwAllocationGranularity > 0); |
| 2778 #endif |
| 2779 |
| 2780 sqlite3_vfs_register(&winVfs, 1); |
| 2781 return SQLITE_OK; |
| 2782 } |
| 2783 int sqlite3_os_end(void){ |
| 2784 return SQLITE_OK; |
| 2785 } |
| 2786 |
| 2787 #endif /* SQLITE_OS_WIN */ |
OLD | NEW |