📄 os_win.c
字号:
if (dwFileOffsetLow == SHARED_FIRST && nNumberOfBytesToLockLow == SHARED_SIZE){ if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ pFile->shared->bExclusive = TRUE; pFile->local.bExclusive = TRUE; bReturn = TRUE; } } /* Want a read-only lock? */ else if ((dwFileOffsetLow >= SHARED_FIRST && dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) && nNumberOfBytesToLockLow == 1){ if (pFile->shared->bExclusive == 0){ pFile->local.nReaders ++; if (pFile->local.nReaders == 1){ pFile->shared->nReaders ++; } bReturn = TRUE; } } /* Want a pending lock? */ else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){ /* If no pending lock has been acquired, then acquire it */ if (pFile->shared->bPending == 0) { pFile->shared->bPending = TRUE; pFile->local.bPending = TRUE; bReturn = TRUE; } } /* Want a reserved lock? */ else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ if (pFile->shared->bReserved == 0) { pFile->shared->bReserved = TRUE; pFile->local.bReserved = TRUE; bReturn = TRUE; } } winceMutexRelease(pFile->hMutex); return bReturn;}/*** An implementation of the UnlockFile API of windows for wince*/static BOOL winceUnlockFile( HANDLE *phFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh){ winFile *pFile = HANDLE_TO_WINFILE(phFile); BOOL bReturn = FALSE; if (!pFile->hMutex) return TRUE; winceMutexAcquire(pFile->hMutex); /* Releasing a reader lock or an exclusive lock */ if (dwFileOffsetLow >= SHARED_FIRST && dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){ /* Did we have an exclusive lock? */ if (pFile->local.bExclusive){ pFile->local.bExclusive = FALSE; pFile->shared->bExclusive = FALSE; bReturn = TRUE; } /* Did we just have a reader lock? */ else if (pFile->local.nReaders){ pFile->local.nReaders --; if (pFile->local.nReaders == 0) { pFile->shared->nReaders --; } bReturn = TRUE; } } /* Releasing a pending lock */ else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ if (pFile->local.bPending){ pFile->local.bPending = FALSE; pFile->shared->bPending = FALSE; bReturn = TRUE; } } /* Releasing a reserved lock */ else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ if (pFile->local.bReserved) { pFile->local.bReserved = FALSE; pFile->shared->bReserved = FALSE; bReturn = TRUE; } } winceMutexRelease(pFile->hMutex); return bReturn;}/*** An implementation of the LockFileEx() API of windows for wince*/static BOOL winceLockFileEx( HANDLE *phFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped){ /* If the caller wants a shared read lock, forward this call ** to winceLockFile */ if (lpOverlapped->Offset == SHARED_FIRST && dwFlags == 1 && nNumberOfBytesToLockLow == SHARED_SIZE){ return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); } return FALSE;}/*** End of the special code for wince*****************************************************************************/#endif /* OS_WINCE *//*** Convert a UTF-8 filename into whatever form the underlying** operating system wants filenames in. Space to hold the result** is obtained from sqliteMalloc and must be freed by the calling** function.*/static void *convertUtf8Filename(const char *zFilename){ void *zConverted = 0; if( isNT() ){ zConverted = utf8ToUnicode(zFilename); }else{ zConverted = utf8ToMbcs(zFilename); } /* caller will handle out of memory */ return zConverted;}/*** Delete the named file.**** Note that windows does not allow a file to be deleted if some other** process has it open. Sometimes a virus scanner or indexing program** will open a journal file shortly after it is created in order to do** whatever it is it does. While this other process is holding the** file open, we will be unable to delete it. To work around this** problem, we delay 100 milliseconds and try to delete again. Up** to MX_DELETION_ATTEMPTs deletion attempts are run before giving** up and returning an error.*/#define MX_DELETION_ATTEMPTS 3int sqlite3WinDelete(const char *zFilename){ int cnt = 0; int rc; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } SimulateIOError(return SQLITE_IOERR_DELETE); if( isNT() ){ do{ rc = DeleteFileW(zConverted); }while( rc==0 && GetFileAttributesW(zConverted)!=0xffffffff && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); }else{#if OS_WINCE return SQLITE_NOMEM;#else do{ rc = DeleteFileA(zConverted); }while( rc==0 && GetFileAttributesA(zConverted)!=0xffffffff && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );#endif } sqliteFree(zConverted); OSTRACE2("DELETE \"%s\"\n", zFilename); return rc!=0 ? SQLITE_OK : SQLITE_IOERR;}/*** Return TRUE if the named file exists.*/int sqlite3WinFileExists(const char *zFilename){ int exists = 0; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ exists = GetFileAttributesW((WCHAR*)zConverted) != 0xffffffff; }else{#if OS_WINCE return SQLITE_NOMEM;#else exists = GetFileAttributesA((char*)zConverted) != 0xffffffff;#endif } sqliteFree(zConverted); return exists;}/* Forward declaration */static int allocateWinFile(winFile *pInit, OsFile **pId);/*** Attempt to open a file for both reading and writing. If that** fails, try opening it read-only. If the file does not exist,** try to create it.**** On success, a handle for the open file is written to *id** and *pReadonly is set to 0 if the file was opened for reading and** writing or 1 if the file was opened read-only. The function returns** SQLITE_OK.**** On failure, the function returns SQLITE_CANTOPEN and leaves** *id and *pReadonly unchanged.*/int sqlite3WinOpenReadWrite( const char *zFilename, OsFile **pId, int *pReadonly){ winFile f; HANDLE h; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } assert( *pId==0 ); if( isNT() ){ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ sqliteFree(zConverted); return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; }#if OS_WINCE if (!winceCreateLock(zFilename, &f)){ CloseHandle(h); sqliteFree(zConverted); return SQLITE_CANTOPEN; }#endif }else{#if OS_WINCE return SQLITE_NOMEM;#else h = CreateFileA((char*)zConverted, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ h = CreateFileA((char*)zConverted, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ sqliteFree(zConverted); return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; }#endif /* OS_WINCE */ } sqliteFree(zConverted); f.h = h;#if OS_WINCE f.zDeleteOnClose = 0;#endif OSTRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); return allocateWinFile(&f, pId);}/*** Attempt to open a new file for exclusive access by this process.** The file will be opened for both reading and writing. To avoid** a potential security problem, we do not allow the file to have** previously existed. Nor do we allow the file to be a symbolic** link.**** If delFlag is true, then make arrangements to automatically delete** the file when it is closed.**** On success, write the file handle into *id and return SQLITE_OK.**** On failure, return SQLITE_CANTOPEN.**** Sometimes if we have just deleted a prior journal file, windows** will fail to open a new one because there is a "pending delete".** To work around this bug, we pause for 100 milliseconds and attempt** a second open after the first one fails. The whole operation only** fails if both open attempts are unsuccessful.*/int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ winFile f; HANDLE h; DWORD fileflags; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } assert( *pId == 0 ); fileflags = FILE_FLAG_RANDOM_ACCESS;#if !OS_WINCE if( delFlag ){ fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; }#endif if( isNT() ){ int cnt = 0; do{ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); }else{#if OS_WINCE return SQLITE_NOMEM;#else int cnt = 0; do{ h = CreateFileA((char*)zConverted, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) );#endif /* OS_WINCE */ }#if OS_WINCE if( delFlag && h!=INVALID_HANDLE_VALUE ){ f.zDeleteOnClose = zConverted; zConverted = 0; } f.hMutex = NULL;#endif sqliteFree(zConverted); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } f.h = h; OSTRACE3("OPEN EX %d \"%s\"\n", h, zFilename); return allocateWinFile(&f, pId);}/*** Attempt to open a new file for read-only access.**** On success, write the file handle into *id and return SQLITE_OK.**** On failure, return SQLITE_CANTOPEN.*/int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ winFile f; HANDLE h; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } assert( *pId==0 ); if( isNT() ){ h = CreateFileW((WCHAR*)zConverted, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); }else{#if OS_WINCE return SQLITE_NOMEM;#else h = CreateFileA((char*)zConverted, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL );#endif } sqliteFree(zConverted); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } f.h = h;#if OS_WINCE f.zDeleteOnClose = 0; f.hMutex = NULL;#endif OSTRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -