?? os_win.c
字號:
/*** 2004 May 22**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.************************************************************************************ This file contains code that is specific to windows.*/#include "sqliteInt.h"#include "os.h"#if OS_WIN /* This file is used for windows only */#include <winbase.h>#ifdef __CYGWIN__# include <sys/cygwin.h>#endif/*** Macros used to determine whether or not to use threads.*/#if defined(THREADSAFE) && THREADSAFE# define SQLITE_W32_THREADS 1#endif/*** Include code that is common to all os_*.c files*/#include "os_common.h"/*** Do not include any of the File I/O interface procedures if the** SQLITE_OMIT_DISKIO macro is defined (indicating that there database** will be in-memory only)*/#ifndef SQLITE_OMIT_DISKIO/*** The following variable is (normally) set once and never changes** thereafter. It records whether the operating system is Win95** or WinNT.**** 0: Operating system unknown.** 1: Operating system is Win95.** 2: Operating system is WinNT.**** In order to facilitate testing on a WinNT system, the test fixture** can manually set this value to 1 to emulate Win98 behavior.*/int sqlite3_os_type = 0;/*** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.** Return false (zero) for Win95, Win98, or WinME.**** Here is an interesting observation: Win95, Win98, and WinME lack** the LockFileEx() API. But we can still statically link against that** API as long as we don't call it win running Win95/98/ME. A call to** this routine is used to determine if the host is Win95/98/ME or** WinNT/2K/XP so that we will know whether or not we can safely call** the LockFileEx() API.*/static int isNT(void){ if( sqlite3_os_type==0 ){ OSVERSIONINFO sInfo; sInfo.dwOSVersionInfoSize = sizeof(sInfo); GetVersionEx(&sInfo); sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; } return sqlite3_os_type==2;}/*** Convert a UTF-8 string to UTF-32. Space to hold the returned string** is obtained from sqliteMalloc.*/static WCHAR *utf8ToUnicode(const char *zFilename){ int nByte; WCHAR *zWideFilename; if( !isNT() ){ return 0; } nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR); zWideFilename = sqliteMalloc( nByte*sizeof(zWideFilename[0]) ); if( zWideFilename==0 ){ return 0; } nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nByte); if( nByte==0 ){ sqliteFree(zWideFilename); zWideFilename = 0; } return zWideFilename;}/*** Convert UTF-32 to UTF-8. Space to hold the returned string is** obtained from sqliteMalloc().*/static char *unicodeToUtf8(const WCHAR *zWideFilename){ int nByte; char *zFilename; nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); zFilename = sqliteMalloc( nByte ); if( zFilename==0 ){ return 0; } nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, 0, 0); if( nByte == 0 ){ sqliteFree(zFilename); zFilename = 0; } return zFilename;}/*** Delete the named file*/int sqlite3OsDelete(const char *zFilename){ WCHAR *zWide = utf8ToUnicode(zFilename); if( zWide ){ DeleteFileW(zWide); sqliteFree(zWide); }else{ DeleteFileA(zFilename); } TRACE2("DELETE \"%s\"\n", zFilename); return SQLITE_OK;}/*** Return TRUE if the named file exists.*/int sqlite3OsFileExists(const char *zFilename){ int exists = 0; WCHAR *zWide = utf8ToUnicode(zFilename); if( zWide ){ exists = GetFileAttributesW(zWide) != 0xffffffff; sqliteFree(zWide); }else{ exists = GetFileAttributesA(zFilename) != 0xffffffff; } return exists;}/*** 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 sqlite3OsOpenReadWrite( const char *zFilename, OsFile *id, int *pReadonly){ HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); assert( !id->isOpen ); if( zWide ){ h = CreateFileW(zWide, 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(zWide, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ sqliteFree(zWide); return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } sqliteFree(zWide); }else{ h = CreateFileA(zFilename, 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(zFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } } id->h = h; id->locktype = NO_LOCK; id->sharedLockByte = 0; id->isOpen = 1; OpenCounter(+1); TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); return SQLITE_OK;}/*** 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.*/int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ HANDLE h; int fileflags; WCHAR *zWide = utf8ToUnicode(zFilename); assert( !id->isOpen ); if( delFlag ){ fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_DELETE_ON_CLOSE; }else{ fileflags = FILE_FLAG_RANDOM_ACCESS; } if( zWide ){ h = CreateFileW(zWide, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); sqliteFree(zWide); }else{ h = CreateFileA(zFilename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } id->h = h; id->locktype = NO_LOCK; id->sharedLockByte = 0; id->isOpen = 1; OpenCounter(+1); TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); return SQLITE_OK;}/*** 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 sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ HANDLE h; WCHAR *zWide = utf8ToUnicode(zFilename); assert( !id->isOpen ); if( zWide ){ h = CreateFileW(zWide, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); sqliteFree(zWide); }else{ h = CreateFileA(zFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } id->h = h; id->locktype = NO_LOCK; id->sharedLockByte = 0; id->isOpen = 1; OpenCounter(+1); TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); return SQLITE_OK;}/*** Attempt to open a file descriptor for the directory that contains a** file. This file descriptor can be used to fsync() the directory** in order to make sure the creation of a new file is actually written** to disk.**** This routine is only meaningful for Unix. It is a no-op under** windows since windows does not support hard links.**** On success, a handle for a previously open file is at *id is** updated with the new directory file descriptor and SQLITE_OK is** returned.**** On failure, the function returns SQLITE_CANTOPEN and leaves** *id unchanged.*/int sqlite3OsOpenDirectory( const char *zDirname, OsFile *id){ return SQLITE_OK;}/*** If the following global variable points to a string which is the** name of a directory, then that directory will be used to store** temporary files.*/char *sqlite3_temp_directory = 0;/*** Create a temporary file name in zBuf. zBuf must be big enough to** hold at least SQLITE_TEMPNAME_SIZE characters.*/int sqlite3OsTempFileName(char *zBuf){ static char zChars[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; int i, j; char zTempPath[SQLITE_TEMPNAME_SIZE]; if( sqlite3_temp_directory ){ strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; }else if( isNT() ){ char *zMulti; WCHAR zWidePath[SQLITE_TEMPNAME_SIZE]; GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath); zMulti = unicodeToUtf8(zWidePath); if( zMulti ){ strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; sqliteFree(zMulti); } }else{ GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath); } for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; for(;;){ sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath); j = strlen(zBuf); sqlite3Randomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; } zBuf[j] = 0; if( !sqlite3OsFileExists(zBuf) ) break; } TRACE2("TEMP FILENAME: %s\n", zBuf); return SQLITE_OK; }/*** Close a file.*/int sqlite3OsClose(OsFile *id){ if( id->isOpen ){ TRACE2("CLOSE %d\n", id->h); CloseHandle(id->h); OpenCounter(-1); id->isOpen = 0; } return SQLITE_OK;}/*** Read data from a file into a buffer. Return SQLITE_OK if all** bytes were read successfully and SQLITE_IOERR if anything goes** wrong.*/int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ DWORD got; assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); TRACE3("READ %d lock=%d\n", id->h, id->locktype); if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ got = 0; } if( got==(DWORD)amt ){ return SQLITE_OK; }else{ return SQLITE_IOERR; }}/*** Write data from a buffer into a file. Return SQLITE_OK on success** or some other error code on failure.*/int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ int rc = 0; DWORD wrote; assert( id->isOpen ); SimulateIOError(SQLITE_IOERR); SimulateDiskfullError; TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); assert( amt>0 ); while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } if( !rc || amt>(int)wrote ){ return SQLITE_FULL; } return SQLITE_OK;}/*** Some microsoft compilers lack this definition.*/#ifndef INVALID_SET_FILE_POINTER
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -