📄 os_win.c
字号:
winFileControl, winSectorSize, winDeviceCharacteristics};/***************************************************************************** Here ends the I/O methods that form the sqlite3_io_methods object.**** The next block of code implements the VFS methods.****************************************************************************//*** Convert a UTF-8 filename into whatever form the underlying** operating system wants filenames in. Space to hold the result** is obtained from malloc 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;}/*** Open a file.*/static int winOpen( sqlite3_vfs *pVfs, /* Not used */ const char *zName, /* Name of the file (UTF-8) */ sqlite3_file *id, /* Write the SQLite file handle here */ int flags, /* Open mode flags */ int *pOutFlags /* Status return flags */){ HANDLE h; DWORD dwDesiredAccess; DWORD dwShareMode; DWORD dwCreationDisposition; DWORD dwFlagsAndAttributes = 0; int isTemp; winFile *pFile = (winFile*)id; void *zConverted = convertUtf8Filename(zName); if( zConverted==0 ){ return SQLITE_NOMEM; } if( flags & SQLITE_OPEN_READWRITE ){ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; }else{ dwDesiredAccess = GENERIC_READ; } if( flags & SQLITE_OPEN_CREATE ){ dwCreationDisposition = OPEN_ALWAYS; }else{ dwCreationDisposition = OPEN_EXISTING; } if( flags & SQLITE_OPEN_MAIN_DB ){ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; }else{ dwShareMode = 0; } if( flags & SQLITE_OPEN_DELETEONCLOSE ){#if OS_WINCE dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;#else dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_DELETE_ON_CLOSE;#endif isTemp = 1; }else{ dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; isTemp = 0; } /* Reports from the internet are that performance is always ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; if( isNT() ){ h = CreateFileW((WCHAR*)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL ); }else{#if OS_WINCE return SQLITE_NOMEM;#else h = CreateFileA((char*)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL );#endif } if( h==INVALID_HANDLE_VALUE ){ free(zConverted); if( flags & SQLITE_OPEN_READWRITE ){ return winOpen(0, zName, id, ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); }else{ return SQLITE_CANTOPEN; } } if( pOutFlags ){ if( flags & SQLITE_OPEN_READWRITE ){ *pOutFlags = SQLITE_OPEN_READWRITE; }else{ *pOutFlags = SQLITE_OPEN_READONLY; } } memset(pFile, 0, sizeof(*pFile)); pFile->pMethod = &winIoMethod; pFile->h = h;#if OS_WINCE if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) == (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) && !winceCreateLock(zName, pFile) ){ CloseHandle(h); free(zConverted); return SQLITE_CANTOPEN; } if( isTemp ){ pFile->zDeleteOnClose = zConverted; }else#endif { free(zConverted); } OpenCounter(+1); return SQLITE_OK;}/*** 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 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 5static int winDelete( sqlite3_vfs *pVfs, /* Not used on win32 */ const char *zFilename, /* Name of file to delete */ int syncDir /* Not used on win32 */){ int cnt = 0; int rc; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } SimulateIOError(return SQLITE_IOERR_DELETE); if( isNT() ){ do{ DeleteFileW(zConverted); }while( (rc = GetFileAttributesW(zConverted))!=0xffffffff && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); }else{#if OS_WINCE return SQLITE_NOMEM;#else do{ DeleteFileA(zConverted); }while( (rc = GetFileAttributesA(zConverted))!=0xffffffff && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );#endif } free(zConverted); OSTRACE2("DELETE \"%s\"\n", zFilename); return rc==0xffffffff ? SQLITE_OK : SQLITE_IOERR_DELETE;}/*** Check the existance and status of a file.*/static int winAccess( sqlite3_vfs *pVfs, /* Not used on win32 */ const char *zFilename, /* Name of file to check */ int flags /* Type of test to make on this file */){ DWORD attr; int rc; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return SQLITE_NOMEM; } if( isNT() ){ attr = GetFileAttributesW((WCHAR*)zConverted); }else{#if OS_WINCE return SQLITE_NOMEM;#else attr = GetFileAttributesA((char*)zConverted);#endif } free(zConverted); switch( flags ){ case SQLITE_ACCESS_READ: case SQLITE_ACCESS_EXISTS: rc = attr!=0xffffffff; break; case SQLITE_ACCESS_READWRITE: rc = (attr & FILE_ATTRIBUTE_READONLY)==0; break; default: assert(!"Invalid flags argument"); } return rc;}/*** Create a temporary file name in zBuf. zBuf must be big enough to** hold at pVfs->mxPathname characters.*/static int winGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; int i, j; char zTempPath[MAX_PATH+1]; if( sqlite3_temp_directory ){ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); }else if( isNT() ){ char *zMulti; WCHAR zWidePath[MAX_PATH]; GetTempPathW(MAX_PATH-30, zWidePath); zMulti = unicodeToUtf8(zWidePath); if( zMulti ){ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); free(zMulti); }else{ return SQLITE_NOMEM; } }else{ char *zUtf8; char zMbcsPath[MAX_PATH]; GetTempPathA(MAX_PATH-30, zMbcsPath); zUtf8 = mbcsToUtf8(zMbcsPath); if( zUtf8 ){ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); free(zUtf8); }else{ return SQLITE_NOMEM; } } for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; sqlite3_snprintf(nBuf-30, zBuf, "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); j = strlen(zBuf); sqlite3Randomness(20, &zBuf[j]); for(i=0; i<20; i++, j++){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; OSTRACE2("TEMP FILENAME: %s\n", zBuf); return SQLITE_OK; }/*** Turn a relative pathname into a full pathname. Write the full** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname** bytes in size.*/static int winFullPathname( sqlite3_vfs *pVfs, /* Pointer to vfs object */ const char *zRelative, /* Possibly relative input path */ int nFull, /* Size of output buffer in bytes */ char *zFull /* Output buffer */){#if defined(__CYGWIN__) cygwin_conv_to_full_win32_path(zRelative, zFull); return SQLITE_OK;#endif#if OS_WINCE /* WinCE has no concept of a relative pathname, or so I am told. */ sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); return SQLITE_OK;#endif#if !OS_WINCE && !defined(__CYGWIN__) int nByte; void *zConverted; char *zOut; zConverted = convertUtf8Filename(zRelative); if( isNT() ){ WCHAR *zTemp; nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; zTemp = malloc( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ free(zConverted); return SQLITE_NOMEM; } GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); free(zConverted); zOut = unicodeToUtf8(zTemp); free(zTemp); }else{ char *zTemp; nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; zTemp = malloc( nByte*sizeof(zTemp[0]) ); if( zTemp==0 ){ free(zConverted); return SQLITE_NOMEM; } GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); free(zConverted); zOut = mbcsToUtf8(zTemp); free(zTemp); } if( zOut ){ sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); free(zOut); return SQLITE_OK; }else{ return SQLITE_NOMEM; }#endif}#ifndef SQLITE_OMIT_LOAD_EXTENSION/*** Interfaces for opening a shared library, finding entry points** within the shared library, and closing the shared library.*//*** Interfaces for opening a shared library, finding entry points** within the shared library, and closing the shared library.*/static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ return 0; } if( isNT() ){ h = LoadLibraryW((WCHAR*)zConverted); }else{#if OS_WINCE return 0;#else h = LoadLibraryA((char*)zConverted);#endif } free(zConverted); return (void*)h;}static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){#if OS_WINCE int error = GetLastError(); if( error>0x7FFFFFF ){ sqlite3_snprintf(nBuf, zBufOut, "OsError 0x%x", error); }else{ sqlite3_snprintf(nBuf, zBufOut, "OsError %d", error); }#else FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, zBufOut, nBuf-1, 0 );#endif}void *winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){#if OS_WINCE /* The GetProcAddressA() routine is only available on wince. */ return GetProcAddressA((HANDLE)pHandle, zSymbol);#else /* All other windows platforms expect GetProcAddress() to take ** an Ansi string regardless of the _UNICODE setting */ return GetProcAddress((HANDLE)pHandle, zSymbol);#endif}void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ FreeLibrary((HANDLE)pHandle);}#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ #define winDlOpen 0 #define winDlError 0 #define winDlSym 0 #define winDlClose 0#endif/*** Write up to nBuf bytes of randomness into zBuf.*/static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ int n = 0; if( sizeof(SYSTEMTIME)<=nBuf-n ){ SYSTEMTIME x; GetSystemTime(&x); memcpy(&zBuf[n], &x, sizeof(x)); n += sizeof(x); } if( sizeof(DWORD)<=nBuf-n ){ DWORD pid = GetCurrentProcessId(); memcpy(&zBuf[n], &pid, sizeof(pid)); n += sizeof(pid); } if( sizeof(DWORD)<=nBuf-n ){ DWORD cnt = GetTickCount(); memcpy(&zBuf[n], &cnt, sizeof(cnt)); n += sizeof(cnt); } if( sizeof(LARGE_INTEGER)<=nBuf-n ){ LARGE_INTEGER i; QueryPerformanceCounter(&i); memcpy(&zBuf[n], &i, sizeof(i)); n += sizeof(i); } return n;}/*** Sleep for a little while. Return the amount of time slept.*/static int winSleep(sqlite3_vfs *pVfs, int microsec){ Sleep((microsec+999)/1000); return ((microsec+999)/1000)*1000;}/*** The following variable, if set to a non-zero value, becomes the result** returned from sqlite3OsCurrentTime(). This is used for testing.*/#ifdef SQLITE_TESTint sqlite3_current_time = 0;#endif/*** Find the current time (in Universal Coordinated Time). Write the** current time and date as a Julian Day number into *prNow and** return 0. Return 1 if the time and date cannot be found.*/int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). */ double now;#if OS_WINCE SYSTEMTIME time; GetSystemTime(&time); SystemTimeToFileTime(&time,&ft);#else GetSystemTimeAsFileTime( &ft );#endif now = ((double)ft.dwHighDateTime) * 4294967296.0; *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;#ifdef SQLITE_TEST if( sqlite3_current_time ){ *prNow = sqlite3_current_time/86400.0 + 2440587.5; }#endif return 0;}/*** Return a pointer to the sqlite3DefaultVfs structure. We use** a function rather than give the structure global scope because** some compilers (MSVC) do not allow forward declarations of** initialized structures.*/sqlite3_vfs *sqlite3OsDefaultVfs(void){ static sqlite3_vfs winVfs = { 1, /* iVersion */ sizeof(winFile), /* szOsFile */ MAX_PATH, /* mxPathname */ 0, /* pNext */ "win32", /* zName */ 0, /* pAppData */ winOpen, /* xOpen */ winDelete, /* xDelete */ winAccess, /* xAccess */ winGetTempname, /* xGetTempName */ winFullPathname, /* xFullPathname */ winDlOpen, /* xDlOpen */ winDlError, /* xDlError */ winDlSym, /* xDlSym */ winDlClose, /* xDlClose */ winRandomness, /* xRandomness */ winSleep, /* xSleep */ winCurrentTime /* xCurrentTime */ }; return &winVfs;}#endif /* OS_WIN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -