1434
|
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 #include "os.h"
|
|
17 #if OS_WIN /* This file is used for windows only */
|
|
18
|
|
19 #include <winbase.h>
|
|
20
|
|
21 #ifdef __CYGWIN__
|
|
22 # include <sys/cygwin.h>
|
|
23 #endif
|
|
24
|
|
25 /*
|
|
26 ** Macros used to determine whether or not to use threads.
|
|
27 */
|
|
28 #if defined(THREADSAFE) && THREADSAFE
|
|
29 # define SQLITE_W32_THREADS 1
|
|
30 #endif
|
|
31
|
|
32 /*
|
|
33 ** Include code that is common to all os_*.c files
|
|
34 */
|
|
35 #include "os_common.h"
|
|
36
|
|
37 /*
|
|
38 ** Determine if we are dealing with WindowsCE - which has a much
|
|
39 ** reduced API.
|
|
40 */
|
|
41 #if defined(_WIN32_WCE)
|
|
42 # define OS_WINCE 1
|
|
43 #else
|
|
44 # define OS_WINCE 0
|
|
45 #endif
|
|
46
|
|
47 /*
|
|
48 ** WinCE lacks native support for file locking so we have to fake it
|
|
49 ** with some code of our own.
|
|
50 */
|
|
51 #if OS_WINCE
|
|
52 typedef struct winceLock {
|
|
53 int nReaders; /* Number of reader locks obtained */
|
|
54 BOOL bPending; /* Indicates a pending lock has been obtained */
|
|
55 BOOL bReserved; /* Indicates a reserved lock has been obtained */
|
|
56 BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
|
|
57 } winceLock;
|
|
58 #endif
|
|
59
|
|
60 /*
|
|
61 ** The winFile structure is a subclass of OsFile specific to the win32
|
|
62 ** portability layer.
|
|
63 */
|
|
64 typedef struct winFile winFile;
|
|
65 struct winFile {
|
|
66 IoMethod const *pMethod;/* Must be first */
|
|
67 HANDLE h; /* Handle for accessing the file */
|
|
68 unsigned char locktype; /* Type of lock currently held on this file */
|
|
69 short sharedLockByte; /* Randomly chosen byte used as a shared lock */
|
|
70 #if OS_WINCE
|
|
71 WCHAR *zDeleteOnClose; /* Name of file to delete when closing */
|
|
72 HANDLE hMutex; /* Mutex used to control access to shared lock */
|
|
73 HANDLE hShared; /* Shared memory segment used for locking */
|
|
74 winceLock local; /* Locks obtained by this instance of winFile */
|
|
75 winceLock *shared; /* Global shared lock memory for the file */
|
|
76 #endif
|
|
77 };
|
|
78
|
|
79
|
|
80 /*
|
|
81 ** Do not include any of the File I/O interface procedures if the
|
|
82 ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
|
|
83 ** will be in-memory only)
|
|
84 */
|
|
85 #ifndef SQLITE_OMIT_DISKIO
|
|
86
|
|
87 /*
|
|
88 ** The following variable is (normally) set once and never changes
|
|
89 ** thereafter. It records whether the operating system is Win95
|
|
90 ** or WinNT.
|
|
91 **
|
|
92 ** 0: Operating system unknown.
|
|
93 ** 1: Operating system is Win95.
|
|
94 ** 2: Operating system is WinNT.
|
|
95 **
|
|
96 ** In order to facilitate testing on a WinNT system, the test fixture
|
|
97 ** can manually set this value to 1 to emulate Win98 behavior.
|
|
98 */
|
|
99 int sqlite3_os_type = 0;
|
|
100
|
|
101 /*
|
|
102 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
|
|
103 ** or WinCE. Return false (zero) for Win95, Win98, or WinME.
|
|
104 **
|
|
105 ** Here is an interesting observation: Win95, Win98, and WinME lack
|
|
106 ** the LockFileEx() API. But we can still statically link against that
|
|
107 ** API as long as we don't call it win running Win95/98/ME. A call to
|
|
108 ** this routine is used to determine if the host is Win95/98/ME or
|
|
109 ** WinNT/2K/XP so that we will know whether or not we can safely call
|
|
110 ** the LockFileEx() API.
|
|
111 */
|
|
112 #if OS_WINCE
|
|
113 # define isNT() (1)
|
|
114 #else
|
|
115 static int isNT(void){
|
|
116 if( sqlite3_os_type==0 ){
|
|
117 OSVERSIONINFO sInfo;
|
|
118 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
|
119 GetVersionEx(&sInfo);
|
|
120 sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
|
|
121 }
|
|
122 return sqlite3_os_type==2;
|
|
123 }
|
|
124 #endif /* OS_WINCE */
|
|
125
|
|
126 /*
|
|
127 ** Convert a UTF-8 string to UTF-32. Space to hold the returned string
|
|
128 ** is obtained from sqliteMalloc.
|
|
129 */
|
|
130 static WCHAR *utf8ToUnicode(const char *zFilename){
|
|
131 int nChar;
|
|
132 WCHAR *zWideFilename;
|
|
133
|
|
134 if( !isNT() ){
|
|
135 return 0;
|
|
136 }
|
|
137 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
|
|
138 zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) );
|
|
139 if( zWideFilename==0 ){
|
|
140 return 0;
|
|
141 }
|
|
142 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar);
|
|
143 if( nChar==0 ){
|
|
144 sqliteFree(zWideFilename);
|
|
145 zWideFilename = 0;
|
|
146 }
|
|
147 return zWideFilename;
|
|
148 }
|
|
149
|
|
150 /*
|
|
151 ** Convert UTF-32 to UTF-8. Space to hold the returned string is
|
|
152 ** obtained from sqliteMalloc().
|
|
153 */
|
|
154 static char *unicodeToUtf8(const WCHAR *zWideFilename){
|
|
155 int nByte;
|
|
156 char *zFilename;
|
|
157
|
|
158 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
|
|
159 zFilename = sqliteMalloc( nByte );
|
|
160 if( zFilename==0 ){
|
|
161 return 0;
|
|
162 }
|
|
163 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
|
|
164 0, 0);
|
|
165 if( nByte == 0 ){
|
|
166 sqliteFree(zFilename);
|
|
167 zFilename = 0;
|
|
168 }
|
|
169 return zFilename;
|
|
170 }
|
|
171
|
|
172 #if OS_WINCE
|
|
173 /*************************************************************************
|
|
174 ** This section contains code for WinCE only.
|
|
175 */
|
|
176 /*
|
|
177 ** WindowsCE does not have a localtime() function. So create a
|
|
178 ** substitute.
|
|
179 */
|
|
180 #include <time.h>
|
|
181 struct tm *__cdecl localtime(const time_t *t)
|
|
182 {
|
|
183 static struct tm y;
|
|
184 FILETIME uTm, lTm;
|
|
185 SYSTEMTIME pTm;
|
|
186 i64 t64;
|
|
187 t64 = *t;
|
|
188 t64 = (t64 + 11644473600)*10000000;
|
|
189 uTm.dwLowDateTime = t64 & 0xFFFFFFFF;
|
|
190 uTm.dwHighDateTime= t64 >> 32;
|
|
191 FileTimeToLocalFileTime(&uTm,&lTm);
|
|
192 FileTimeToSystemTime(&lTm,&pTm);
|
|
193 y.tm_year = pTm.wYear - 1900;
|
|
194 y.tm_mon = pTm.wMonth - 1;
|
|
195 y.tm_wday = pTm.wDayOfWeek;
|
|
196 y.tm_mday = pTm.wDay;
|
|
197 y.tm_hour = pTm.wHour;
|
|
198 y.tm_min = pTm.wMinute;
|
|
199 y.tm_sec = pTm.wSecond;
|
|
200 return &y;
|
|
201 }
|
|
202
|
|
203 /* This will never be called, but defined to make the code compile */
|
|
204 #define GetTempPathA(a,b)
|
|
205
|
|
206 #define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e)
|
|
207 #define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e)
|
|
208 #define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f)
|
|
209
|
|
210 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)]
|
|
211
|
|
212 /*
|
|
213 ** Acquire a lock on the handle h
|
|
214 */
|
|
215 static void winceMutexAcquire(HANDLE h){
|
|
216 DWORD dwErr;
|
|
217 do {
|
|
218 dwErr = WaitForSingleObject(h, INFINITE);
|
|
219 } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
|
|
220 }
|
|
221 /*
|
|
222 ** Release a lock acquired by winceMutexAcquire()
|
|
223 */
|
|
224 #define winceMutexRelease(h) ReleaseMutex(h)
|
|
225
|
|
226 /*
|
|
227 ** Create the mutex and shared memory used for locking in the file
|
|
228 ** descriptor pFile
|
|
229 */
|
|
230 static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
|
|
231 WCHAR *zTok;
|
|
232 WCHAR *zName = utf8ToUnicode(zFilename);
|
|
233 BOOL bInit = TRUE;
|
|
234
|
|
235 /* Initialize the local lockdata */
|
|
236 ZeroMemory(&pFile->local, sizeof(pFile->local));
|
|
237
|
|
238 /* Replace the backslashes from the filename and lowercase it
|
|
239 ** to derive a mutex name. */
|
|
240 zTok = CharLowerW(zName);
|
|
241 for (;*zTok;zTok++){
|
|
242 if (*zTok == '\\') *zTok = '_';
|
|
243 }
|
|
244
|
|
245 /* Create/open the named mutex */
|
|
246 pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
|
|
247 if (!pFile->hMutex){
|
|
248 sqliteFree(zName);
|
|
249 return FALSE;
|
|
250 }
|
|
251
|
|
252 /* Acquire the mutex before continuing */
|
|
253 winceMutexAcquire(pFile->hMutex);
|
|
254
|
|
255 /* Since the names of named mutexes, semaphores, file mappings etc are
|
|
256 ** case-sensitive, take advantage of that by uppercasing the mutex name
|
|
257 ** and using that as the shared filemapping name.
|
|
258 */
|
|
259 CharUpperW(zName);
|
|
260 pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
|
|
261 PAGE_READWRITE, 0, sizeof(winceLock),
|
|
262 zName);
|
|
263
|
|
264 /* Set a flag that indicates we're the first to create the memory so it
|
|
265 ** must be zero-initialized */
|
|
266 if (GetLastError() == ERROR_ALREADY_EXISTS){
|
|
267 bInit = FALSE;
|
|
268 }
|
|
269
|
|
270 sqliteFree(zName);
|
|
271
|
|
272 /* If we succeeded in making the shared memory handle, map it. */
|
|
273 if (pFile->hShared){
|
|
274 pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
|
|
275 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
|
|
276 /* If mapping failed, close the shared memory handle and erase it */
|
|
277 if (!pFile->shared){
|
|
278 CloseHandle(pFile->hShared);
|
|
279 pFile->hShared = NULL;
|
|
280 }
|
|
281 }
|
|
282
|
|
283 /* If shared memory could not be created, then close the mutex and fail */
|
|
284 if (pFile->hShared == NULL){
|
|
285 winceMutexRelease(pFile->hMutex);
|
|
286 CloseHandle(pFile->hMutex);
|
|
287 pFile->hMutex = NULL;
|
|
288 return FALSE;
|
|
289 }
|
|
290
|
|
291 /* Initialize the shared memory if we're supposed to */
|
|
292 if (bInit) {
|
|
293 ZeroMemory(pFile->shared, sizeof(winceLock));
|
|
294 }
|
|
295
|
|
296 winceMutexRelease(pFile->hMutex);
|
|
297 return TRUE;
|
|
298 }
|
|
299
|
|
300 /*
|
|
301 ** Destroy the part of winFile that deals with wince locks
|
|
302 */
|
|
303 static void winceDestroyLock(winFile *pFile){
|
|
304 if (pFile->hMutex){
|
|
305 /* Acquire the mutex */
|
|
306 winceMutexAcquire(pFile->hMutex);
|
|
307
|
|
308 /* The following blocks should probably assert in debug mode, but they
|
|
309 are to cleanup in case any locks remained open */
|
|
310 if (pFile->local.nReaders){
|
|
311 pFile->shared->nReaders --;
|
|
312 }
|
|
313 if (pFile->local.bReserved){
|
|
314 pFile->shared->bReserved = FALSE;
|
|
315 }
|
|
316 if (pFile->local.bPending){
|
|
317 pFile->shared->bPending = FALSE;
|
|
318 }
|
|
319 if (pFile->local.bExclusive){
|
|
320 pFile->shared->bExclusive = FALSE;
|
|
321 }
|
|
322
|
|
323 /* De-reference and close our copy of the shared memory handle */
|
|
324 UnmapViewOfFile(pFile->shared);
|
|
325 CloseHandle(pFile->hShared);
|
|
326
|
|
327 /* Done with the mutex */
|
|
328 winceMutexRelease(pFile->hMutex);
|
|
329 CloseHandle(pFile->hMutex);
|
|
330 pFile->hMutex = NULL;
|
|
331 }
|
|
332 }
|
|
333
|
|
334 /*
|
|
335 ** An implementation of the LockFile() API of windows for wince
|
|
336 */
|
|
337 static BOOL winceLockFile(
|
|
338 HANDLE *phFile,
|
|
339 DWORD dwFileOffsetLow,
|
|
340 DWORD dwFileOffsetHigh,
|
|
341 DWORD nNumberOfBytesToLockLow,
|
|
342 DWORD nNumberOfBytesToLockHigh
|
|
343 ){
|
|
344 winFile *pFile = HANDLE_TO_WINFILE(phFile);
|
|
345 BOOL bReturn = FALSE;
|
|
346
|
|
347 if (!pFile->hMutex) return TRUE;
|
|
348 winceMutexAcquire(pFile->hMutex);
|
|
349
|
|
350 /* Wanting an exclusive lock? */
|
|
351 if (dwFileOffsetLow == SHARED_FIRST
|
|
352 && nNumberOfBytesToLockLow == SHARED_SIZE){
|
|
353 if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
|
|
354 pFile->shared->bExclusive = TRUE;
|
|
355 pFile->local.bExclusive = TRUE;
|
|
356 bReturn = TRUE;
|
|
357 }
|
|
358 }
|
|
359
|
|
360 /* Want a read-only lock? */
|
|
361 else if ((dwFileOffsetLow >= SHARED_FIRST &&
|
|
362 dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) &&
|
|
363 nNumberOfBytesToLockLow == 1){
|
|
364 if (pFile->shared->bExclusive == 0){
|
|
365 pFile->local.nReaders ++;
|
|
366 if (pFile->local.nReaders == 1){
|
|
367 pFile->shared->nReaders ++;
|
|
368 }
|
|
369 bReturn = TRUE;
|
|
370 }
|
|
371 }
|
|
372
|
|
373 /* Want a pending lock? */
|
|
374 else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){
|
|
375 /* If no pending lock has been acquired, then acquire it */
|
|
376 if (pFile->shared->bPending == 0) {
|
|
377 pFile->shared->bPending = TRUE;
|
|
378 pFile->local.bPending = TRUE;
|
|
379 bReturn = TRUE;
|
|
380 }
|
|
381 }
|
|
382 /* Want a reserved lock? */
|
|
383 else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
|
|
384 if (pFile->shared->bReserved == 0) {
|
|
385 pFile->shared->bReserved = TRUE;
|
|
386 pFile->local.bReserved = TRUE;
|
|
387 bReturn = TRUE;
|
|
388 }
|
|
389 }
|
|
390
|
|
391 winceMutexRelease(pFile->hMutex);
|
|
392 return bReturn;
|
|
393 }
|
|
394
|
|
395 /*
|
|
396 ** An implementation of the UnlockFile API of windows for wince
|
|
397 */
|
|
398 static BOOL winceUnlockFile(
|
|
399 HANDLE *phFile,
|
|
400 DWORD dwFileOffsetLow,
|
|
401 DWORD dwFileOffsetHigh,
|
|
402 DWORD nNumberOfBytesToUnlockLow,
|
|
403 DWORD nNumberOfBytesToUnlockHigh
|
|
404 ){
|
|
405 winFile *pFile = HANDLE_TO_WINFILE(phFile);
|
|
406 BOOL bReturn = FALSE;
|
|
407
|
|
408 if (!pFile->hMutex) return TRUE;
|
|
409 winceMutexAcquire(pFile->hMutex);
|
|
410
|
|
411 /* Releasing a reader lock or an exclusive lock */
|
|
412 if (dwFileOffsetLow >= SHARED_FIRST &&
|
|
413 dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){
|
|
414 /* Did we have an exclusive lock? */
|
|
415 if (pFile->local.bExclusive){
|
|
416 pFile->local.bExclusive = FALSE;
|
|
417 pFile->shared->bExclusive = FALSE;
|
|
418 bReturn = TRUE;
|
|
419 }
|
|
420
|
|
421 /* Did we just have a reader lock? */
|
|
422 else if (pFile->local.nReaders){
|
|
423 pFile->local.nReaders --;
|
|
424 if (pFile->local.nReaders == 0)
|
|
425 {
|
|
426 pFile->shared->nReaders --;
|
|
427 }
|
|
428 bReturn = TRUE;
|
|
429 }
|
|
430 }
|
|
431
|
|
432 /* Releasing a pending lock */
|
|
433 else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
|
|
434 if (pFile->local.bPending){
|
|
435 pFile->local.bPending = FALSE;
|
|
436 pFile->shared->bPending = FALSE;
|
|
437 bReturn = TRUE;
|
|
438 }
|
|
439 }
|
|
440 /* Releasing a reserved lock */
|
|
441 else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
|
|
442 if (pFile->local.bReserved) {
|
|
443 pFile->local.bReserved = FALSE;
|
|
444 pFile->shared->bReserved = FALSE;
|
|
445 bReturn = TRUE;
|
|
446 }
|
|
447 }
|
|
448
|
|
449 winceMutexRelease(pFile->hMutex);
|
|
450 return bReturn;
|
|
451 }
|
|
452
|
|
453 /*
|
|
454 ** An implementation of the LockFileEx() API of windows for wince
|
|
455 */
|
|
456 static BOOL winceLockFileEx(
|
|
457 HANDLE *phFile,
|
|
458 DWORD dwFlags,
|
|
459 DWORD dwReserved,
|
|
460 DWORD nNumberOfBytesToLockLow,
|
|
461 DWORD nNumberOfBytesToLockHigh,
|
|
462 LPOVERLAPPED lpOverlapped
|
|
463 ){
|
|
464 /* If the caller wants a shared read lock, forward this call
|
|
465 ** to winceLockFile */
|
|
466 if (lpOverlapped->Offset == SHARED_FIRST &&
|
|
467 dwFlags == 1 &&
|
|
468 nNumberOfBytesToLockLow == SHARED_SIZE){
|
|
469 return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
|
|
470 }
|
|
471 return FALSE;
|
|
472 }
|
|
473 /*
|
|
474 ** End of the special code for wince
|
|
475 *****************************************************************************/
|
|
476 #endif /* OS_WINCE */
|
|
477
|
|
478 /*
|
|
479 ** Delete the named file.
|
|
480 **
|
|
481 ** Note that windows does not allow a file to be deleted if some other
|
|
482 ** process has it open. Sometimes a virus scanner or indexing program
|
|
483 ** will open a journal file shortly after it is created in order to do
|
|
484 ** whatever it is it does. While this other process is holding the
|
|
485 ** file open, we will be unable to delete it. To work around this
|
|
486 ** problem, we delay 100 milliseconds and try to delete again. Up
|
|
487 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
|
|
488 ** up and returning an error.
|
|
489 */
|
|
490 #define MX_DELETION_ATTEMPTS 3
|
|
491 int sqlite3WinDelete(const char *zFilename){
|
|
492 WCHAR *zWide = utf8ToUnicode(zFilename);
|
|
493 int cnt = 0;
|
|
494 int rc;
|
|
495 if( zWide ){
|
|
496 do{
|
|
497 rc = DeleteFileW(zWide);
|
|
498 }while( rc==0 && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );
|
|
499 sqliteFree(zWide);
|
|
500 }else{
|
|
501 #if OS_WINCE
|
|
502 return SQLITE_NOMEM;
|
|
503 #else
|
|
504 do{
|
|
505 rc = DeleteFileA(zFilename);
|
|
506 }while( rc==0 && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );
|
|
507 #endif
|
|
508 }
|
|
509 TRACE2("DELETE \"%s\"\n", zFilename);
|
|
510 return rc==0 ? SQLITE_OK : SQLITE_IOERR;
|
|
511 }
|
|
512
|
|
513 /*
|
|
514 ** Return TRUE if the named file exists.
|
|
515 */
|
|
516 int sqlite3WinFileExists(const char *zFilename){
|
|
517 int exists = 0;
|
|
518 WCHAR *zWide = utf8ToUnicode(zFilename);
|
|
519 if( zWide ){
|
|
520 exists = GetFileAttributesW(zWide) != 0xffffffff;
|
|
521 sqliteFree(zWide);
|
|
522 }else{
|
|
523 #if OS_WINCE
|
|
524 return SQLITE_NOMEM;
|
|
525 #else
|
|
526 exists = GetFileAttributesA(zFilename) != 0xffffffff;
|
|
527 #endif
|
|
528 }
|
|
529 return exists;
|
|
530 }
|
|
531
|
|
532 /* Forward declaration */
|
|
533 static int allocateWinFile(winFile *pInit, OsFile **pId);
|
|
534
|
|
535 /*
|
|
536 ** Attempt to open a file for both reading and writing. If that
|
|
537 ** fails, try opening it read-only. If the file does not exist,
|
|
538 ** try to create it.
|
|
539 **
|
|
540 ** On success, a handle for the open file is written to *id
|
|
541 ** and *pReadonly is set to 0 if the file was opened for reading and
|
|
542 ** writing or 1 if the file was opened read-only. The function returns
|
|
543 ** SQLITE_OK.
|
|
544 **
|
|
545 ** On failure, the function returns SQLITE_CANTOPEN and leaves
|
|
546 ** *id and *pReadonly unchanged.
|
|
547 */
|
|
548 int sqlite3WinOpenReadWrite(
|
|
549 const char *zFilename,
|
|
550 OsFile **pId,
|
|
551 int *pReadonly
|
|
552 ){
|
|
553 winFile f;
|
|
554 HANDLE h;
|
|
555 WCHAR *zWide = utf8ToUnicode(zFilename);
|
|
556 assert( *pId==0 );
|
|
557 if( zWide ){
|
|
558 h = CreateFileW(zWide,
|
|
559 GENERIC_READ | GENERIC_WRITE,
|
|
560 FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
561 NULL,
|
|
562 OPEN_ALWAYS,
|
|
563 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
564 NULL
|
|
565 );
|
|
566 if( h==INVALID_HANDLE_VALUE ){
|
|
567 h = CreateFileW(zWide,
|
|
568 GENERIC_READ,
|
|
569 FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
570 NULL,
|
|
571 OPEN_ALWAYS,
|
|
572 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
573 NULL
|
|
574 );
|
|
575 if( h==INVALID_HANDLE_VALUE ){
|
|
576 sqliteFree(zWide);
|
|
577 return SQLITE_CANTOPEN;
|
|
578 }
|
|
579 *pReadonly = 1;
|
|
580 }else{
|
|
581 *pReadonly = 0;
|
|
582 }
|
|
583 #if OS_WINCE
|
|
584 if (!winceCreateLock(zFilename, &f)){
|
|
585 CloseHandle(h);
|
|
586 sqliteFree(zWide);
|
|
587 return SQLITE_CANTOPEN;
|
|
588 }
|
|
589 #endif
|
|
590 sqliteFree(zWide);
|
|
591 }else{
|
|
592 #if OS_WINCE
|
|
593 return SQLITE_NOMEM;
|
|
594 #else
|
|
595 h = CreateFileA(zFilename,
|
|
596 GENERIC_READ | GENERIC_WRITE,
|
|
597 FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
598 NULL,
|
|
599 OPEN_ALWAYS,
|
|
600 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
601 NULL
|
|
602 );
|
|
603 if( h==INVALID_HANDLE_VALUE ){
|
|
604 h = CreateFileA(zFilename,
|
|
605 GENERIC_READ,
|
|
606 FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
607 NULL,
|
|
608 OPEN_ALWAYS,
|
|
609 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
610 NULL
|
|
611 );
|
|
612 if( h==INVALID_HANDLE_VALUE ){
|
|
613 return SQLITE_CANTOPEN;
|
|
614 }
|
|
615 *pReadonly = 1;
|
|
616 }else{
|
|
617 *pReadonly = 0;
|
|
618 }
|
|
619 #endif /* OS_WINCE */
|
|
620 }
|
|
621 f.h = h;
|
|
622 #if OS_WINCE
|
|
623 f.zDeleteOnClose = 0;
|
|
624 #endif
|
|
625 TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
|
|
626 return allocateWinFile(&f, pId);
|
|
627 }
|
|
628
|
|
629
|
|
630 /*
|
|
631 ** Attempt to open a new file for exclusive access by this process.
|
|
632 ** The file will be opened for both reading and writing. To avoid
|
|
633 ** a potential security problem, we do not allow the file to have
|
|
634 ** previously existed. Nor do we allow the file to be a symbolic
|
|
635 ** link.
|
|
636 **
|
|
637 ** If delFlag is true, then make arrangements to automatically delete
|
|
638 ** the file when it is closed.
|
|
639 **
|
|
640 ** On success, write the file handle into *id and return SQLITE_OK.
|
|
641 **
|
|
642 ** On failure, return SQLITE_CANTOPEN.
|
|
643 **
|
|
644 ** Sometimes if we have just deleted a prior journal file, windows
|
|
645 ** will fail to open a new one because there is a "pending delete".
|
|
646 ** To work around this bug, we pause for 100 milliseconds and attempt
|
|
647 ** a second open after the first one fails. The whole operation only
|
|
648 ** fails if both open attempts are unsuccessful.
|
|
649 */
|
|
650 int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
|
|
651 winFile f;
|
|
652 HANDLE h;
|
|
653 int fileflags;
|
|
654 WCHAR *zWide = utf8ToUnicode(zFilename);
|
|
655 assert( *pId == 0 );
|
|
656 fileflags = FILE_FLAG_RANDOM_ACCESS;
|
|
657 #if !OS_WINCE
|
|
658 if( delFlag ){
|
|
659 fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
|
|
660 }
|
|
661 #endif
|
|
662 if( zWide ){
|
|
663 int cnt = 0;
|
|
664 do{
|
|
665 h = CreateFileW(zWide,
|
|
666 GENERIC_READ | GENERIC_WRITE,
|
|
667 0,
|
|
668 NULL,
|
|
669 CREATE_ALWAYS,
|
|
670 fileflags,
|
|
671 NULL
|
|
672 );
|
|
673 }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) );
|
|
674 sqliteFree(zWide);
|
|
675 }else{
|
|
676 #if OS_WINCE
|
|
677 return SQLITE_NOMEM;
|
|
678 #else
|
|
679 int cnt = 0;
|
|
680 do{
|
|
681 h = CreateFileA(zFilename,
|
|
682 GENERIC_READ | GENERIC_WRITE,
|
|
683 0,
|
|
684 NULL,
|
|
685 CREATE_ALWAYS,
|
|
686 fileflags,
|
|
687 NULL
|
|
688 );
|
|
689 }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) );
|
|
690 #endif /* OS_WINCE */
|
|
691 }
|
|
692 if( h==INVALID_HANDLE_VALUE ){
|
|
693 return SQLITE_CANTOPEN;
|
|
694 }
|
|
695 f.h = h;
|
|
696 #if OS_WINCE
|
|
697 f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0;
|
|
698 f.hMutex = NULL;
|
|
699 #endif
|
|
700 TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
|
|
701 return allocateWinFile(&f, pId);
|
|
702 }
|
|
703
|
|
704 /*
|
|
705 ** Attempt to open a new file for read-only access.
|
|
706 **
|
|
707 ** On success, write the file handle into *id and return SQLITE_OK.
|
|
708 **
|
|
709 ** On failure, return SQLITE_CANTOPEN.
|
|
710 */
|
|
711 int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
|
|
712 winFile f;
|
|
713 HANDLE h;
|
|
714 WCHAR *zWide = utf8ToUnicode(zFilename);
|
|
715 assert( *pId==0 );
|
|
716 if( zWide ){
|
|
717 h = CreateFileW(zWide,
|
|
718 GENERIC_READ,
|
|
719 0,
|
|
720 NULL,
|
|
721 OPEN_EXISTING,
|
|
722 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
723 NULL
|
|
724 );
|
|
725 sqliteFree(zWide);
|
|
726 }else{
|
|
727 #if OS_WINCE
|
|
728 return SQLITE_NOMEM;
|
|
729 #else
|
|
730 h = CreateFileA(zFilename,
|
|
731 GENERIC_READ,
|
|
732 0,
|
|
733 NULL,
|
|
734 OPEN_EXISTING,
|
|
735 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
736 NULL
|
|
737 );
|
|
738 #endif
|
|
739 }
|
|
740 if( h==INVALID_HANDLE_VALUE ){
|
|
741 return SQLITE_CANTOPEN;
|
|
742 }
|
|
743 f.h = h;
|
|
744 #if OS_WINCE
|
|
745 f.zDeleteOnClose = 0;
|
|
746 f.hMutex = NULL;
|
|
747 #endif
|
|
748 TRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
|
|
749 return allocateWinFile(&f, pId);
|
|
750 }
|
|
751
|
|
752 /*
|
|
753 ** Attempt to open a file descriptor for the directory that contains a
|
|
754 ** file. This file descriptor can be used to fsync() the directory
|
|
755 ** in order to make sure the creation of a new file is actually written
|
|
756 ** to disk.
|
|
757 **
|
|
758 ** This routine is only meaningful for Unix. It is a no-op under
|
|
759 ** windows since windows does not support hard links.
|
|
760 **
|
|
761 ** On success, a handle for a previously open file is at *id is
|
|
762 ** updated with the new directory file descriptor and SQLITE_OK is
|
|
763 ** returned.
|
|
764 **
|
|
765 ** On failure, the function returns SQLITE_CANTOPEN and leaves
|
|
766 ** *id unchanged.
|
|
767 */
|
|
768 static int winOpenDirectory(
|
|
769 OsFile *id,
|
|
770 const char *zDirname
|
|
771 ){
|
|
772 return SQLITE_OK;
|
|
773 }
|
|
774
|
|
775 /*
|
|
776 ** If the following global variable points to a string which is the
|
|
777 ** name of a directory, then that directory will be used to store
|
|
778 ** temporary files.
|
|
779 */
|
|
780 char *sqlite3_temp_directory = 0;
|
|
781
|
|
782 /*
|
|
783 ** Create a temporary file name in zBuf. zBuf must be big enough to
|
|
784 ** hold at least SQLITE_TEMPNAME_SIZE characters.
|
|
785 */
|
|
786 int sqlite3WinTempFileName(char *zBuf){
|
|
787 static char zChars[] =
|
|
788 "abcdefghijklmnopqrstuvwxyz"
|
|
789 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
790 "0123456789";
|
|
791 int i, j;
|
|
792 char zTempPath[SQLITE_TEMPNAME_SIZE];
|
|
793 if( sqlite3_temp_directory ){
|
|
794 strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30);
|
|
795 zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
|
|
796 }else if( isNT() ){
|
|
797 char *zMulti;
|
|
798 WCHAR zWidePath[SQLITE_TEMPNAME_SIZE];
|
|
799 GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath);
|
|
800 zMulti = unicodeToUtf8(zWidePath);
|
|
801 if( zMulti ){
|
|
802 strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30);
|
|
803 zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
|
|
804 sqliteFree(zMulti);
|
|
805 }
|
|
806 }else{
|
|
807 GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
|
|
808 }
|
|
809 for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
|
|
810 zTempPath[i] = 0;
|
|
811 for(;;){
|
|
812 sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath);
|
|
813 j = strlen(zBuf);
|
|
814 sqlite3Randomness(15, &zBuf[j]);
|
|
815 for(i=0; i<15; i++, j++){
|
|
816 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
|
|
817 }
|
|
818 zBuf[j] = 0;
|
|
819 if( !sqlite3OsFileExists(zBuf) ) break;
|
|
820 }
|
|
821 TRACE2("TEMP FILENAME: %s\n", zBuf);
|
|
822 return SQLITE_OK;
|
|
823 }
|
|
824
|
|
825 /*
|
|
826 ** Close a file.
|
|
827 **
|
|
828 ** It is reported that an attempt to close a handle might sometimes
|
|
829 ** fail. This is a very unreasonable result, but windows is notorious
|
|
830 ** for being unreasonable so I do not doubt that it might happen. If
|
|
831 ** the close fails, we pause for 100 milliseconds and try again. As
|
|
832 ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
|
|
833 ** giving up and returning an error.
|
|
834 */
|
|
835 #define MX_CLOSE_ATTEMPT 3
|
|
836 static int winClose(OsFile **pId){
|
|
837 winFile *pFile;
|
|
838 int rc = 1;
|
|
839 if( pId && (pFile = (winFile*)*pId)!=0 ){
|
|
840 int rc, cnt = 0;
|
|
841 TRACE2("CLOSE %d\n", pFile->h);
|
|
842 do{
|
|
843 rc = CloseHandle(pFile->h);
|
|
844 }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
|
|
845 #if OS_WINCE
|
|
846 winceDestroyLock(pFile);
|
|
847 if( pFile->zDeleteOnClose ){
|
|
848 DeleteFileW(pFile->zDeleteOnClose);
|
|
849 sqliteFree(pFile->zDeleteOnClose);
|
|
850 }
|
|
851 #endif
|
|
852 OpenCounter(-1);
|
|
853 sqliteFree(pFile);
|
|
854 *pId = 0;
|
|
855 }
|
|
856 return rc ? SQLITE_OK : SQLITE_IOERR;
|
|
857 }
|
|
858
|
|
859 /*
|
|
860 ** Read data from a file into a buffer. Return SQLITE_OK if all
|
|
861 ** bytes were read successfully and SQLITE_IOERR if anything goes
|
|
862 ** wrong.
|
|
863 */
|
|
864 static int winRead(OsFile *id, void *pBuf, int amt){
|
|
865 DWORD got;
|
|
866 assert( id!=0 );
|
|
867 SimulateIOError(SQLITE_IOERR);
|
|
868 TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
|
|
869 if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){
|
|
870 got = 0;
|
|
871 }
|
|
872 if( got==(DWORD)amt ){
|
|
873 return SQLITE_OK;
|
|
874 }else{
|
|
875 return SQLITE_IOERR;
|
|
876 }
|
|
877 }
|
|
878
|
|
879 /*
|
|
880 ** Write data from a buffer into a file. Return SQLITE_OK on success
|
|
881 ** or some other error code on failure.
|
|
882 */
|
|
883 static int winWrite(OsFile *id, const void *pBuf, int amt){
|
|
884 int rc = 0;
|
|
885 DWORD wrote;
|
|
886 assert( id!=0 );
|
|
887 SimulateIOError(SQLITE_IOERR);
|
|
888 SimulateDiskfullError;
|
|
889 TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
|
|
890 assert( amt>0 );
|
|
891 while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0
|
|
892 && wrote>0 ){
|
|
893 amt -= wrote;
|
|
894 pBuf = &((char*)pBuf)[wrote];
|
|
895 }
|
|
896 if( !rc || amt>(int)wrote ){
|
|
897 return SQLITE_FULL;
|
|
898 }
|
|
899 return SQLITE_OK;
|
|
900 }
|
|
901
|
|
902 /*
|
|
903 ** Some microsoft compilers lack this definition.
|
|
904 */
|
|
905 #ifndef INVALID_SET_FILE_POINTER
|
|
906 # define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
|
907 #endif
|
|
908
|
|
909 /*
|
|
910 ** Move the read/write pointer in a file.
|
|
911 */
|
|
912 static int winSeek(OsFile *id, i64 offset){
|
|
913 LONG upperBits = offset>>32;
|
|
914 LONG lowerBits = offset & 0xffffffff;
|
|
915 DWORD rc;
|
|
916 assert( id!=0 );
|
|
917 #ifdef SQLITE_TEST
|
|
918 if( offset ) SimulateDiskfullError
|
|
919 #endif
|
|
920 SEEK(offset/1024 + 1);
|
|
921 rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN);
|
|
922 TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset);
|
|
923 if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
|
|
924 return SQLITE_FULL;
|
|
925 }
|
|
926 return SQLITE_OK;
|
|
927 }
|
|
928
|
|
929 /*
|
|
930 ** Make sure all writes to a particular file are committed to disk.
|
|
931 */
|
|
932 static int winSync(OsFile *id, int dataOnly){
|
|
933 assert( id!=0 );
|
|
934 TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
|
|
935 if( FlushFileBuffers(((winFile*)id)->h) ){
|
|
936 return SQLITE_OK;
|
|
937 }else{
|
|
938 return SQLITE_IOERR;
|
|
939 }
|
|
940 }
|
|
941
|
|
942 /*
|
|
943 ** Sync the directory zDirname. This is a no-op on operating systems other
|
|
944 ** than UNIX.
|
|
945 */
|
|
946 int sqlite3WinSyncDirectory(const char *zDirname){
|
|
947 SimulateIOError(SQLITE_IOERR);
|
|
948 return SQLITE_OK;
|
|
949 }
|
|
950
|
|
951 /*
|
|
952 ** Truncate an open file to a specified size
|
|
953 */
|
|
954 static int winTruncate(OsFile *id, i64 nByte){
|
|
955 LONG upperBits = nByte>>32;
|
|
956 assert( id!=0 );
|
|
957 TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte);
|
|
958 SimulateIOError(SQLITE_IOERR);
|
|
959 SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN);
|
|
960 SetEndOfFile(((winFile*)id)->h);
|
|
961 return SQLITE_OK;
|
|
962 }
|
|
963
|
|
964 /*
|
|
965 ** Determine the current size of a file in bytes
|
|
966 */
|
|
967 static int winFileSize(OsFile *id, i64 *pSize){
|
|
968 DWORD upperBits, lowerBits;
|
|
969 assert( id!=0 );
|
|
970 SimulateIOError(SQLITE_IOERR);
|
|
971 lowerBits = GetFileSize(((winFile*)id)->h, &upperBits);
|
|
972 *pSize = (((i64)upperBits)<<32) + lowerBits;
|
|
973 return SQLITE_OK;
|
|
974 }
|
|
975
|
|
976 /*
|
|
977 ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
|
|
978 */
|
|
979 #ifndef LOCKFILE_FAIL_IMMEDIATELY
|
|
980 # define LOCKFILE_FAIL_IMMEDIATELY 1
|
|
981 #endif
|
|
982
|
|
983 /*
|
|
984 ** Acquire a reader lock.
|
|
985 ** Different API routines are called depending on whether or not this
|
|
986 ** is Win95 or WinNT.
|
|
987 */
|
|
988 static int getReadLock(winFile *id){
|
|
989 int res;
|
|
990 if( isNT() ){
|
|
991 OVERLAPPED ovlp;
|
|
992 ovlp.Offset = SHARED_FIRST;
|
|
993 ovlp.OffsetHigh = 0;
|
|
994 ovlp.hEvent = 0;
|
|
995 res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp);
|
|
996 }else{
|
|
997 int lk;
|
|
998 sqlite3Randomness(sizeof(lk), &lk);
|
|
999 id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
|
|
1000 res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
|
|
1001 }
|
|
1002 return res;
|
|
1003 }
|
|
1004
|
|
1005 /*
|
|
1006 ** Undo a readlock
|
|
1007 */
|
|
1008 static int unlockReadLock(winFile *pFile){
|
|
1009 int res;
|
|
1010 if( isNT() ){
|
|
1011 res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
|
1012 }else{
|
|
1013 res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
|
|
1014 }
|
|
1015 return res;
|
|
1016 }
|
|
1017
|
|
1018 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
|
1019 /*
|
|
1020 ** Check that a given pathname is a directory and is writable
|
|
1021 **
|
|
1022 */
|
|
1023 int sqlite3WinIsDirWritable(char *zDirname){
|
|
1024 int fileAttr;
|
|
1025 WCHAR *zWide;
|
|
1026 if( zDirname==0 ) return 0;
|
|
1027 if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0;
|
|
1028 zWide = utf8ToUnicode(zDirname);
|
|
1029 if( zWide ){
|
|
1030 fileAttr = GetFileAttributesW(zWide);
|
|
1031 sqliteFree(zWide);
|
|
1032 }else{
|
|
1033 #if OS_WINCE
|
|
1034 return 0;
|
|
1035 #else
|
|
1036 fileAttr = GetFileAttributesA(zDirname);
|
|
1037 #endif
|
|
1038 }
|
|
1039 if( fileAttr == 0xffffffff ) return 0;
|
|
1040 if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
|
|
1041 return 0;
|
|
1042 }
|
|
1043 return 1;
|
|
1044 }
|
|
1045 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
|
|
1046
|
|
1047 /*
|
|
1048 ** Lock the file with the lock specified by parameter locktype - one
|
|
1049 ** of the following:
|
|
1050 **
|
|
1051 ** (1) SHARED_LOCK
|
|
1052 ** (2) RESERVED_LOCK
|
|
1053 ** (3) PENDING_LOCK
|
|
1054 ** (4) EXCLUSIVE_LOCK
|
|
1055 **
|
|
1056 ** Sometimes when requesting one lock state, additional lock states
|
|
1057 ** are inserted in between. The locking might fail on one of the later
|
|
1058 ** transitions leaving the lock state different from what it started but
|
|
1059 ** still short of its goal. The following chart shows the allowed
|
|
1060 ** transitions and the inserted intermediate states:
|
|
1061 **
|
|
1062 ** UNLOCKED -> SHARED
|
|
1063 ** SHARED -> RESERVED
|
|
1064 ** SHARED -> (PENDING) -> EXCLUSIVE
|
|
1065 ** RESERVED -> (PENDING) -> EXCLUSIVE
|
|
1066 ** PENDING -> EXCLUSIVE
|
|
1067 **
|
|
1068 ** This routine will only increase a lock. The winUnlock() routine
|
|
1069 ** erases all locks at once and returns us immediately to locking level 0.
|
|
1070 ** It is not possible to lower the locking level one step at a time. You
|
|
1071 ** must go straight to locking level 0.
|
|
1072 */
|
|
1073 static int winLock(OsFile *id, int locktype){
|
|
1074 int rc = SQLITE_OK; /* Return code from subroutines */
|
|
1075 int res = 1; /* Result of a windows lock call */
|
|
1076 int newLocktype; /* Set id->locktype to this value before exiting */
|
|
1077 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
|
|
1078 winFile *pFile = (winFile*)id;
|
|
1079
|
|
1080 assert( pFile!=0 );
|
|
1081 TRACE5("LOCK %d %d was %d(%d)\n",
|
|
1082 pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
|
|
1083
|
|
1084 /* If there is already a lock of this type or more restrictive on the
|
|
1085 ** OsFile, do nothing. Don't use the end_lock: exit path, as
|
|
1086 ** sqlite3OsEnterMutex() hasn't been called yet.
|
|
1087 */
|
|
1088 if( pFile->locktype>=locktype ){
|
|
1089 return SQLITE_OK;
|
|
1090 }
|
|
1091
|
|
1092 /* Make sure the locking sequence is correct
|
|
1093 */
|
|
1094 assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
|
|
1095 assert( locktype!=PENDING_LOCK );
|
|
1096 assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
|
|
1097
|
|
1098 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
|
|
1099 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
|
|
1100 ** the PENDING_LOCK byte is temporary.
|
|
1101 */
|
|
1102 newLocktype = pFile->locktype;
|
|
1103 if( pFile->locktype==NO_LOCK
|
|
1104 || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
|
|
1105 ){
|
|
1106 int cnt = 3;
|
|
1107 while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
|
|
1108 /* Try 3 times to get the pending lock. The pending lock might be
|
|
1109 ** held by another reader process who will release it momentarily.
|
|
1110 */
|
|
1111 TRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
|
|
1112 Sleep(1);
|
|
1113 }
|
|
1114 gotPendingLock = res;
|
|
1115 }
|
|
1116
|
|
1117 /* Acquire a shared lock
|
|
1118 */
|
|
1119 if( locktype==SHARED_LOCK && res ){
|
|
1120 assert( pFile->locktype==NO_LOCK );
|
|
1121 res = getReadLock(pFile);
|
|
1122 if( res ){
|
|
1123 newLocktype = SHARED_LOCK;
|
|
1124 }
|
|
1125 }
|
|
1126
|
|
1127 /* Acquire a RESERVED lock
|
|
1128 */
|
|
1129 if( locktype==RESERVED_LOCK && res ){
|
|
1130 assert( pFile->locktype==SHARED_LOCK );
|
|
1131 res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
|
|
1132 if( res ){
|
|
1133 newLocktype = RESERVED_LOCK;
|
|
1134 }
|
|
1135 }
|
|
1136
|
|
1137 /* Acquire a PENDING lock
|
|
1138 */
|
|
1139 if( locktype==EXCLUSIVE_LOCK && res ){
|
|
1140 newLocktype = PENDING_LOCK;
|
|
1141 gotPendingLock = 0;
|
|
1142 }
|
|
1143
|
|
1144 /* Acquire an EXCLUSIVE lock
|
|
1145 */
|
|
1146 if( locktype==EXCLUSIVE_LOCK && res ){
|
|
1147 assert( pFile->locktype>=SHARED_LOCK );
|
|
1148 res = unlockReadLock(pFile);
|
|
1149 TRACE2("unreadlock = %d\n", res);
|
|
1150 res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
|
1151 if( res ){
|
|
1152 newLocktype = EXCLUSIVE_LOCK;
|
|
1153 }else{
|
|
1154 TRACE2("error-code = %d\n", GetLastError());
|
|
1155 }
|
|
1156 }
|
|
1157
|
|
1158 /* If we are holding a PENDING lock that ought to be released, then
|
|
1159 ** release it now.
|
|
1160 */
|
|
1161 if( gotPendingLock && locktype==SHARED_LOCK ){
|
|
1162 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
|
|
1163 }
|
|
1164
|
|
1165 /* Update the state of the lock has held in the file descriptor then
|
|
1166 ** return the appropriate result code.
|
|
1167 */
|
|
1168 if( res ){
|
|
1169 rc = SQLITE_OK;
|
|
1170 }else{
|
|
1171 TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
|
|
1172 locktype, newLocktype);
|
|
1173 rc = SQLITE_BUSY;
|
|
1174 }
|
|
1175 pFile->locktype = newLocktype;
|
|
1176 return rc;
|
|
1177 }
|
|
1178
|
|
1179 /*
|
|
1180 ** This routine checks if there is a RESERVED lock held on the specified
|
|
1181 ** file by this or any other process. If such a lock is held, return
|
|
1182 ** non-zero, otherwise zero.
|
|
1183 */
|
|
1184 static int winCheckReservedLock(OsFile *id){
|
|
1185 int rc;
|
|
1186 winFile *pFile = (winFile*)id;
|
|
1187 assert( pFile!=0 );
|
|
1188 if( pFile->locktype>=RESERVED_LOCK ){
|
|
1189 rc = 1;
|
|
1190 TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
|
|
1191 }else{
|
|
1192 rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
|
|
1193 if( rc ){
|
|
1194 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
|
|
1195 }
|
|
1196 rc = !rc;
|
|
1197 TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
|
|
1198 }
|
|
1199 return rc;
|
|
1200 }
|
|
1201
|
|
1202 /*
|
|
1203 ** Lower the locking level on file descriptor id to locktype. locktype
|
|
1204 ** must be either NO_LOCK or SHARED_LOCK.
|
|
1205 **
|
|
1206 ** If the locking level of the file descriptor is already at or below
|
|
1207 ** the requested locking level, this routine is a no-op.
|
|
1208 **
|
|
1209 ** It is not possible for this routine to fail if the second argument
|
|
1210 ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
|
|
1211 ** might return SQLITE_IOERR;
|
|
1212 */
|
|
1213 static int winUnlock(OsFile *id, int locktype){
|
|
1214 int type;
|
|
1215 int rc = SQLITE_OK;
|
|
1216 winFile *pFile = (winFile*)id;
|
|
1217 assert( pFile!=0 );
|
|
1218 assert( locktype<=SHARED_LOCK );
|
|
1219 TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
|
|
1220 pFile->locktype, pFile->sharedLockByte);
|
|
1221 type = pFile->locktype;
|
|
1222 if( type>=EXCLUSIVE_LOCK ){
|
|
1223 UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
|
1224 if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
|
|
1225 /* This should never happen. We should always be able to
|
|
1226 ** reacquire the read lock */
|
|
1227 rc = SQLITE_IOERR;
|
|
1228 }
|
|
1229 }
|
|
1230 if( type>=RESERVED_LOCK ){
|
|
1231 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
|
|
1232 }
|
|
1233 if( locktype==NO_LOCK && type>=SHARED_LOCK ){
|
|
1234 unlockReadLock(pFile);
|
|
1235 }
|
|
1236 if( type>=PENDING_LOCK ){
|
|
1237 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
|
|
1238 }
|
|
1239 pFile->locktype = locktype;
|
|
1240 return rc;
|
|
1241 }
|
|
1242
|
|
1243 /*
|
|
1244 ** Turn a relative pathname into a full pathname. Return a pointer
|
|
1245 ** to the full pathname stored in space obtained from sqliteMalloc().
|
|
1246 ** The calling function is responsible for freeing this space once it
|
|
1247 ** is no longer needed.
|
|
1248 */
|
|
1249 char *sqlite3WinFullPathname(const char *zRelative){
|
|
1250 char *zFull;
|
|
1251 #if defined(__CYGWIN__)
|
|
1252 int nByte;
|
|
1253 nByte = strlen(zRelative) + MAX_PATH + 1001;
|
|
1254 zFull = sqliteMalloc( nByte );
|
|
1255 if( zFull==0 ) return 0;
|
|
1256 if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
|
|
1257 #elif OS_WINCE
|
|
1258 /* WinCE has no concept of a relative pathname, or so I am told. */
|
|
1259 zFull = sqliteStrDup(zRelative);
|
|
1260 #else
|
|
1261 char *zNotUsed;
|
|
1262 WCHAR *zWide;
|
|
1263 int nByte;
|
|
1264 zWide = utf8ToUnicode(zRelative);
|
|
1265 if( zWide ){
|
|
1266 WCHAR *zTemp, *zNotUsedW;
|
|
1267 nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1;
|
|
1268 zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
|
|
1269 if( zTemp==0 ) return 0;
|
|
1270 GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW);
|
|
1271 sqliteFree(zWide);
|
|
1272 zFull = unicodeToUtf8(zTemp);
|
|
1273 sqliteFree(zTemp);
|
|
1274 }else{
|
|
1275 nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
|
|
1276 zFull = sqliteMalloc( nByte*sizeof(zFull[0]) );
|
|
1277 if( zFull==0 ) return 0;
|
|
1278 GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
|
|
1279 }
|
|
1280 #endif
|
|
1281 return zFull;
|
|
1282 }
|
|
1283
|
|
1284 /*
|
|
1285 ** The fullSync option is meaningless on windows. This is a no-op.
|
|
1286 */
|
|
1287 static void winSetFullSync(OsFile *id, int v){
|
|
1288 return;
|
|
1289 }
|
|
1290
|
|
1291 /*
|
|
1292 ** Return the underlying file handle for an OsFile
|
|
1293 */
|
|
1294 static int winFileHandle(OsFile *id){
|
|
1295 return (int)((winFile*)id)->h;
|
|
1296 }
|
|
1297
|
|
1298 /*
|
|
1299 ** Return an integer that indices the type of lock currently held
|
|
1300 ** by this handle. (Used for testing and analysis only.)
|
|
1301 */
|
|
1302 static int winLockState(OsFile *id){
|
|
1303 return ((winFile*)id)->locktype;
|
|
1304 }
|
|
1305
|
|
1306 /*
|
|
1307 ** This vector defines all the methods that can operate on an OsFile
|
|
1308 ** for win32.
|
|
1309 */
|
|
1310 static const IoMethod sqlite3WinIoMethod = {
|
|
1311 winClose,
|
|
1312 winOpenDirectory,
|
|
1313 winRead,
|
|
1314 winWrite,
|
|
1315 winSeek,
|
|
1316 winTruncate,
|
|
1317 winSync,
|
|
1318 winSetFullSync,
|
|
1319 winFileHandle,
|
|
1320 winFileSize,
|
|
1321 winLock,
|
|
1322 winUnlock,
|
|
1323 winLockState,
|
|
1324 winCheckReservedLock,
|
|
1325 };
|
|
1326
|
|
1327 /*
|
|
1328 ** Allocate memory for an OsFile. Initialize the new OsFile
|
|
1329 ** to the value given in pInit and return a pointer to the new
|
|
1330 ** OsFile. If we run out of memory, close the file and return NULL.
|
|
1331 */
|
|
1332 static int allocateWinFile(winFile *pInit, OsFile **pId){
|
|
1333 winFile *pNew;
|
|
1334 pNew = sqliteMalloc( sizeof(*pNew) );
|
|
1335 if( pNew==0 ){
|
|
1336 CloseHandle(pInit->h);
|
|
1337 #if OS_WINCE
|
|
1338 sqliteFree(pInit->zDeleteOnClose);
|
|
1339 #endif
|
|
1340 *pId = 0;
|
|
1341 return SQLITE_NOMEM;
|
|
1342 }else{
|
|
1343 *pNew = *pInit;
|
|
1344 pNew->pMethod = &sqlite3WinIoMethod;
|
|
1345 pNew->locktype = NO_LOCK;
|
|
1346 pNew->sharedLockByte = 0;
|
|
1347 *pId = (OsFile*)pNew;
|
|
1348 OpenCounter(+1);
|
|
1349 return SQLITE_OK;
|
|
1350 }
|
|
1351 }
|
|
1352
|
|
1353
|
|
1354 #endif /* SQLITE_OMIT_DISKIO */
|
|
1355 /***************************************************************************
|
|
1356 ** Everything above deals with file I/O. Everything that follows deals
|
|
1357 ** with other miscellanous aspects of the operating system interface
|
|
1358 ****************************************************************************/
|
|
1359
|
|
1360 /*
|
|
1361 ** Get information to seed the random number generator. The seed
|
|
1362 ** is written into the buffer zBuf[256]. The calling function must
|
|
1363 ** supply a sufficiently large buffer.
|
|
1364 */
|
|
1365 int sqlite3WinRandomSeed(char *zBuf){
|
|
1366 /* We have to initialize zBuf to prevent valgrind from reporting
|
|
1367 ** errors. The reports issued by valgrind are incorrect - we would
|
|
1368 ** prefer that the randomness be increased by making use of the
|
|
1369 ** uninitialized space in zBuf - but valgrind errors tend to worry
|
|
1370 ** some users. Rather than argue, it seems easier just to initialize
|
|
1371 ** the whole array and silence valgrind, even if that means less randomness
|
|
1372 ** in the random seed.
|
|
1373 **
|
|
1374 ** When testing, initializing zBuf[] to zero is all we do. That means
|
|
1375 ** that we always use the same random number sequence.* This makes the
|
|
1376 ** tests repeatable.
|
|
1377 */
|
|
1378 memset(zBuf, 0, 256);
|
|
1379 GetSystemTime((LPSYSTEMTIME)zBuf);
|
|
1380 return SQLITE_OK;
|
|
1381 }
|
|
1382
|
|
1383 /*
|
|
1384 ** Sleep for a little while. Return the amount of time slept.
|
|
1385 */
|
|
1386 int sqlite3WinSleep(int ms){
|
|
1387 Sleep(ms);
|
|
1388 return ms;
|
|
1389 }
|
|
1390
|
|
1391 /*
|
|
1392 ** Static variables used for thread synchronization
|
|
1393 */
|
|
1394 static int inMutex = 0;
|
|
1395 #ifdef SQLITE_W32_THREADS
|
|
1396 static DWORD mutexOwner;
|
|
1397 static CRITICAL_SECTION cs;
|
|
1398 #endif
|
|
1399
|
|
1400 /*
|
|
1401 ** The following pair of routines implement mutual exclusion for
|
|
1402 ** multi-threaded processes. Only a single thread is allowed to
|
|
1403 ** executed code that is surrounded by EnterMutex() and LeaveMutex().
|
|
1404 **
|
|
1405 ** SQLite uses only a single Mutex. There is not much critical
|
|
1406 ** code and what little there is executes quickly and without blocking.
|
|
1407 **
|
|
1408 ** Version 3.3.1 and earlier used a simple mutex. Beginning with
|
|
1409 ** version 3.3.2, a recursive mutex is required.
|
|
1410 */
|
|
1411 void sqlite3WinEnterMutex(){
|
|
1412 #ifdef SQLITE_W32_THREADS
|
|
1413 static int isInit = 0;
|
|
1414 while( !isInit ){
|
|
1415 static long lock = 0;
|
|
1416 if( InterlockedIncrement(&lock)==1 ){
|
|
1417 InitializeCriticalSection(&cs);
|
|
1418 isInit = 1;
|
|
1419 }else{
|
|
1420 Sleep(1);
|
|
1421 }
|
|
1422 }
|
|
1423 EnterCriticalSection(&cs);
|
|
1424 mutexOwner = GetCurrentThreadId();
|
|
1425 #endif
|
|
1426 inMutex++;
|
|
1427 }
|
|
1428 void sqlite3WinLeaveMutex(){
|
|
1429 assert( inMutex );
|
|
1430 inMutex--;
|
|
1431 #ifdef SQLITE_W32_THREADS
|
|
1432 assert( mutexOwner==GetCurrentThreadId() );
|
|
1433 LeaveCriticalSection(&cs);
|
|
1434 #endif
|
|
1435 }
|
|
1436
|
|
1437 /*
|
|
1438 ** Return TRUE if the mutex is currently held.
|
|
1439 **
|
|
1440 ** If the thisThreadOnly parameter is true, return true if and only if the
|
|
1441 ** calling thread holds the mutex. If the parameter is false, return
|
|
1442 ** true if any thread holds the mutex.
|
|
1443 */
|
|
1444 int sqlite3WinInMutex(int thisThreadOnly){
|
|
1445 #ifdef SQLITE_W32_THREADS
|
|
1446 return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId());
|
|
1447 #else
|
|
1448 return inMutex>0;
|
|
1449 #endif
|
|
1450 }
|
|
1451
|
|
1452
|
|
1453 /*
|
|
1454 ** The following variable, if set to a non-zero value, becomes the result
|
|
1455 ** returned from sqlite3OsCurrentTime(). This is used for testing.
|
|
1456 */
|
|
1457 #ifdef SQLITE_TEST
|
|
1458 int sqlite3_current_time = 0;
|
|
1459 #endif
|
|
1460
|
|
1461 /*
|
|
1462 ** Find the current time (in Universal Coordinated Time). Write the
|
|
1463 ** current time and date as a Julian Day number into *prNow and
|
|
1464 ** return 0. Return 1 if the time and date cannot be found.
|
|
1465 */
|
|
1466 int sqlite3WinCurrentTime(double *prNow){
|
|
1467 FILETIME ft;
|
|
1468 /* FILETIME structure is a 64-bit value representing the number of
|
|
1469 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
|
|
1470 */
|
|
1471 double now;
|
|
1472 #if OS_WINCE
|
|
1473 SYSTEMTIME time;
|
|
1474 GetSystemTime(&time);
|
|
1475 SystemTimeToFileTime(&time,&ft);
|
|
1476 #else
|
|
1477 GetSystemTimeAsFileTime( &ft );
|
|
1478 #endif
|
|
1479 now = ((double)ft.dwHighDateTime) * 4294967296.0;
|
|
1480 *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
|
|
1481 #ifdef SQLITE_TEST
|
|
1482 if( sqlite3_current_time ){
|
|
1483 *prNow = sqlite3_current_time/86400.0 + 2440587.5;
|
|
1484 }
|
|
1485 #endif
|
|
1486 return 0;
|
|
1487 }
|
|
1488
|
|
1489 /*
|
|
1490 ** Remember the number of thread-specific-data blocks allocated.
|
|
1491 ** Use this to verify that we are not leaking thread-specific-data.
|
|
1492 ** Ticket #1601
|
|
1493 */
|
|
1494 #ifdef SQLITE_TEST
|
|
1495 int sqlite3_tsd_count = 0;
|
|
1496 # define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count)
|
|
1497 # define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count)
|
|
1498 #else
|
|
1499 # define TSD_COUNTER_INCR /* no-op */
|
|
1500 # define TSD_COUNTER_DECR /* no-op */
|
|
1501 #endif
|
|
1502
|
|
1503
|
|
1504
|
|
1505 /*
|
|
1506 ** If called with allocateFlag>1, then return a pointer to thread
|
|
1507 ** specific data for the current thread. Allocate and zero the
|
|
1508 ** thread-specific data if it does not already exist necessary.
|
|
1509 **
|
|
1510 ** If called with allocateFlag==0, then check the current thread
|
|
1511 ** specific data. Return it if it exists. If it does not exist,
|
|
1512 ** then return NULL.
|
|
1513 **
|
|
1514 ** If called with allocateFlag<0, check to see if the thread specific
|
|
1515 ** data is allocated and is all zero. If it is then deallocate it.
|
|
1516 ** Return a pointer to the thread specific data or NULL if it is
|
|
1517 ** unallocated or gets deallocated.
|
|
1518 */
|
|
1519 ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){
|
|
1520 static int key;
|
|
1521 static int keyInit = 0;
|
|
1522 static const ThreadData zeroData = {0};
|
|
1523 ThreadData *pTsd;
|
|
1524
|
|
1525 if( !keyInit ){
|
|
1526 sqlite3OsEnterMutex();
|
|
1527 if( !keyInit ){
|
|
1528 key = TlsAlloc();
|
|
1529 if( key==0xffffffff ){
|
|
1530 sqlite3OsLeaveMutex();
|
|
1531 return 0;
|
|
1532 }
|
|
1533 keyInit = 1;
|
|
1534 }
|
|
1535 sqlite3OsLeaveMutex();
|
|
1536 }
|
|
1537 pTsd = TlsGetValue(key);
|
|
1538 if( allocateFlag>0 ){
|
|
1539 if( !pTsd ){
|
|
1540 pTsd = sqlite3OsMalloc( sizeof(zeroData) );
|
|
1541 if( pTsd ){
|
|
1542 *pTsd = zeroData;
|
|
1543 TlsSetValue(key, pTsd);
|
|
1544 TSD_COUNTER_INCR;
|
|
1545 }
|
|
1546 }
|
|
1547 }else if( pTsd!=0 && allocateFlag<0
|
|
1548 && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){
|
|
1549 sqlite3OsFree(pTsd);
|
|
1550 TlsSetValue(key, 0);
|
|
1551 TSD_COUNTER_DECR;
|
|
1552 pTsd = 0;
|
|
1553 }
|
|
1554 return pTsd;
|
|
1555 }
|
|
1556 #endif /* OS_WIN */
|