| 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 GetDiskFreeSpaceW() 0 | |
| 77 #endif | |
| 78 | |
| 79 /* | |
| 80 ** WinCE lacks native support for file locking so we have to fake it | |
| 81 ** with some code of our own. | |
| 82 */ | |
| 83 #if SQLITE_OS_WINCE | |
| 84 typedef struct winceLock { | |
| 85 int nReaders; /* Number of reader locks obtained */ | |
| 86 BOOL bPending; /* Indicates a pending lock has been obtained */ | |
| 87 BOOL bReserved; /* Indicates a reserved lock has been obtained */ | |
| 88 BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ | |
| 89 } winceLock; | |
| 90 #endif | |
| 91 | |
| 92 /* | |
| 93 ** The winFile structure is a subclass of sqlite3_file* specific to the win32 | |
| 94 ** portability layer. | |
| 95 */ | |
| 96 typedef struct winFile winFile; | |
| 97 struct winFile { | |
| 98 const sqlite3_io_methods *pMethod;/* Must be first */ | |
| 99 HANDLE h; /* Handle for accessing the file */ | |
| 100 unsigned char locktype; /* Type of lock currently held on this file */ | |
| 101 short sharedLockByte; /* Randomly chosen byte used as a shared lock */ | |
| 102 DWORD lastErrno; /* The Windows errno from the last I/O error */ | |
| 103 DWORD sectorSize; /* Sector size of the device file is on */ | |
| 104 #if SQLITE_OS_WINCE | |
| 105 WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ | |
| 106 HANDLE hMutex; /* Mutex used to control access to shared lock */ | |
| 107 HANDLE hShared; /* Shared memory segment used for locking */ | |
| 108 winceLock local; /* Locks obtained by this instance of winFile */ | |
| 109 winceLock *shared; /* Global shared lock memory for the file */ | |
| 110 #endif | |
| 111 }; | |
| 112 | |
| 113 /* | |
| 114 ** Forward prototypes. | |
| 115 */ | |
| 116 static int getSectorSize( | |
| 117 sqlite3_vfs *pVfs, | |
| 118 const char *zRelative /* UTF-8 file name */ | |
| 119 ); | |
| 120 | |
| 121 /* | |
| 122 ** The following variable is (normally) set once and never changes | |
| 123 ** thereafter. It records whether the operating system is Win95 | |
| 124 ** or WinNT. | |
| 125 ** | |
| 126 ** 0: Operating system unknown. | |
| 127 ** 1: Operating system is Win95. | |
| 128 ** 2: Operating system is WinNT. | |
| 129 ** | |
| 130 ** In order to facilitate testing on a WinNT system, the test fixture | |
| 131 ** can manually set this value to 1 to emulate Win98 behavior. | |
| 132 */ | |
| 133 #ifdef SQLITE_TEST | |
| 134 int sqlite3_os_type = 0; | |
| 135 #else | |
| 136 static int sqlite3_os_type = 0; | |
| 137 #endif | |
| 138 | |
| 139 /* | |
| 140 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, | |
| 141 ** or WinCE. Return false (zero) for Win95, Win98, or WinME. | |
| 142 ** | |
| 143 ** Here is an interesting observation: Win95, Win98, and WinME lack | |
| 144 ** the LockFileEx() API. But we can still statically link against that | |
| 145 ** API as long as we don't call it when running Win95/98/ME. A call to | |
| 146 ** this routine is used to determine if the host is Win95/98/ME or | |
| 147 ** WinNT/2K/XP so that we will know whether or not we can safely call | |
| 148 ** the LockFileEx() API. | |
| 149 */ | |
| 150 #if SQLITE_OS_WINCE | |
| 151 # define isNT() (1) | |
| 152 #else | |
| 153 static int isNT(void){ | |
| 154 if( sqlite3_os_type==0 ){ | |
| 155 OSVERSIONINFO sInfo; | |
| 156 sInfo.dwOSVersionInfoSize = sizeof(sInfo); | |
| 157 GetVersionEx(&sInfo); | |
| 158 sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; | |
| 159 } | |
| 160 return sqlite3_os_type==2; | |
| 161 } | |
| 162 #endif /* SQLITE_OS_WINCE */ | |
| 163 | |
| 164 /* | |
| 165 ** Convert a UTF-8 string to microsoft unicode (UTF-16?). | |
| 166 ** | |
| 167 ** Space to hold the returned string is obtained from malloc. | |
| 168 */ | |
| 169 static WCHAR *utf8ToUnicode(const char *zFilename){ | |
| 170 int nChar; | |
| 171 WCHAR *zWideFilename; | |
| 172 | |
| 173 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); | |
| 174 zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) ); | |
| 175 if( zWideFilename==0 ){ | |
| 176 return 0; | |
| 177 } | |
| 178 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); | |
| 179 if( nChar==0 ){ | |
| 180 free(zWideFilename); | |
| 181 zWideFilename = 0; | |
| 182 } | |
| 183 return zWideFilename; | |
| 184 } | |
| 185 | |
| 186 /* | |
| 187 ** Convert microsoft unicode to UTF-8. Space to hold the returned string is | |
| 188 ** obtained from malloc(). | |
| 189 */ | |
| 190 static char *unicodeToUtf8(const WCHAR *zWideFilename){ | |
| 191 int nByte; | |
| 192 char *zFilename; | |
| 193 | |
| 194 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); | |
| 195 zFilename = malloc( nByte ); | |
| 196 if( zFilename==0 ){ | |
| 197 return 0; | |
| 198 } | |
| 199 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, | |
| 200 0, 0); | |
| 201 if( nByte == 0 ){ | |
| 202 free(zFilename); | |
| 203 zFilename = 0; | |
| 204 } | |
| 205 return zFilename; | |
| 206 } | |
| 207 | |
| 208 /* | |
| 209 ** Convert an ansi string to microsoft unicode, based on the | |
| 210 ** current codepage settings for file apis. | |
| 211 ** | |
| 212 ** Space to hold the returned string is obtained | |
| 213 ** from malloc. | |
| 214 */ | |
| 215 static WCHAR *mbcsToUnicode(const char *zFilename){ | |
| 216 int nByte; | |
| 217 WCHAR *zMbcsFilename; | |
| 218 int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; | |
| 219 | |
| 220 nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); | |
| 221 zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) ); | |
| 222 if( zMbcsFilename==0 ){ | |
| 223 return 0; | |
| 224 } | |
| 225 nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); | |
| 226 if( nByte==0 ){ | |
| 227 free(zMbcsFilename); | |
| 228 zMbcsFilename = 0; | |
| 229 } | |
| 230 return zMbcsFilename; | |
| 231 } | |
| 232 | |
| 233 /* | |
| 234 ** Convert microsoft unicode to multibyte character string, based on the | |
| 235 ** user's Ansi codepage. | |
| 236 ** | |
| 237 ** Space to hold the returned string is obtained from | |
| 238 ** malloc(). | |
| 239 */ | |
| 240 static char *unicodeToMbcs(const WCHAR *zWideFilename){ | |
| 241 int nByte; | |
| 242 char *zFilename; | |
| 243 int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; | |
| 244 | |
| 245 nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); | |
| 246 zFilename = malloc( nByte ); | |
| 247 if( zFilename==0 ){ | |
| 248 return 0; | |
| 249 } | |
| 250 nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, | |
| 251 0, 0); | |
| 252 if( nByte == 0 ){ | |
| 253 free(zFilename); | |
| 254 zFilename = 0; | |
| 255 } | |
| 256 return zFilename; | |
| 257 } | |
| 258 | |
| 259 /* | |
| 260 ** Convert multibyte character string to UTF-8. Space to hold the | |
| 261 ** returned string is obtained from malloc(). | |
| 262 */ | |
| 263 char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ | |
| 264 char *zFilenameUtf8; | |
| 265 WCHAR *zTmpWide; | |
| 266 | |
| 267 zTmpWide = mbcsToUnicode(zFilename); | |
| 268 if( zTmpWide==0 ){ | |
| 269 return 0; | |
| 270 } | |
| 271 zFilenameUtf8 = unicodeToUtf8(zTmpWide); | |
| 272 free(zTmpWide); | |
| 273 return zFilenameUtf8; | |
| 274 } | |
| 275 | |
| 276 /* | |
| 277 ** Convert UTF-8 to multibyte character string. Space to hold the | |
| 278 ** returned string is obtained from malloc(). | |
| 279 */ | |
| 280 static char *utf8ToMbcs(const char *zFilename){ | |
| 281 char *zFilenameMbcs; | |
| 282 WCHAR *zTmpWide; | |
| 283 | |
| 284 zTmpWide = utf8ToUnicode(zFilename); | |
| 285 if( zTmpWide==0 ){ | |
| 286 return 0; | |
| 287 } | |
| 288 zFilenameMbcs = unicodeToMbcs(zTmpWide); | |
| 289 free(zTmpWide); | |
| 290 return zFilenameMbcs; | |
| 291 } | |
| 292 | |
| 293 #if SQLITE_OS_WINCE | |
| 294 /************************************************************************* | |
| 295 ** This section contains code for WinCE only. | |
| 296 */ | |
| 297 /* | |
| 298 ** WindowsCE does not have a localtime() function. So create a | |
| 299 ** substitute. | |
| 300 */ | |
| 301 #include <time.h> | |
| 302 struct tm *__cdecl localtime(const time_t *t) | |
| 303 { | |
| 304 static struct tm y; | |
| 305 FILETIME uTm, lTm; | |
| 306 SYSTEMTIME pTm; | |
| 307 sqlite3_int64 t64; | |
| 308 t64 = *t; | |
| 309 t64 = (t64 + 11644473600)*10000000; | |
| 310 uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); | |
| 311 uTm.dwHighDateTime= (DWORD)(t64 >> 32); | |
| 312 FileTimeToLocalFileTime(&uTm,&lTm); | |
| 313 FileTimeToSystemTime(&lTm,&pTm); | |
| 314 y.tm_year = pTm.wYear - 1900; | |
| 315 y.tm_mon = pTm.wMonth - 1; | |
| 316 y.tm_wday = pTm.wDayOfWeek; | |
| 317 y.tm_mday = pTm.wDay; | |
| 318 y.tm_hour = pTm.wHour; | |
| 319 y.tm_min = pTm.wMinute; | |
| 320 y.tm_sec = pTm.wSecond; | |
| 321 return &y; | |
| 322 } | |
| 323 | |
| 324 /* This will never be called, but defined to make the code compile */ | |
| 325 #define GetTempPathA(a,b) | |
| 326 | |
| 327 #define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) | |
| 328 #define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) | |
| 329 #define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) | |
| 330 | |
| 331 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] | |
| 332 | |
| 333 /* | |
| 334 ** Acquire a lock on the handle h | |
| 335 */ | |
| 336 static void winceMutexAcquire(HANDLE h){ | |
| 337 DWORD dwErr; | |
| 338 do { | |
| 339 dwErr = WaitForSingleObject(h, INFINITE); | |
| 340 } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); | |
| 341 } | |
| 342 /* | |
| 343 ** Release a lock acquired by winceMutexAcquire() | |
| 344 */ | |
| 345 #define winceMutexRelease(h) ReleaseMutex(h) | |
| 346 | |
| 347 /* | |
| 348 ** Create the mutex and shared memory used for locking in the file | |
| 349 ** descriptor pFile | |
| 350 */ | |
| 351 static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ | |
| 352 WCHAR *zTok; | |
| 353 WCHAR *zName = utf8ToUnicode(zFilename); | |
| 354 BOOL bInit = TRUE; | |
| 355 | |
| 356 /* Initialize the local lockdata */ | |
| 357 ZeroMemory(&pFile->local, sizeof(pFile->local)); | |
| 358 | |
| 359 /* Replace the backslashes from the filename and lowercase it | |
| 360 ** to derive a mutex name. */ | |
| 361 zTok = CharLowerW(zName); | |
| 362 for (;*zTok;zTok++){ | |
| 363 if (*zTok == '\\') *zTok = '_'; | |
| 364 } | |
| 365 | |
| 366 /* Create/open the named mutex */ | |
| 367 pFile->hMutex = CreateMutexW(NULL, FALSE, zName); | |
| 368 if (!pFile->hMutex){ | |
| 369 pFile->lastErrno = GetLastError(); | |
| 370 free(zName); | |
| 371 return FALSE; | |
| 372 } | |
| 373 | |
| 374 /* Acquire the mutex before continuing */ | |
| 375 winceMutexAcquire(pFile->hMutex); | |
| 376 | |
| 377 /* Since the names of named mutexes, semaphores, file mappings etc are | |
| 378 ** case-sensitive, take advantage of that by uppercasing the mutex name | |
| 379 ** and using that as the shared filemapping name. | |
| 380 */ | |
| 381 CharUpperW(zName); | |
| 382 pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, | |
| 383 PAGE_READWRITE, 0, sizeof(winceLock), | |
| 384 zName); | |
| 385 | |
| 386 /* Set a flag that indicates we're the first to create the memory so it | |
| 387 ** must be zero-initialized */ | |
| 388 if (GetLastError() == ERROR_ALREADY_EXISTS){ | |
| 389 bInit = FALSE; | |
| 390 } | |
| 391 | |
| 392 free(zName); | |
| 393 | |
| 394 /* If we succeeded in making the shared memory handle, map it. */ | |
| 395 if (pFile->hShared){ | |
| 396 pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, | |
| 397 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); | |
| 398 /* If mapping failed, close the shared memory handle and erase it */ | |
| 399 if (!pFile->shared){ | |
| 400 pFile->lastErrno = GetLastError(); | |
| 401 CloseHandle(pFile->hShared); | |
| 402 pFile->hShared = NULL; | |
| 403 } | |
| 404 } | |
| 405 | |
| 406 /* If shared memory could not be created, then close the mutex and fail */ | |
| 407 if (pFile->hShared == NULL){ | |
| 408 winceMutexRelease(pFile->hMutex); | |
| 409 CloseHandle(pFile->hMutex); | |
| 410 pFile->hMutex = NULL; | |
| 411 return FALSE; | |
| 412 } | |
| 413 | |
| 414 /* Initialize the shared memory if we're supposed to */ | |
| 415 if (bInit) { | |
| 416 ZeroMemory(pFile->shared, sizeof(winceLock)); | |
| 417 } | |
| 418 | |
| 419 winceMutexRelease(pFile->hMutex); | |
| 420 return TRUE; | |
| 421 } | |
| 422 | |
| 423 /* | |
| 424 ** Destroy the part of winFile that deals with wince locks | |
| 425 */ | |
| 426 static void winceDestroyLock(winFile *pFile){ | |
| 427 if (pFile->hMutex){ | |
| 428 /* Acquire the mutex */ | |
| 429 winceMutexAcquire(pFile->hMutex); | |
| 430 | |
| 431 /* The following blocks should probably assert in debug mode, but they | |
| 432 are to cleanup in case any locks remained open */ | |
| 433 if (pFile->local.nReaders){ | |
| 434 pFile->shared->nReaders --; | |
| 435 } | |
| 436 if (pFile->local.bReserved){ | |
| 437 pFile->shared->bReserved = FALSE; | |
| 438 } | |
| 439 if (pFile->local.bPending){ | |
| 440 pFile->shared->bPending = FALSE; | |
| 441 } | |
| 442 if (pFile->local.bExclusive){ | |
| 443 pFile->shared->bExclusive = FALSE; | |
| 444 } | |
| 445 | |
| 446 /* De-reference and close our copy of the shared memory handle */ | |
| 447 UnmapViewOfFile(pFile->shared); | |
| 448 CloseHandle(pFile->hShared); | |
| 449 | |
| 450 /* Done with the mutex */ | |
| 451 winceMutexRelease(pFile->hMutex); | |
| 452 CloseHandle(pFile->hMutex); | |
| 453 pFile->hMutex = NULL; | |
| 454 } | |
| 455 } | |
| 456 | |
| 457 /* | |
| 458 ** An implementation of the LockFile() API of windows for wince | |
| 459 */ | |
| 460 static BOOL winceLockFile( | |
| 461 HANDLE *phFile, | |
| 462 DWORD dwFileOffsetLow, | |
| 463 DWORD dwFileOffsetHigh, | |
| 464 DWORD nNumberOfBytesToLockLow, | |
| 465 DWORD nNumberOfBytesToLockHigh | |
| 466 ){ | |
| 467 winFile *pFile = HANDLE_TO_WINFILE(phFile); | |
| 468 BOOL bReturn = FALSE; | |
| 469 | |
| 470 UNUSED_PARAMETER(dwFileOffsetHigh); | |
| 471 UNUSED_PARAMETER(nNumberOfBytesToLockHigh); | |
| 472 | |
| 473 if (!pFile->hMutex) return TRUE; | |
| 474 winceMutexAcquire(pFile->hMutex); | |
| 475 | |
| 476 /* Wanting an exclusive lock? */ | |
| 477 if (dwFileOffsetLow == (DWORD)SHARED_FIRST | |
| 478 && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ | |
| 479 if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ | |
| 480 pFile->shared->bExclusive = TRUE; | |
| 481 pFile->local.bExclusive = TRUE; | |
| 482 bReturn = TRUE; | |
| 483 } | |
| 484 } | |
| 485 | |
| 486 /* Want a read-only lock? */ | |
| 487 else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && | |
| 488 nNumberOfBytesToLockLow == 1){ | |
| 489 if (pFile->shared->bExclusive == 0){ | |
| 490 pFile->local.nReaders ++; | |
| 491 if (pFile->local.nReaders == 1){ | |
| 492 pFile->shared->nReaders ++; | |
| 493 } | |
| 494 bReturn = TRUE; | |
| 495 } | |
| 496 } | |
| 497 | |
| 498 /* Want a pending lock? */ | |
| 499 else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow ==
1){ | |
| 500 /* If no pending lock has been acquired, then acquire it */ | |
| 501 if (pFile->shared->bPending == 0) { | |
| 502 pFile->shared->bPending = TRUE; | |
| 503 pFile->local.bPending = TRUE; | |
| 504 bReturn = TRUE; | |
| 505 } | |
| 506 } | |
| 507 | |
| 508 /* Want a reserved lock? */ | |
| 509 else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow ==
1){ | |
| 510 if (pFile->shared->bReserved == 0) { | |
| 511 pFile->shared->bReserved = TRUE; | |
| 512 pFile->local.bReserved = TRUE; | |
| 513 bReturn = TRUE; | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 winceMutexRelease(pFile->hMutex); | |
| 518 return bReturn; | |
| 519 } | |
| 520 | |
| 521 /* | |
| 522 ** An implementation of the UnlockFile API of windows for wince | |
| 523 */ | |
| 524 static BOOL winceUnlockFile( | |
| 525 HANDLE *phFile, | |
| 526 DWORD dwFileOffsetLow, | |
| 527 DWORD dwFileOffsetHigh, | |
| 528 DWORD nNumberOfBytesToUnlockLow, | |
| 529 DWORD nNumberOfBytesToUnlockHigh | |
| 530 ){ | |
| 531 winFile *pFile = HANDLE_TO_WINFILE(phFile); | |
| 532 BOOL bReturn = FALSE; | |
| 533 | |
| 534 UNUSED_PARAMETER(dwFileOffsetHigh); | |
| 535 UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); | |
| 536 | |
| 537 if (!pFile->hMutex) return TRUE; | |
| 538 winceMutexAcquire(pFile->hMutex); | |
| 539 | |
| 540 /* Releasing a reader lock or an exclusive lock */ | |
| 541 if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ | |
| 542 /* Did we have an exclusive lock? */ | |
| 543 if (pFile->local.bExclusive){ | |
| 544 assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); | |
| 545 pFile->local.bExclusive = FALSE; | |
| 546 pFile->shared->bExclusive = FALSE; | |
| 547 bReturn = TRUE; | |
| 548 } | |
| 549 | |
| 550 /* Did we just have a reader lock? */ | |
| 551 else if (pFile->local.nReaders){ | |
| 552 assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesTo
UnlockLow == 1); | |
| 553 pFile->local.nReaders --; | |
| 554 if (pFile->local.nReaders == 0) | |
| 555 { | |
| 556 pFile->shared->nReaders --; | |
| 557 } | |
| 558 bReturn = TRUE; | |
| 559 } | |
| 560 } | |
| 561 | |
| 562 /* Releasing a pending lock */ | |
| 563 else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow =
= 1){ | |
| 564 if (pFile->local.bPending){ | |
| 565 pFile->local.bPending = FALSE; | |
| 566 pFile->shared->bPending = FALSE; | |
| 567 bReturn = TRUE; | |
| 568 } | |
| 569 } | |
| 570 /* Releasing a reserved lock */ | |
| 571 else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow
== 1){ | |
| 572 if (pFile->local.bReserved) { | |
| 573 pFile->local.bReserved = FALSE; | |
| 574 pFile->shared->bReserved = FALSE; | |
| 575 bReturn = TRUE; | |
| 576 } | |
| 577 } | |
| 578 | |
| 579 winceMutexRelease(pFile->hMutex); | |
| 580 return bReturn; | |
| 581 } | |
| 582 | |
| 583 /* | |
| 584 ** An implementation of the LockFileEx() API of windows for wince | |
| 585 */ | |
| 586 static BOOL winceLockFileEx( | |
| 587 HANDLE *phFile, | |
| 588 DWORD dwFlags, | |
| 589 DWORD dwReserved, | |
| 590 DWORD nNumberOfBytesToLockLow, | |
| 591 DWORD nNumberOfBytesToLockHigh, | |
| 592 LPOVERLAPPED lpOverlapped | |
| 593 ){ | |
| 594 UNUSED_PARAMETER(dwReserved); | |
| 595 UNUSED_PARAMETER(nNumberOfBytesToLockHigh); | |
| 596 | |
| 597 /* If the caller wants a shared read lock, forward this call | |
| 598 ** to winceLockFile */ | |
| 599 if (lpOverlapped->Offset == (DWORD)SHARED_FIRST && | |
| 600 dwFlags == 1 && | |
| 601 nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ | |
| 602 return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); | |
| 603 } | |
| 604 return FALSE; | |
| 605 } | |
| 606 /* | |
| 607 ** End of the special code for wince | |
| 608 *****************************************************************************/ | |
| 609 #endif /* SQLITE_OS_WINCE */ | |
| 610 | |
| 611 /***************************************************************************** | |
| 612 ** The next group of routines implement the I/O methods specified | |
| 613 ** by the sqlite3_io_methods object. | |
| 614 ******************************************************************************/ | |
| 615 | |
| 616 /* | |
| 617 ** Close a file. | |
| 618 ** | |
| 619 ** It is reported that an attempt to close a handle might sometimes | |
| 620 ** fail. This is a very unreasonable result, but windows is notorious | |
| 621 ** for being unreasonable so I do not doubt that it might happen. If | |
| 622 ** the close fails, we pause for 100 milliseconds and try again. As | |
| 623 ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before | |
| 624 ** giving up and returning an error. | |
| 625 */ | |
| 626 #define MX_CLOSE_ATTEMPT 3 | |
| 627 static int winClose(sqlite3_file *id){ | |
| 628 int rc, cnt = 0; | |
| 629 winFile *pFile = (winFile*)id; | |
| 630 | |
| 631 assert( id!=0 ); | |
| 632 OSTRACE2("CLOSE %d\n", pFile->h); | |
| 633 do{ | |
| 634 rc = CloseHandle(pFile->h); | |
| 635 }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); | |
| 636 #if SQLITE_OS_WINCE | |
| 637 #define WINCE_DELETION_ATTEMPTS 3 | |
| 638 winceDestroyLock(pFile); | |
| 639 if( pFile->zDeleteOnClose ){ | |
| 640 int cnt = 0; | |
| 641 while( | |
| 642 DeleteFileW(pFile->zDeleteOnClose)==0 | |
| 643 && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff | |
| 644 && cnt++ < WINCE_DELETION_ATTEMPTS | |
| 645 ){ | |
| 646 Sleep(100); /* Wait a little before trying again */ | |
| 647 } | |
| 648 free(pFile->zDeleteOnClose); | |
| 649 } | |
| 650 #endif | |
| 651 OpenCounter(-1); | |
| 652 return rc ? SQLITE_OK : SQLITE_IOERR; | |
| 653 } | |
| 654 | |
| 655 /* | |
| 656 ** Some microsoft compilers lack this definition. | |
| 657 */ | |
| 658 #ifndef INVALID_SET_FILE_POINTER | |
| 659 # define INVALID_SET_FILE_POINTER ((DWORD)-1) | |
| 660 #endif | |
| 661 | |
| 662 /* | |
| 663 ** Read data from a file into a buffer. Return SQLITE_OK if all | |
| 664 ** bytes were read successfully and SQLITE_IOERR if anything goes | |
| 665 ** wrong. | |
| 666 */ | |
| 667 static int winRead( | |
| 668 sqlite3_file *id, /* File to read from */ | |
| 669 void *pBuf, /* Write content into this buffer */ | |
| 670 int amt, /* Number of bytes to read */ | |
| 671 sqlite3_int64 offset /* Begin reading at this offset */ | |
| 672 ){ | |
| 673 LONG upperBits = (LONG)((offset>>32) & 0x7fffffff); | |
| 674 LONG lowerBits = (LONG)(offset & 0xffffffff); | |
| 675 DWORD rc; | |
| 676 winFile *pFile = (winFile*)id; | |
| 677 DWORD error; | |
| 678 DWORD got; | |
| 679 | |
| 680 assert( id!=0 ); | |
| 681 SimulateIOError(return SQLITE_IOERR_READ); | |
| 682 OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype); | |
| 683 rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); | |
| 684 if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ | |
| 685 pFile->lastErrno = error; | |
| 686 return SQLITE_FULL; | |
| 687 } | |
| 688 if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){ | |
| 689 pFile->lastErrno = GetLastError(); | |
| 690 return SQLITE_IOERR_READ; | |
| 691 } | |
| 692 if( got==(DWORD)amt ){ | |
| 693 return SQLITE_OK; | |
| 694 }else{ | |
| 695 /* Unread parts of the buffer must be zero-filled */ | |
| 696 memset(&((char*)pBuf)[got], 0, amt-got); | |
| 697 return SQLITE_IOERR_SHORT_READ; | |
| 698 } | |
| 699 } | |
| 700 | |
| 701 /* | |
| 702 ** Write data from a buffer into a file. Return SQLITE_OK on success | |
| 703 ** or some other error code on failure. | |
| 704 */ | |
| 705 static int winWrite( | |
| 706 sqlite3_file *id, /* File to write into */ | |
| 707 const void *pBuf, /* The bytes to be written */ | |
| 708 int amt, /* Number of bytes to write */ | |
| 709 sqlite3_int64 offset /* Offset into the file to begin writing at */ | |
| 710 ){ | |
| 711 LONG upperBits = (LONG)((offset>>32) & 0x7fffffff); | |
| 712 LONG lowerBits = (LONG)(offset & 0xffffffff); | |
| 713 DWORD rc; | |
| 714 winFile *pFile = (winFile*)id; | |
| 715 DWORD error; | |
| 716 DWORD wrote = 0; | |
| 717 | |
| 718 assert( id!=0 ); | |
| 719 SimulateIOError(return SQLITE_IOERR_WRITE); | |
| 720 SimulateDiskfullError(return SQLITE_FULL); | |
| 721 OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype); | |
| 722 rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); | |
| 723 if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ | |
| 724 pFile->lastErrno = error; | |
| 725 return SQLITE_FULL; | |
| 726 } | |
| 727 assert( amt>0 ); | |
| 728 while( | |
| 729 amt>0 | |
| 730 && (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0 | |
| 731 && wrote>0 | |
| 732 ){ | |
| 733 amt -= wrote; | |
| 734 pBuf = &((char*)pBuf)[wrote]; | |
| 735 } | |
| 736 if( !rc || amt>(int)wrote ){ | |
| 737 pFile->lastErrno = GetLastError(); | |
| 738 return SQLITE_FULL; | |
| 739 } | |
| 740 return SQLITE_OK; | |
| 741 } | |
| 742 | |
| 743 /* | |
| 744 ** Truncate an open file to a specified size | |
| 745 */ | |
| 746 static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ | |
| 747 LONG upperBits = (LONG)((nByte>>32) & 0x7fffffff); | |
| 748 LONG lowerBits = (LONG)(nByte & 0xffffffff); | |
| 749 DWORD rc; | |
| 750 winFile *pFile = (winFile*)id; | |
| 751 DWORD error; | |
| 752 | |
| 753 assert( id!=0 ); | |
| 754 OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte); | |
| 755 SimulateIOError(return SQLITE_IOERR_TRUNCATE); | |
| 756 rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); | |
| 757 if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ | |
| 758 pFile->lastErrno = error; | |
| 759 return SQLITE_IOERR_TRUNCATE; | |
| 760 } | |
| 761 /* SetEndOfFile will fail if nByte is negative */ | |
| 762 if( !SetEndOfFile(pFile->h) ){ | |
| 763 pFile->lastErrno = GetLastError(); | |
| 764 return SQLITE_IOERR_TRUNCATE; | |
| 765 } | |
| 766 return SQLITE_OK; | |
| 767 } | |
| 768 | |
| 769 #ifdef SQLITE_TEST | |
| 770 /* | |
| 771 ** Count the number of fullsyncs and normal syncs. This is used to test | |
| 772 ** that syncs and fullsyncs are occuring at the right times. | |
| 773 */ | |
| 774 int sqlite3_sync_count = 0; | |
| 775 int sqlite3_fullsync_count = 0; | |
| 776 #endif | |
| 777 | |
| 778 /* | |
| 779 ** Make sure all writes to a particular file are committed to disk. | |
| 780 */ | |
| 781 static int winSync(sqlite3_file *id, int flags){ | |
| 782 #ifndef SQLITE_NO_SYNC | |
| 783 winFile *pFile = (winFile*)id; | |
| 784 | |
| 785 assert( id!=0 ); | |
| 786 OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype); | |
| 787 #else | |
| 788 UNUSED_PARAMETER(id); | |
| 789 #endif | |
| 790 #ifndef SQLITE_TEST | |
| 791 UNUSED_PARAMETER(flags); | |
| 792 #else | |
| 793 if( flags & SQLITE_SYNC_FULL ){ | |
| 794 sqlite3_fullsync_count++; | |
| 795 } | |
| 796 sqlite3_sync_count++; | |
| 797 #endif | |
| 798 /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a | |
| 799 ** no-op | |
| 800 */ | |
| 801 #ifdef SQLITE_NO_SYNC | |
| 802 return SQLITE_OK; | |
| 803 #else | |
| 804 if( FlushFileBuffers(pFile->h) ){ | |
| 805 return SQLITE_OK; | |
| 806 }else{ | |
| 807 pFile->lastErrno = GetLastError(); | |
| 808 return SQLITE_IOERR; | |
| 809 } | |
| 810 #endif | |
| 811 } | |
| 812 | |
| 813 /* | |
| 814 ** Determine the current size of a file in bytes | |
| 815 */ | |
| 816 static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ | |
| 817 DWORD upperBits; | |
| 818 DWORD lowerBits; | |
| 819 winFile *pFile = (winFile*)id; | |
| 820 DWORD error; | |
| 821 | |
| 822 assert( id!=0 ); | |
| 823 SimulateIOError(return SQLITE_IOERR_FSTAT); | |
| 824 lowerBits = GetFileSize(pFile->h, &upperBits); | |
| 825 if( (lowerBits == INVALID_FILE_SIZE) | |
| 826 && ((error = GetLastError()) != NO_ERROR) ) | |
| 827 { | |
| 828 pFile->lastErrno = error; | |
| 829 return SQLITE_IOERR_FSTAT; | |
| 830 } | |
| 831 *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; | |
| 832 return SQLITE_OK; | |
| 833 } | |
| 834 | |
| 835 /* | |
| 836 ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. | |
| 837 */ | |
| 838 #ifndef LOCKFILE_FAIL_IMMEDIATELY | |
| 839 # define LOCKFILE_FAIL_IMMEDIATELY 1 | |
| 840 #endif | |
| 841 | |
| 842 /* | |
| 843 ** Acquire a reader lock. | |
| 844 ** Different API routines are called depending on whether or not this | |
| 845 ** is Win95 or WinNT. | |
| 846 */ | |
| 847 static int getReadLock(winFile *pFile){ | |
| 848 int res; | |
| 849 if( isNT() ){ | |
| 850 OVERLAPPED ovlp; | |
| 851 ovlp.Offset = SHARED_FIRST; | |
| 852 ovlp.OffsetHigh = 0; | |
| 853 ovlp.hEvent = 0; | |
| 854 res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, | |
| 855 0, SHARED_SIZE, 0, &ovlp); | |
| 856 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 857 */ | |
| 858 #if SQLITE_OS_WINCE==0 | |
| 859 }else{ | |
| 860 int lk; | |
| 861 sqlite3_randomness(sizeof(lk), &lk); | |
| 862 pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); | |
| 863 res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); | |
| 864 #endif | |
| 865 } | |
| 866 if( res == 0 ){ | |
| 867 pFile->lastErrno = GetLastError(); | |
| 868 } | |
| 869 return res; | |
| 870 } | |
| 871 | |
| 872 /* | |
| 873 ** Undo a readlock | |
| 874 */ | |
| 875 static int unlockReadLock(winFile *pFile){ | |
| 876 int res; | |
| 877 if( isNT() ){ | |
| 878 res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); | |
| 879 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 880 */ | |
| 881 #if SQLITE_OS_WINCE==0 | |
| 882 }else{ | |
| 883 res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); | |
| 884 #endif | |
| 885 } | |
| 886 if( res == 0 ){ | |
| 887 pFile->lastErrno = GetLastError(); | |
| 888 } | |
| 889 return res; | |
| 890 } | |
| 891 | |
| 892 /* | |
| 893 ** Lock the file with the lock specified by parameter locktype - one | |
| 894 ** of the following: | |
| 895 ** | |
| 896 ** (1) SHARED_LOCK | |
| 897 ** (2) RESERVED_LOCK | |
| 898 ** (3) PENDING_LOCK | |
| 899 ** (4) EXCLUSIVE_LOCK | |
| 900 ** | |
| 901 ** Sometimes when requesting one lock state, additional lock states | |
| 902 ** are inserted in between. The locking might fail on one of the later | |
| 903 ** transitions leaving the lock state different from what it started but | |
| 904 ** still short of its goal. The following chart shows the allowed | |
| 905 ** transitions and the inserted intermediate states: | |
| 906 ** | |
| 907 ** UNLOCKED -> SHARED | |
| 908 ** SHARED -> RESERVED | |
| 909 ** SHARED -> (PENDING) -> EXCLUSIVE | |
| 910 ** RESERVED -> (PENDING) -> EXCLUSIVE | |
| 911 ** PENDING -> EXCLUSIVE | |
| 912 ** | |
| 913 ** This routine will only increase a lock. The winUnlock() routine | |
| 914 ** erases all locks at once and returns us immediately to locking level 0. | |
| 915 ** It is not possible to lower the locking level one step at a time. You | |
| 916 ** must go straight to locking level 0. | |
| 917 */ | |
| 918 static int winLock(sqlite3_file *id, int locktype){ | |
| 919 int rc = SQLITE_OK; /* Return code from subroutines */ | |
| 920 int res = 1; /* Result of a windows lock call */ | |
| 921 int newLocktype; /* Set pFile->locktype to this value before exiting */ | |
| 922 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ | |
| 923 winFile *pFile = (winFile*)id; | |
| 924 DWORD error = NO_ERROR; | |
| 925 | |
| 926 assert( id!=0 ); | |
| 927 OSTRACE5("LOCK %d %d was %d(%d)\n", | |
| 928 pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); | |
| 929 | |
| 930 /* If there is already a lock of this type or more restrictive on the | |
| 931 ** OsFile, do nothing. Don't use the end_lock: exit path, as | |
| 932 ** sqlite3OsEnterMutex() hasn't been called yet. | |
| 933 */ | |
| 934 if( pFile->locktype>=locktype ){ | |
| 935 return SQLITE_OK; | |
| 936 } | |
| 937 | |
| 938 /* Make sure the locking sequence is correct | |
| 939 */ | |
| 940 assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); | |
| 941 assert( locktype!=PENDING_LOCK ); | |
| 942 assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); | |
| 943 | |
| 944 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or | |
| 945 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of | |
| 946 ** the PENDING_LOCK byte is temporary. | |
| 947 */ | |
| 948 newLocktype = pFile->locktype; | |
| 949 if( (pFile->locktype==NO_LOCK) | |
| 950 || ( (locktype==EXCLUSIVE_LOCK) | |
| 951 && (pFile->locktype==RESERVED_LOCK)) | |
| 952 ){ | |
| 953 int cnt = 3; | |
| 954 while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ | |
| 955 /* Try 3 times to get the pending lock. The pending lock might be | |
| 956 ** held by another reader process who will release it momentarily. | |
| 957 */ | |
| 958 OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); | |
| 959 Sleep(1); | |
| 960 } | |
| 961 gotPendingLock = res; | |
| 962 if( !res ){ | |
| 963 error = GetLastError(); | |
| 964 } | |
| 965 } | |
| 966 | |
| 967 /* Acquire a shared lock | |
| 968 */ | |
| 969 if( locktype==SHARED_LOCK && res ){ | |
| 970 assert( pFile->locktype==NO_LOCK ); | |
| 971 res = getReadLock(pFile); | |
| 972 if( res ){ | |
| 973 newLocktype = SHARED_LOCK; | |
| 974 }else{ | |
| 975 error = GetLastError(); | |
| 976 } | |
| 977 } | |
| 978 | |
| 979 /* Acquire a RESERVED lock | |
| 980 */ | |
| 981 if( locktype==RESERVED_LOCK && res ){ | |
| 982 assert( pFile->locktype==SHARED_LOCK ); | |
| 983 res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); | |
| 984 if( res ){ | |
| 985 newLocktype = RESERVED_LOCK; | |
| 986 }else{ | |
| 987 error = GetLastError(); | |
| 988 } | |
| 989 } | |
| 990 | |
| 991 /* Acquire a PENDING lock | |
| 992 */ | |
| 993 if( locktype==EXCLUSIVE_LOCK && res ){ | |
| 994 newLocktype = PENDING_LOCK; | |
| 995 gotPendingLock = 0; | |
| 996 } | |
| 997 | |
| 998 /* Acquire an EXCLUSIVE lock | |
| 999 */ | |
| 1000 if( locktype==EXCLUSIVE_LOCK && res ){ | |
| 1001 assert( pFile->locktype>=SHARED_LOCK ); | |
| 1002 res = unlockReadLock(pFile); | |
| 1003 OSTRACE2("unreadlock = %d\n", res); | |
| 1004 res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); | |
| 1005 if( res ){ | |
| 1006 newLocktype = EXCLUSIVE_LOCK; | |
| 1007 }else{ | |
| 1008 error = GetLastError(); | |
| 1009 OSTRACE2("error-code = %d\n", error); | |
| 1010 getReadLock(pFile); | |
| 1011 } | |
| 1012 } | |
| 1013 | |
| 1014 /* If we are holding a PENDING lock that ought to be released, then | |
| 1015 ** release it now. | |
| 1016 */ | |
| 1017 if( gotPendingLock && locktype==SHARED_LOCK ){ | |
| 1018 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); | |
| 1019 } | |
| 1020 | |
| 1021 /* Update the state of the lock has held in the file descriptor then | |
| 1022 ** return the appropriate result code. | |
| 1023 */ | |
| 1024 if( res ){ | |
| 1025 rc = SQLITE_OK; | |
| 1026 }else{ | |
| 1027 OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, | |
| 1028 locktype, newLocktype); | |
| 1029 pFile->lastErrno = error; | |
| 1030 rc = SQLITE_BUSY; | |
| 1031 } | |
| 1032 pFile->locktype = (u8)newLocktype; | |
| 1033 return rc; | |
| 1034 } | |
| 1035 | |
| 1036 /* | |
| 1037 ** This routine checks if there is a RESERVED lock held on the specified | |
| 1038 ** file by this or any other process. If such a lock is held, return | |
| 1039 ** non-zero, otherwise zero. | |
| 1040 */ | |
| 1041 static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ | |
| 1042 int rc; | |
| 1043 winFile *pFile = (winFile*)id; | |
| 1044 | |
| 1045 assert( id!=0 ); | |
| 1046 if( pFile->locktype>=RESERVED_LOCK ){ | |
| 1047 rc = 1; | |
| 1048 OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); | |
| 1049 }else{ | |
| 1050 rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); | |
| 1051 if( rc ){ | |
| 1052 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); | |
| 1053 } | |
| 1054 rc = !rc; | |
| 1055 OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); | |
| 1056 } | |
| 1057 *pResOut = rc; | |
| 1058 return SQLITE_OK; | |
| 1059 } | |
| 1060 | |
| 1061 /* | |
| 1062 ** Lower the locking level on file descriptor id to locktype. locktype | |
| 1063 ** must be either NO_LOCK or SHARED_LOCK. | |
| 1064 ** | |
| 1065 ** If the locking level of the file descriptor is already at or below | |
| 1066 ** the requested locking level, this routine is a no-op. | |
| 1067 ** | |
| 1068 ** It is not possible for this routine to fail if the second argument | |
| 1069 ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine | |
| 1070 ** might return SQLITE_IOERR; | |
| 1071 */ | |
| 1072 static int winUnlock(sqlite3_file *id, int locktype){ | |
| 1073 int type; | |
| 1074 winFile *pFile = (winFile*)id; | |
| 1075 int rc = SQLITE_OK; | |
| 1076 assert( pFile!=0 ); | |
| 1077 assert( locktype<=SHARED_LOCK ); | |
| 1078 OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, | |
| 1079 pFile->locktype, pFile->sharedLockByte); | |
| 1080 type = pFile->locktype; | |
| 1081 if( type>=EXCLUSIVE_LOCK ){ | |
| 1082 UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); | |
| 1083 if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ | |
| 1084 /* This should never happen. We should always be able to | |
| 1085 ** reacquire the read lock */ | |
| 1086 rc = SQLITE_IOERR_UNLOCK; | |
| 1087 } | |
| 1088 } | |
| 1089 if( type>=RESERVED_LOCK ){ | |
| 1090 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); | |
| 1091 } | |
| 1092 if( locktype==NO_LOCK && type>=SHARED_LOCK ){ | |
| 1093 unlockReadLock(pFile); | |
| 1094 } | |
| 1095 if( type>=PENDING_LOCK ){ | |
| 1096 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); | |
| 1097 } | |
| 1098 pFile->locktype = (u8)locktype; | |
| 1099 return rc; | |
| 1100 } | |
| 1101 | |
| 1102 /* | |
| 1103 ** Control and query of the open file handle. | |
| 1104 */ | |
| 1105 static int winFileControl(sqlite3_file *id, int op, void *pArg){ | |
| 1106 switch( op ){ | |
| 1107 case SQLITE_FCNTL_LOCKSTATE: { | |
| 1108 *(int*)pArg = ((winFile*)id)->locktype; | |
| 1109 return SQLITE_OK; | |
| 1110 } | |
| 1111 case SQLITE_LAST_ERRNO: { | |
| 1112 *(int*)pArg = (int)((winFile*)id)->lastErrno; | |
| 1113 return SQLITE_OK; | |
| 1114 } | |
| 1115 } | |
| 1116 return SQLITE_ERROR; | |
| 1117 } | |
| 1118 | |
| 1119 /* | |
| 1120 ** Return the sector size in bytes of the underlying block device for | |
| 1121 ** the specified file. This is almost always 512 bytes, but may be | |
| 1122 ** larger for some devices. | |
| 1123 ** | |
| 1124 ** SQLite code assumes this function cannot fail. It also assumes that | |
| 1125 ** if two files are created in the same file-system directory (i.e. | |
| 1126 ** a database and its journal file) that the sector size will be the | |
| 1127 ** same for both. | |
| 1128 */ | |
| 1129 static int winSectorSize(sqlite3_file *id){ | |
| 1130 assert( id!=0 ); | |
| 1131 return (int)(((winFile*)id)->sectorSize); | |
| 1132 } | |
| 1133 | |
| 1134 /* | |
| 1135 ** Return a vector of device characteristics. | |
| 1136 */ | |
| 1137 static int winDeviceCharacteristics(sqlite3_file *id){ | |
| 1138 UNUSED_PARAMETER(id); | |
| 1139 return 0; | |
| 1140 } | |
| 1141 | |
| 1142 /* | |
| 1143 ** This vector defines all the methods that can operate on an | |
| 1144 ** sqlite3_file for win32. | |
| 1145 */ | |
| 1146 static const sqlite3_io_methods winIoMethod = { | |
| 1147 1, /* iVersion */ | |
| 1148 winClose, | |
| 1149 winRead, | |
| 1150 winWrite, | |
| 1151 winTruncate, | |
| 1152 winSync, | |
| 1153 winFileSize, | |
| 1154 winLock, | |
| 1155 winUnlock, | |
| 1156 winCheckReservedLock, | |
| 1157 winFileControl, | |
| 1158 winSectorSize, | |
| 1159 winDeviceCharacteristics | |
| 1160 }; | |
| 1161 | |
| 1162 /*************************************************************************** | |
| 1163 ** Here ends the I/O methods that form the sqlite3_io_methods object. | |
| 1164 ** | |
| 1165 ** The next block of code implements the VFS methods. | |
| 1166 ****************************************************************************/ | |
| 1167 | |
| 1168 /* | |
| 1169 ** Convert a UTF-8 filename into whatever form the underlying | |
| 1170 ** operating system wants filenames in. Space to hold the result | |
| 1171 ** is obtained from malloc and must be freed by the calling | |
| 1172 ** function. | |
| 1173 */ | |
| 1174 static void *convertUtf8Filename(const char *zFilename){ | |
| 1175 void *zConverted = 0; | |
| 1176 if( isNT() ){ | |
| 1177 zConverted = utf8ToUnicode(zFilename); | |
| 1178 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 1179 */ | |
| 1180 #if SQLITE_OS_WINCE==0 | |
| 1181 }else{ | |
| 1182 zConverted = utf8ToMbcs(zFilename); | |
| 1183 #endif | |
| 1184 } | |
| 1185 /* caller will handle out of memory */ | |
| 1186 return zConverted; | |
| 1187 } | |
| 1188 | |
| 1189 /* | |
| 1190 ** Create a temporary file name in zBuf. zBuf must be big enough to | |
| 1191 ** hold at pVfs->mxPathname characters. | |
| 1192 */ | |
| 1193 static int getTempname(int nBuf, char *zBuf){ | |
| 1194 static char zChars[] = | |
| 1195 "abcdefghijklmnopqrstuvwxyz" | |
| 1196 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
| 1197 "0123456789"; | |
| 1198 size_t i, j; | |
| 1199 char zTempPath[MAX_PATH+1]; | |
| 1200 if( sqlite3_temp_directory ){ | |
| 1201 sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); | |
| 1202 }else if( isNT() ){ | |
| 1203 char *zMulti; | |
| 1204 WCHAR zWidePath[MAX_PATH]; | |
| 1205 GetTempPathW(MAX_PATH-30, zWidePath); | |
| 1206 zMulti = unicodeToUtf8(zWidePath); | |
| 1207 if( zMulti ){ | |
| 1208 sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); | |
| 1209 free(zMulti); | |
| 1210 }else{ | |
| 1211 return SQLITE_NOMEM; | |
| 1212 } | |
| 1213 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 1214 ** Since the ASCII version of these Windows API do not exist for WINCE, | |
| 1215 ** it's important to not reference them for WINCE builds. | |
| 1216 */ | |
| 1217 #if SQLITE_OS_WINCE==0 | |
| 1218 }else{ | |
| 1219 char *zUtf8; | |
| 1220 char zMbcsPath[MAX_PATH]; | |
| 1221 GetTempPathA(MAX_PATH-30, zMbcsPath); | |
| 1222 zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); | |
| 1223 if( zUtf8 ){ | |
| 1224 sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); | |
| 1225 free(zUtf8); | |
| 1226 }else{ | |
| 1227 return SQLITE_NOMEM; | |
| 1228 } | |
| 1229 #endif | |
| 1230 } | |
| 1231 for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} | |
| 1232 zTempPath[i] = 0; | |
| 1233 sqlite3_snprintf(nBuf-30, zBuf, | |
| 1234 "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); | |
| 1235 j = sqlite3Strlen30(zBuf); | |
| 1236 sqlite3_randomness(20, &zBuf[j]); | |
| 1237 for(i=0; i<20; i++, j++){ | |
| 1238 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; | |
| 1239 } | |
| 1240 zBuf[j] = 0; | |
| 1241 OSTRACE2("TEMP FILENAME: %s\n", zBuf); | |
| 1242 return SQLITE_OK; | |
| 1243 } | |
| 1244 | |
| 1245 /* | |
| 1246 ** The return value of getLastErrorMsg | |
| 1247 ** is zero if the error message fits in the buffer, or non-zero | |
| 1248 ** otherwise (if the message was truncated). | |
| 1249 */ | |
| 1250 static int getLastErrorMsg(int nBuf, char *zBuf){ | |
| 1251 DWORD error = GetLastError(); | |
| 1252 | |
| 1253 #if SQLITE_OS_WINCE | |
| 1254 sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); | |
| 1255 #else | |
| 1256 /* FormatMessage returns 0 on failure. Otherwise it | |
| 1257 ** returns the number of TCHARs written to the output | |
| 1258 ** buffer, excluding the terminating null char. | |
| 1259 */ | |
| 1260 if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, | |
| 1261 NULL, | |
| 1262 error, | |
| 1263 0, | |
| 1264 zBuf, | |
| 1265 nBuf-1, | |
| 1266 0)) | |
| 1267 { | |
| 1268 sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); | |
| 1269 } | |
| 1270 #endif | |
| 1271 | |
| 1272 return 0; | |
| 1273 } | |
| 1274 | |
| 1275 /* | |
| 1276 ** Open a file. | |
| 1277 */ | |
| 1278 static int winOpen( | |
| 1279 sqlite3_vfs *pVfs, /* Not used */ | |
| 1280 const char *zName, /* Name of the file (UTF-8) */ | |
| 1281 sqlite3_file *id, /* Write the SQLite file handle here */ | |
| 1282 int flags, /* Open mode flags */ | |
| 1283 int *pOutFlags /* Status return flags */ | |
| 1284 ){ | |
| 1285 HANDLE h; | |
| 1286 DWORD dwDesiredAccess; | |
| 1287 DWORD dwShareMode; | |
| 1288 DWORD dwCreationDisposition; | |
| 1289 DWORD dwFlagsAndAttributes = 0; | |
| 1290 #if SQLITE_OS_WINCE | |
| 1291 int isTemp = 0; | |
| 1292 #endif | |
| 1293 winFile *pFile = (winFile*)id; | |
| 1294 void *zConverted; /* Filename in OS encoding */ | |
| 1295 const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ | |
| 1296 char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */ | |
| 1297 | |
| 1298 assert( id!=0 ); | |
| 1299 UNUSED_PARAMETER(pVfs); | |
| 1300 | |
| 1301 /* If the second argument to this function is NULL, generate a | |
| 1302 ** temporary file name to use | |
| 1303 */ | |
| 1304 if( !zUtf8Name ){ | |
| 1305 int rc = getTempname(MAX_PATH+1, zTmpname); | |
| 1306 if( rc!=SQLITE_OK ){ | |
| 1307 return rc; | |
| 1308 } | |
| 1309 zUtf8Name = zTmpname; | |
| 1310 } | |
| 1311 | |
| 1312 /* Convert the filename to the system encoding. */ | |
| 1313 zConverted = convertUtf8Filename(zUtf8Name); | |
| 1314 if( zConverted==0 ){ | |
| 1315 return SQLITE_NOMEM; | |
| 1316 } | |
| 1317 | |
| 1318 if( flags & SQLITE_OPEN_READWRITE ){ | |
| 1319 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; | |
| 1320 }else{ | |
| 1321 dwDesiredAccess = GENERIC_READ; | |
| 1322 } | |
| 1323 /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is | |
| 1324 ** created. SQLite doesn't use it to indicate "exclusive access" | |
| 1325 ** as it is usually understood. | |
| 1326 */ | |
| 1327 assert(!(flags & SQLITE_OPEN_EXCLUSIVE) || (flags & SQLITE_OPEN_CREATE)); | |
| 1328 if( flags & SQLITE_OPEN_EXCLUSIVE ){ | |
| 1329 /* Creates a new file, only if it does not already exist. */ | |
| 1330 /* If the file exists, it fails. */ | |
| 1331 dwCreationDisposition = CREATE_NEW; | |
| 1332 }else if( flags & SQLITE_OPEN_CREATE ){ | |
| 1333 /* Open existing file, or create if it doesn't exist */ | |
| 1334 dwCreationDisposition = OPEN_ALWAYS; | |
| 1335 }else{ | |
| 1336 /* Opens a file, only if it exists. */ | |
| 1337 dwCreationDisposition = OPEN_EXISTING; | |
| 1338 } | |
| 1339 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; | |
| 1340 if( flags & SQLITE_OPEN_DELETEONCLOSE ){ | |
| 1341 #if SQLITE_OS_WINCE | |
| 1342 dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; | |
| 1343 isTemp = 1; | |
| 1344 #else | |
| 1345 dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY | |
| 1346 | FILE_ATTRIBUTE_HIDDEN | |
| 1347 | FILE_FLAG_DELETE_ON_CLOSE; | |
| 1348 #endif | |
| 1349 }else{ | |
| 1350 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; | |
| 1351 } | |
| 1352 /* Reports from the internet are that performance is always | |
| 1353 ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ | |
| 1354 #if SQLITE_OS_WINCE | |
| 1355 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; | |
| 1356 #endif | |
| 1357 if( isNT() ){ | |
| 1358 h = CreateFileW((WCHAR*)zConverted, | |
| 1359 dwDesiredAccess, | |
| 1360 dwShareMode, | |
| 1361 NULL, | |
| 1362 dwCreationDisposition, | |
| 1363 dwFlagsAndAttributes, | |
| 1364 NULL | |
| 1365 ); | |
| 1366 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 1367 ** Since the ASCII version of these Windows API do not exist for WINCE, | |
| 1368 ** it's important to not reference them for WINCE builds. | |
| 1369 */ | |
| 1370 #if SQLITE_OS_WINCE==0 | |
| 1371 }else{ | |
| 1372 h = CreateFileA((char*)zConverted, | |
| 1373 dwDesiredAccess, | |
| 1374 dwShareMode, | |
| 1375 NULL, | |
| 1376 dwCreationDisposition, | |
| 1377 dwFlagsAndAttributes, | |
| 1378 NULL | |
| 1379 ); | |
| 1380 #endif | |
| 1381 } | |
| 1382 if( h==INVALID_HANDLE_VALUE ){ | |
| 1383 free(zConverted); | |
| 1384 if( flags & SQLITE_OPEN_READWRITE ){ | |
| 1385 return winOpen(pVfs, zName, id, | |
| 1386 ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); | |
| 1387 }else{ | |
| 1388 return SQLITE_CANTOPEN; | |
| 1389 } | |
| 1390 } | |
| 1391 if( pOutFlags ){ | |
| 1392 if( flags & SQLITE_OPEN_READWRITE ){ | |
| 1393 *pOutFlags = SQLITE_OPEN_READWRITE; | |
| 1394 }else{ | |
| 1395 *pOutFlags = SQLITE_OPEN_READONLY; | |
| 1396 } | |
| 1397 } | |
| 1398 memset(pFile, 0, sizeof(*pFile)); | |
| 1399 pFile->pMethod = &winIoMethod; | |
| 1400 pFile->h = h; | |
| 1401 pFile->lastErrno = NO_ERROR; | |
| 1402 pFile->sectorSize = getSectorSize(pVfs, zUtf8Name); | |
| 1403 #if SQLITE_OS_WINCE | |
| 1404 if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) == | |
| 1405 (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) | |
| 1406 && !winceCreateLock(zName, pFile) | |
| 1407 ){ | |
| 1408 CloseHandle(h); | |
| 1409 free(zConverted); | |
| 1410 return SQLITE_CANTOPEN; | |
| 1411 } | |
| 1412 if( isTemp ){ | |
| 1413 pFile->zDeleteOnClose = zConverted; | |
| 1414 }else | |
| 1415 #endif | |
| 1416 { | |
| 1417 free(zConverted); | |
| 1418 } | |
| 1419 OpenCounter(+1); | |
| 1420 return SQLITE_OK; | |
| 1421 } | |
| 1422 | |
| 1423 /* | |
| 1424 ** Delete the named file. | |
| 1425 ** | |
| 1426 ** Note that windows does not allow a file to be deleted if some other | |
| 1427 ** process has it open. Sometimes a virus scanner or indexing program | |
| 1428 ** will open a journal file shortly after it is created in order to do | |
| 1429 ** whatever it does. While this other process is holding the | |
| 1430 ** file open, we will be unable to delete it. To work around this | |
| 1431 ** problem, we delay 100 milliseconds and try to delete again. Up | |
| 1432 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving | |
| 1433 ** up and returning an error. | |
| 1434 */ | |
| 1435 #define MX_DELETION_ATTEMPTS 5 | |
| 1436 static int winDelete( | |
| 1437 sqlite3_vfs *pVfs, /* Not used on win32 */ | |
| 1438 const char *zFilename, /* Name of file to delete */ | |
| 1439 int syncDir /* Not used on win32 */ | |
| 1440 ){ | |
| 1441 int cnt = 0; | |
| 1442 DWORD rc; | |
| 1443 DWORD error = 0; | |
| 1444 void *zConverted = convertUtf8Filename(zFilename); | |
| 1445 UNUSED_PARAMETER(pVfs); | |
| 1446 UNUSED_PARAMETER(syncDir); | |
| 1447 if( zConverted==0 ){ | |
| 1448 return SQLITE_NOMEM; | |
| 1449 } | |
| 1450 SimulateIOError(return SQLITE_IOERR_DELETE); | |
| 1451 if( isNT() ){ | |
| 1452 do{ | |
| 1453 DeleteFileW(zConverted); | |
| 1454 }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBU
TES) | |
| 1455 || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) | |
| 1456 && (++cnt < MX_DELETION_ATTEMPTS) | |
| 1457 && (Sleep(100), 1) ); | |
| 1458 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 1459 ** Since the ASCII version of these Windows API do not exist for WINCE, | |
| 1460 ** it's important to not reference them for WINCE builds. | |
| 1461 */ | |
| 1462 #if SQLITE_OS_WINCE==0 | |
| 1463 }else{ | |
| 1464 do{ | |
| 1465 DeleteFileA(zConverted); | |
| 1466 }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBU
TES) | |
| 1467 || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) | |
| 1468 && (++cnt < MX_DELETION_ATTEMPTS) | |
| 1469 && (Sleep(100), 1) ); | |
| 1470 #endif | |
| 1471 } | |
| 1472 free(zConverted); | |
| 1473 OSTRACE2("DELETE \"%s\"\n", zFilename); | |
| 1474 return ( (rc == INVALID_FILE_ATTRIBUTES) | |
| 1475 && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE; | |
| 1476 } | |
| 1477 | |
| 1478 /* | |
| 1479 ** Check the existance and status of a file. | |
| 1480 */ | |
| 1481 static int winAccess( | |
| 1482 sqlite3_vfs *pVfs, /* Not used on win32 */ | |
| 1483 const char *zFilename, /* Name of file to check */ | |
| 1484 int flags, /* Type of test to make on this file */ | |
| 1485 int *pResOut /* OUT: Result */ | |
| 1486 ){ | |
| 1487 DWORD attr; | |
| 1488 int rc = 0; | |
| 1489 void *zConverted = convertUtf8Filename(zFilename); | |
| 1490 UNUSED_PARAMETER(pVfs); | |
| 1491 if( zConverted==0 ){ | |
| 1492 return SQLITE_NOMEM; | |
| 1493 } | |
| 1494 if( isNT() ){ | |
| 1495 attr = GetFileAttributesW((WCHAR*)zConverted); | |
| 1496 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 1497 ** Since the ASCII version of these Windows API do not exist for WINCE, | |
| 1498 ** it's important to not reference them for WINCE builds. | |
| 1499 */ | |
| 1500 #if SQLITE_OS_WINCE==0 | |
| 1501 }else{ | |
| 1502 attr = GetFileAttributesA((char*)zConverted); | |
| 1503 #endif | |
| 1504 } | |
| 1505 free(zConverted); | |
| 1506 switch( flags ){ | |
| 1507 case SQLITE_ACCESS_READ: | |
| 1508 case SQLITE_ACCESS_EXISTS: | |
| 1509 rc = attr!=INVALID_FILE_ATTRIBUTES; | |
| 1510 break; | |
| 1511 case SQLITE_ACCESS_READWRITE: | |
| 1512 rc = (attr & FILE_ATTRIBUTE_READONLY)==0; | |
| 1513 break; | |
| 1514 default: | |
| 1515 assert(!"Invalid flags argument"); | |
| 1516 } | |
| 1517 *pResOut = rc; | |
| 1518 return SQLITE_OK; | |
| 1519 } | |
| 1520 | |
| 1521 | |
| 1522 /* | |
| 1523 ** Turn a relative pathname into a full pathname. Write the full | |
| 1524 ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname | |
| 1525 ** bytes in size. | |
| 1526 */ | |
| 1527 static int winFullPathname( | |
| 1528 sqlite3_vfs *pVfs, /* Pointer to vfs object */ | |
| 1529 const char *zRelative, /* Possibly relative input path */ | |
| 1530 int nFull, /* Size of output buffer in bytes */ | |
| 1531 char *zFull /* Output buffer */ | |
| 1532 ){ | |
| 1533 | |
| 1534 #if defined(__CYGWIN__) | |
| 1535 UNUSED_PARAMETER(nFull); | |
| 1536 cygwin_conv_to_full_win32_path(zRelative, zFull); | |
| 1537 return SQLITE_OK; | |
| 1538 #endif | |
| 1539 | |
| 1540 #if SQLITE_OS_WINCE | |
| 1541 UNUSED_PARAMETER(nFull); | |
| 1542 /* WinCE has no concept of a relative pathname, or so I am told. */ | |
| 1543 sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); | |
| 1544 return SQLITE_OK; | |
| 1545 #endif | |
| 1546 | |
| 1547 #if !SQLITE_OS_WINCE && !defined(__CYGWIN__) | |
| 1548 int nByte; | |
| 1549 void *zConverted; | |
| 1550 char *zOut; | |
| 1551 UNUSED_PARAMETER(nFull); | |
| 1552 zConverted = convertUtf8Filename(zRelative); | |
| 1553 if( isNT() ){ | |
| 1554 WCHAR *zTemp; | |
| 1555 nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; | |
| 1556 zTemp = malloc( nByte*sizeof(zTemp[0]) ); | |
| 1557 if( zTemp==0 ){ | |
| 1558 free(zConverted); | |
| 1559 return SQLITE_NOMEM; | |
| 1560 } | |
| 1561 GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); | |
| 1562 free(zConverted); | |
| 1563 zOut = unicodeToUtf8(zTemp); | |
| 1564 free(zTemp); | |
| 1565 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 1566 ** Since the ASCII version of these Windows API do not exist for WINCE, | |
| 1567 ** it's important to not reference them for WINCE builds. | |
| 1568 */ | |
| 1569 #if SQLITE_OS_WINCE==0 | |
| 1570 }else{ | |
| 1571 char *zTemp; | |
| 1572 nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; | |
| 1573 zTemp = malloc( nByte*sizeof(zTemp[0]) ); | |
| 1574 if( zTemp==0 ){ | |
| 1575 free(zConverted); | |
| 1576 return SQLITE_NOMEM; | |
| 1577 } | |
| 1578 GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); | |
| 1579 free(zConverted); | |
| 1580 zOut = sqlite3_win32_mbcs_to_utf8(zTemp); | |
| 1581 free(zTemp); | |
| 1582 #endif | |
| 1583 } | |
| 1584 if( zOut ){ | |
| 1585 sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); | |
| 1586 free(zOut); | |
| 1587 return SQLITE_OK; | |
| 1588 }else{ | |
| 1589 return SQLITE_NOMEM; | |
| 1590 } | |
| 1591 #endif | |
| 1592 } | |
| 1593 | |
| 1594 /* | |
| 1595 ** Get the sector size of the device used to store | |
| 1596 ** file. | |
| 1597 */ | |
| 1598 static int getSectorSize( | |
| 1599 sqlite3_vfs *pVfs, | |
| 1600 const char *zRelative /* UTF-8 file name */ | |
| 1601 ){ | |
| 1602 DWORD bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; | |
| 1603 /* GetDiskFreeSpace is not supported under WINCE */ | |
| 1604 #if SQLITE_OS_WINCE | |
| 1605 UNUSED_PARAMETER(pVfs); | |
| 1606 UNUSED_PARAMETER(zRelative); | |
| 1607 #else | |
| 1608 char zFullpath[MAX_PATH+1]; | |
| 1609 int rc; | |
| 1610 DWORD dwRet = 0; | |
| 1611 DWORD dwDummy; | |
| 1612 | |
| 1613 /* | |
| 1614 ** We need to get the full path name of the file | |
| 1615 ** to get the drive letter to look up the sector | |
| 1616 ** size. | |
| 1617 */ | |
| 1618 rc = winFullPathname(pVfs, zRelative, MAX_PATH, zFullpath); | |
| 1619 if( rc == SQLITE_OK ) | |
| 1620 { | |
| 1621 void *zConverted = convertUtf8Filename(zFullpath); | |
| 1622 if( zConverted ){ | |
| 1623 if( isNT() ){ | |
| 1624 /* trim path to just drive reference */ | |
| 1625 WCHAR *p = zConverted; | |
| 1626 for(;*p;p++){ | |
| 1627 if( *p == '\\' ){ | |
| 1628 *p = '\0'; | |
| 1629 break; | |
| 1630 } | |
| 1631 } | |
| 1632 dwRet = GetDiskFreeSpaceW((WCHAR*)zConverted, | |
| 1633 &dwDummy, | |
| 1634 &bytesPerSector, | |
| 1635 &dwDummy, | |
| 1636 &dwDummy); | |
| 1637 }else{ | |
| 1638 /* trim path to just drive reference */ | |
| 1639 CHAR *p = (CHAR *)zConverted; | |
| 1640 for(;*p;p++){ | |
| 1641 if( *p == '\\' ){ | |
| 1642 *p = '\0'; | |
| 1643 break; | |
| 1644 } | |
| 1645 } | |
| 1646 dwRet = GetDiskFreeSpaceA((CHAR*)zConverted, | |
| 1647 &dwDummy, | |
| 1648 &bytesPerSector, | |
| 1649 &dwDummy, | |
| 1650 &dwDummy); | |
| 1651 } | |
| 1652 free(zConverted); | |
| 1653 } | |
| 1654 if( !dwRet ){ | |
| 1655 bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; | |
| 1656 } | |
| 1657 } | |
| 1658 #endif | |
| 1659 return (int) bytesPerSector; | |
| 1660 } | |
| 1661 | |
| 1662 #ifndef SQLITE_OMIT_LOAD_EXTENSION | |
| 1663 /* | |
| 1664 ** Interfaces for opening a shared library, finding entry points | |
| 1665 ** within the shared library, and closing the shared library. | |
| 1666 */ | |
| 1667 /* | |
| 1668 ** Interfaces for opening a shared library, finding entry points | |
| 1669 ** within the shared library, and closing the shared library. | |
| 1670 */ | |
| 1671 static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ | |
| 1672 HANDLE h; | |
| 1673 void *zConverted = convertUtf8Filename(zFilename); | |
| 1674 UNUSED_PARAMETER(pVfs); | |
| 1675 if( zConverted==0 ){ | |
| 1676 return 0; | |
| 1677 } | |
| 1678 if( isNT() ){ | |
| 1679 h = LoadLibraryW((WCHAR*)zConverted); | |
| 1680 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. | |
| 1681 ** Since the ASCII version of these Windows API do not exist for WINCE, | |
| 1682 ** it's important to not reference them for WINCE builds. | |
| 1683 */ | |
| 1684 #if SQLITE_OS_WINCE==0 | |
| 1685 }else{ | |
| 1686 h = LoadLibraryA((char*)zConverted); | |
| 1687 #endif | |
| 1688 } | |
| 1689 free(zConverted); | |
| 1690 return (void*)h; | |
| 1691 } | |
| 1692 static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ | |
| 1693 UNUSED_PARAMETER(pVfs); | |
| 1694 getLastErrorMsg(nBuf, zBufOut); | |
| 1695 } | |
| 1696 void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){ | |
| 1697 UNUSED_PARAMETER(pVfs); | |
| 1698 #if SQLITE_OS_WINCE | |
| 1699 /* The GetProcAddressA() routine is only available on wince. */ | |
| 1700 return (void(*)(void))GetProcAddressA((HANDLE)pHandle, zSymbol); | |
| 1701 #else | |
| 1702 /* All other windows platforms expect GetProcAddress() to take | |
| 1703 ** an Ansi string regardless of the _UNICODE setting */ | |
| 1704 return (void(*)(void))GetProcAddress((HANDLE)pHandle, zSymbol); | |
| 1705 #endif | |
| 1706 } | |
| 1707 void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ | |
| 1708 UNUSED_PARAMETER(pVfs); | |
| 1709 FreeLibrary((HANDLE)pHandle); | |
| 1710 } | |
| 1711 #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ | |
| 1712 #define winDlOpen 0 | |
| 1713 #define winDlError 0 | |
| 1714 #define winDlSym 0 | |
| 1715 #define winDlClose 0 | |
| 1716 #endif | |
| 1717 | |
| 1718 | |
| 1719 /* | |
| 1720 ** Write up to nBuf bytes of randomness into zBuf. | |
| 1721 */ | |
| 1722 static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ | |
| 1723 int n = 0; | |
| 1724 UNUSED_PARAMETER(pVfs); | |
| 1725 #if defined(SQLITE_TEST) | |
| 1726 n = nBuf; | |
| 1727 memset(zBuf, 0, nBuf); | |
| 1728 #else | |
| 1729 if( sizeof(SYSTEMTIME)<=nBuf-n ){ | |
| 1730 SYSTEMTIME x; | |
| 1731 GetSystemTime(&x); | |
| 1732 memcpy(&zBuf[n], &x, sizeof(x)); | |
| 1733 n += sizeof(x); | |
| 1734 } | |
| 1735 if( sizeof(DWORD)<=nBuf-n ){ | |
| 1736 DWORD pid = GetCurrentProcessId(); | |
| 1737 memcpy(&zBuf[n], &pid, sizeof(pid)); | |
| 1738 n += sizeof(pid); | |
| 1739 } | |
| 1740 if( sizeof(DWORD)<=nBuf-n ){ | |
| 1741 DWORD cnt = GetTickCount(); | |
| 1742 memcpy(&zBuf[n], &cnt, sizeof(cnt)); | |
| 1743 n += sizeof(cnt); | |
| 1744 } | |
| 1745 if( sizeof(LARGE_INTEGER)<=nBuf-n ){ | |
| 1746 LARGE_INTEGER i; | |
| 1747 QueryPerformanceCounter(&i); | |
| 1748 memcpy(&zBuf[n], &i, sizeof(i)); | |
| 1749 n += sizeof(i); | |
| 1750 } | |
| 1751 #endif | |
| 1752 return n; | |
| 1753 } | |
| 1754 | |
| 1755 | |
| 1756 /* | |
| 1757 ** Sleep for a little while. Return the amount of time slept. | |
| 1758 */ | |
| 1759 static int winSleep(sqlite3_vfs *pVfs, int microsec){ | |
| 1760 Sleep((microsec+999)/1000); | |
| 1761 UNUSED_PARAMETER(pVfs); | |
| 1762 return ((microsec+999)/1000)*1000; | |
| 1763 } | |
| 1764 | |
| 1765 /* | |
| 1766 ** The following variable, if set to a non-zero value, becomes the result | |
| 1767 ** returned from sqlite3OsCurrentTime(). This is used for testing. | |
| 1768 */ | |
| 1769 #ifdef SQLITE_TEST | |
| 1770 int sqlite3_current_time = 0; | |
| 1771 #endif | |
| 1772 | |
| 1773 /* | |
| 1774 ** Find the current time (in Universal Coordinated Time). Write the | |
| 1775 ** current time and date as a Julian Day number into *prNow and | |
| 1776 ** return 0. Return 1 if the time and date cannot be found. | |
| 1777 */ | |
| 1778 int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ | |
| 1779 FILETIME ft; | |
| 1780 /* FILETIME structure is a 64-bit value representing the number of | |
| 1781 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). | |
| 1782 */ | |
| 1783 sqlite3_int64 timeW; /* Whole days */ | |
| 1784 sqlite3_int64 timeF; /* Fractional Days */ | |
| 1785 | |
| 1786 /* Number of 100-nanosecond intervals in a single day */ | |
| 1787 static const sqlite3_int64 ntuPerDay = | |
| 1788 10000000*(sqlite3_int64)86400; | |
| 1789 | |
| 1790 /* Number of 100-nanosecond intervals in half of a day */ | |
| 1791 static const sqlite3_int64 ntuPerHalfDay = | |
| 1792 10000000*(sqlite3_int64)43200; | |
| 1793 | |
| 1794 /* 2^32 - to avoid use of LL and warnings in gcc */ | |
| 1795 static const sqlite3_int64 max32BitValue = | |
| 1796 (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294
967296; | |
| 1797 | |
| 1798 #if SQLITE_OS_WINCE | |
| 1799 SYSTEMTIME time; | |
| 1800 GetSystemTime(&time); | |
| 1801 /* if SystemTimeToFileTime() fails, it returns zero. */ | |
| 1802 if (!SystemTimeToFileTime(&time,&ft)){ | |
| 1803 return 1; | |
| 1804 } | |
| 1805 #else | |
| 1806 GetSystemTimeAsFileTime( &ft ); | |
| 1807 #endif | |
| 1808 UNUSED_PARAMETER(pVfs); | |
| 1809 timeW = (((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + (sqlite3_int64)ft
.dwLowDateTime; | |
| 1810 timeF = timeW % ntuPerDay; /* fractional days (100-nanoseconds) */ | |
| 1811 timeW = timeW / ntuPerDay; /* whole days */ | |
| 1812 timeW = timeW + 2305813; /* add whole days (from 2305813.5) */ | |
| 1813 timeF = timeF + ntuPerHalfDay; /* add half a day (from 2305813.5) */ | |
| 1814 timeW = timeW + (timeF/ntuPerDay); /* add whole day if half day made one */ | |
| 1815 timeF = timeF % ntuPerDay; /* compute new fractional days */ | |
| 1816 *prNow = (double)timeW + ((double)timeF / (double)ntuPerDay); | |
| 1817 #ifdef SQLITE_TEST | |
| 1818 if( sqlite3_current_time ){ | |
| 1819 *prNow = ((double)sqlite3_current_time + (double)43200) / (double)86400 + (d
ouble)2440587; | |
| 1820 } | |
| 1821 #endif | |
| 1822 return 0; | |
| 1823 } | |
| 1824 | |
| 1825 /* | |
| 1826 ** The idea is that this function works like a combination of | |
| 1827 ** GetLastError() and FormatMessage() on windows (or errno and | |
| 1828 ** strerror_r() on unix). After an error is returned by an OS | |
| 1829 ** function, SQLite calls this function with zBuf pointing to | |
| 1830 ** a buffer of nBuf bytes. The OS layer should populate the | |
| 1831 ** buffer with a nul-terminated UTF-8 encoded error message | |
| 1832 ** describing the last IO error to have occurred within the calling | |
| 1833 ** thread. | |
| 1834 ** | |
| 1835 ** If the error message is too large for the supplied buffer, | |
| 1836 ** it should be truncated. The return value of xGetLastError | |
| 1837 ** is zero if the error message fits in the buffer, or non-zero | |
| 1838 ** otherwise (if the message was truncated). If non-zero is returned, | |
| 1839 ** then it is not necessary to include the nul-terminator character | |
| 1840 ** in the output buffer. | |
| 1841 ** | |
| 1842 ** Not supplying an error message will have no adverse effect | |
| 1843 ** on SQLite. It is fine to have an implementation that never | |
| 1844 ** returns an error message: | |
| 1845 ** | |
| 1846 ** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ | |
| 1847 ** assert(zBuf[0]=='\0'); | |
| 1848 ** return 0; | |
| 1849 ** } | |
| 1850 ** | |
| 1851 ** However if an error message is supplied, it will be incorporated | |
| 1852 ** by sqlite into the error message available to the user using | |
| 1853 ** sqlite3_errmsg(), possibly making IO errors easier to debug. | |
| 1854 */ | |
| 1855 static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ | |
| 1856 UNUSED_PARAMETER(pVfs); | |
| 1857 return getLastErrorMsg(nBuf, zBuf); | |
| 1858 } | |
| 1859 | |
| 1860 /* | |
| 1861 ** Initialize and deinitialize the operating system interface. | |
| 1862 */ | |
| 1863 int sqlite3_os_init(void){ | |
| 1864 static sqlite3_vfs winVfs = { | |
| 1865 1, /* iVersion */ | |
| 1866 sizeof(winFile), /* szOsFile */ | |
| 1867 MAX_PATH, /* mxPathname */ | |
| 1868 0, /* pNext */ | |
| 1869 "win32", /* zName */ | |
| 1870 0, /* pAppData */ | |
| 1871 | |
| 1872 winOpen, /* xOpen */ | |
| 1873 winDelete, /* xDelete */ | |
| 1874 winAccess, /* xAccess */ | |
| 1875 winFullPathname, /* xFullPathname */ | |
| 1876 winDlOpen, /* xDlOpen */ | |
| 1877 winDlError, /* xDlError */ | |
| 1878 winDlSym, /* xDlSym */ | |
| 1879 winDlClose, /* xDlClose */ | |
| 1880 winRandomness, /* xRandomness */ | |
| 1881 winSleep, /* xSleep */ | |
| 1882 winCurrentTime, /* xCurrentTime */ | |
| 1883 winGetLastError /* xGetLastError */ | |
| 1884 }; | |
| 1885 | |
| 1886 sqlite3_vfs_register(&winVfs, 1); | |
| 1887 return SQLITE_OK; | |
| 1888 } | |
| 1889 int sqlite3_os_end(void){ | |
| 1890 return SQLITE_OK; | |
| 1891 } | |
| 1892 | |
| 1893 void chromium_sqlite3_initialize_win_sqlite3_file(sqlite3_file* file, HANDLE han
dle) { | |
| 1894 winFile* winSQLite3File = (winFile*)file; | |
| 1895 memset(file, 0, sizeof(*file)); | |
| 1896 winSQLite3File->pMethod = &winIoMethod; | |
| 1897 winSQLite3File->h = handle; | |
| 1898 } | |
| 1899 | |
| 1900 #endif /* SQLITE_OS_WIN */ | |
| OLD | NEW |