Compare commits

...

8 Commits

Author SHA1 Message Date
mistachkin 12b0cd00c0 For Windows 8.x and higher, require the SQLITE_WIN32_WIN8_SECTOR_SIZE compile-time option in order to enable sector size determination.
FossilOrigin-Name: 47beb55c5bf3baa7a430c2f9bbd7ba9c19346d91
2017-01-18 23:12:27 +00:00
mistachkin 126bcef6be Improve and update comments.
FossilOrigin-Name: 2dc16d345bfb492b2ec69463b6130ff1b62fd291
2017-01-18 19:36:10 +00:00
mistachkin 235e27c0e3 Minimize the requested permissions when opening the volume on Windows 7 and Vista.
FossilOrigin-Name: 8d429a59cdad1693827b41369d642f9486c01155
2017-01-18 19:06:41 +00:00
mistachkin 518c505a94 Add runtime version checking for winSectorSize.
FossilOrigin-Name: cb9d1ab33d4109e0712d1a9dd2e51861e168e418
2017-01-18 01:11:03 +00:00
mistachkin 5f05aa24ac When determining sector sizes on Windows 7 and Vista, make sure the target file is on the same volume as corresponding root directory.
FossilOrigin-Name: de699ead5a8c5bcf074ef220365fe4a1e5310de4
2017-01-18 00:27:09 +00:00
mistachkin 838c32d3aa Merge updates from trunk.
FossilOrigin-Name: 8b42b8e31af03e82c091d4585d03f4edf49c0af9
2017-01-13 22:21:39 +00:00
mistachkin 1e5d9b6f8e Attempt to detect physical sector sizes on Windows Vista and higher.
FossilOrigin-Name: 6e388423c492c52aef221bd14f66482e0365d86d
2017-01-12 23:37:52 +00:00
mistachkin 8e37d48f4a Attempt to detect physical sector sizes on Windows 8 and higher.
FossilOrigin-Name: 381fd34b97ffe14f4bb784a9aae74477af699a08
2017-01-11 16:52:42 +00:00
3 changed files with 241 additions and 32 deletions
+7 -7
View File
@@ -1,5 +1,5 @@
C Fix\sa\sproblem\spreventing\sresumption\sof\sRBU\soperations\safter\srecovering\sfrom\sa\nprocess\sor\ssystem\sfailure\sthat\soccurs\sduring\sthe\sincremental-checkpoint\sphase.
D 2017-01-13T18:24:37.297
C For\sWindows\s8.x\sand\shigher,\srequire\sthe\sSQLITE_WIN32_WIN8_SECTOR_SIZE\scompile-time\soption\sin\sorder\sto\senable\ssector\ssize\sdetermination.
D 2017-01-18T23:12:27.503
F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
@@ -374,7 +374,7 @@ F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9
F src/os_win.c 54fd6ea6a9e609174004d6fcddddd2bdc4ac486a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 9dc72d23eebbdf992bd69f2ab954d0d3a27c7340
F src/pager.h d1e944291030351f362a0a7da9b5c3e34e603e39
@@ -1545,7 +1545,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 8c85b8fdd7f0ba65fba83361d361a567b797a184
R dc62936e86267740ae9736f88160b05f
U dan
Z f2366ce5ecd39574b5b5eb81b3b99a63
P 2dc16d345bfb492b2ec69463b6130ff1b62fd291
R 583653aaf51043f6394c35e95117e229
U mistachkin
Z f36279a74c520ca73c83f5f24da3d4a6
+1 -1
View File
@@ -1 +1 @@
97914266cb4ec63b0c9185ab139673139bd2f0ed
47beb55c5bf3baa7a430c2f9bbd7ba9c19346d91
+233 -24
View File
@@ -68,6 +68,14 @@
** Define the required Windows SDK version constants if they are not
** already available.
*/
#ifndef _WIN32_WINNT_VISTA
# define _WIN32_WINNT_VISTA 0x0600
#endif
#ifndef _WIN32_WINNT_WIN8
# define _WIN32_WINNT_WIN8 0x0602
#endif
#ifndef NTDDI_WIN8
# define NTDDI_WIN8 0x06020000
#endif
@@ -446,21 +454,31 @@ const sqlite3_mem_methods *sqlite3MemGetWin32(void);
#endif /* SQLITE_WIN32_MALLOC */
/*
** The following variable is (normally) set once and never changes
** thereafter. It records whether the operating system is Win9x
** or WinNT.
** The following variables are (normally) set once and never change
** thereafter. They record the major and minor OS version and whether
** the operating system type is Win9x or WinNT.
**
** 0: Operating system unknown.
** 1: Operating system is Win9x.
** 2: Operating system is WinNT.
** sqlite3_os_type = 0: Operating system type is unknown.
** sqlite3_os_type = 1: Operating system type is Win9x.
** sqlite3_os_type = 2: Operating system type is WinNT.
**
** In order to facilitate testing on a WinNT system, the test fixture
** For the major and minor versions, the following are the "well-known"
** operating system releases (i.e. the ones that are tested for):
**
** sqlite3_os_major.sqlite3_os_minor = 6.0 = Windows Vista
** sqlite3_os_major.sqlite3_os_minor = 6.2 = Windows 8
**
** In order to facilitate testing on WinNT systems, the test fixture
** can manually set this value to 1 to emulate Win98 behavior.
*/
#ifdef SQLITE_TEST
LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
LONG SQLITE_WIN32_VOLATILE sqlite3_os_major = 0;
LONG SQLITE_WIN32_VOLATILE sqlite3_os_minor = 0;
#else
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_major = 0;
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_minor = 0;
#endif
#ifndef SYSCALL
@@ -1010,7 +1028,8 @@ static struct win_syscall {
#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
#if SQLITE_OS_WINRT
#if SQLITE_OS_WINRT || (defined(SQLITE_WIN32_WIN8_SECTOR_SIZE) && \
defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN8)
{ "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
#else
{ "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
@@ -1134,6 +1153,39 @@ static struct win_syscall {
#define osFlushViewOfFile \
((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && defined(_WIN32_WINNT) && \
_WIN32_WINNT >= _WIN32_WINNT_VISTA
{ "DeviceIoControl", (SYSCALL)DeviceIoControl, 0 },
#else
{ "DeviceIoControl", (SYSCALL)0, 0 },
#endif
#define osDeviceIoControl ((BOOL(WINAPI*)( \
HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPVOID, \
LPOVERLAPPED))aSyscall[80].pCurrent)
#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && defined(_WIN32_WINNT) && \
_WIN32_WINNT >= _WIN32_WINNT_VISTA
{ "GetVolumeInformationByHandleW", (SYSCALL)GetVolumeInformationByHandleW, 0 },
#else
{ "GetVolumeInformationByHandleW", (SYSCALL)0, 0 },
#endif
#define osGetVolumeInformationByHandleW ((BOOL(WINAPI*)( \
HANDLE,LPWSTR,DWORD,LPDWORD,LPDWORD,LPDWORD,LPWSTR, \
DWORD))aSyscall[81].pCurrent)
#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && defined(_WIN32_WINNT) && \
_WIN32_WINNT >= _WIN32_WINNT_VISTA
{ "GetVolumeInformationW", (SYSCALL)GetVolumeInformationW, 0 },
#else
{ "GetVolumeInformationW", (SYSCALL)0, 0 },
#endif
#define osGetVolumeInformationW ((BOOL(WINAPI*)( \
LPCWSTR,LPWSTR,DWORD,LPDWORD,LPDWORD,LPDWORD,LPWSTR, \
DWORD))aSyscall[82].pCurrent)
}; /* End of the overrideable system calls */
/*
@@ -1403,6 +1455,63 @@ DWORD sqlite3Win32Wait(HANDLE hObject){
# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
#endif
/*
** This following version checking macros should evaluate to non-zero only
** when running on Windows Vista (or higher) or Windows 8 (or higher).
*/
#if !SQLITE_WIN32_GETVERSIONEX
# define osIsVistaPlus() (1)
# define osIsWin8Plus() (1)
#elif SQLITE_OS_WINCE
# define osIsVistaPlus() (0)
# define osIsWin8Plus() (0)
#elif SQLITE_OS_WINRT
# define osIsVistaPlus() (1)
# define osIsWin8Plus() (1)
#else
# define osIsVistaPlus() (winGetVersionEx() && ((sqlite3_os_major>6) || \
((sqlite3_os_major==6) && (sqlite3_os_minor>=0))))
# define osIsWin8Plus() (winGetVersionEx() && ((sqlite3_os_major>6) || \
((sqlite3_os_major==6) && (sqlite3_os_minor>=2))))
#endif
/*
** This function populates the Windows version information needed by this
** module. Use of the GetVersionExA or GetVersionExW function is required.
** The return value will be non-zero if version information was queried.
*/
#if SQLITE_WIN32_GETVERSIONEX
static int winGetVersionEx(){
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
#if defined(SQLITE_WIN32_HAS_ANSI)
OSVERSIONINFOA sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExA(&sInfo);
osInterlockedCompareExchange(&sqlite3_os_type,
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
osInterlockedCompareExchange(&sqlite3_os_major,
(LONG)sInfo.dwMajorVersion, 0);
osInterlockedCompareExchange(&sqlite3_os_minor,
(LONG)sInfo.dwMinorVersion, 0);
return 1;
#elif defined(SQLITE_WIN32_HAS_WIDE)
OSVERSIONINFOW sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExW(&sInfo);
osInterlockedCompareExchange(&sqlite3_os_type,
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
osInterlockedCompareExchange(&sqlite3_os_major,
(LONG)sInfo.dwMajorVersion, 0);
osInterlockedCompareExchange(&sqlite3_os_minor,
(LONG)sInfo.dwMinorVersion, 0);
return 1;
#endif
}
return 0;
}
#endif
/*
** This function determines if the machine is running a version of Windows
** based on the NT kernel.
@@ -1415,21 +1524,7 @@ int sqlite3_win32_is_nt(void){
*/
return 1;
#elif SQLITE_WIN32_GETVERSIONEX
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
#if defined(SQLITE_WIN32_HAS_ANSI)
OSVERSIONINFOA sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExA(&sInfo);
osInterlockedCompareExchange(&sqlite3_os_type,
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
#elif defined(SQLITE_WIN32_HAS_WIDE)
OSVERSIONINFOW sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExW(&sInfo);
osInterlockedCompareExchange(&sqlite3_os_type,
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
#endif
}
winGetVersionEx();
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
@@ -3538,6 +3633,46 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_NOTFOUND;
}
/*
** Same-volume determination for versions of Windows prior to Windows 8
** is untested, undocumented, and unsupported. All such code is omitted
** unless the SQLITE_WIN32_VISTA_SECTOR_SIZE define is set at compile-time,
** and that compile-time option is off by default and undocumented. The
** following code is for reference only.
*/
#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && \
defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
/*
** This function attempts to determine if the specified file resides on the
** same volume as the corresponding root directory. If not, the specified
** file may be impacted by a hard link, symbolic link, or reparse point (e.g.
** junction).
**
** This function may return false even when the file is on the same volume
** as the corresponding root directory. This function may return true only
** when there is no doubt that the specified file is on the same volume as
** the corresponding root directory associated with the volume.
*/
static BOOL winIsOnSameVolume(winFile *pFile){
WCHAR zRoot[] = L"_:\\\0"; /* underscore will be drive letter */
DWORD dwFileVolumeSerialNumber = 0;
DWORD dwRootVolumeSerialNumber = 0;
if ( !osGetVolumeInformationByHandleW(pFile->h, NULL, 0,
&dwFileVolumeSerialNumber, NULL,
NULL, NULL, 0) ){
return FALSE;
}
zRoot[0] = (WCHAR)pFile->zPath[0]; /* 'A' to 'Z' only, upper/lower case */
if( !osGetVolumeInformationW(zRoot, NULL, 0, &dwRootVolumeSerialNumber,
NULL, NULL, NULL, 0) ){
return FALSE;
}
return (dwFileVolumeSerialNumber == dwRootVolumeSerialNumber);
}
#endif
/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
@@ -3549,6 +3684,80 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
** same for both.
*/
static int winSectorSize(sqlite3_file *id){
#if defined(SQLITE_WIN32_WIN8_SECTOR_SIZE) && \
defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
if( osIsWin8Plus() ){
winFile *pFile = (winFile*)id;
FILE_STORAGE_INFO info;
memset(&info, 0, sizeof(FILE_STORAGE_INFO));
if( osGetFileInformationByHandleEx(pFile->h, FileStorageInfo,
&info, sizeof(info)) ){
ULONG size = info.FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
OSTRACE(("SECTOR file=%p, size=%lu\n", pFile->h, size));
if( size>0 && size<=2147483647 ){
return (int)size;
}
}else{
pFile->lastErrno = osGetLastError();
winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
"winSectorSize1", pFile->zPath);
}
}
#endif
/*
** Sector-size determination for versions of Windows prior to Windows 8
** is untested, undocumented, and unsupported. All such code is omitted
** unless the SQLITE_WIN32_VISTA_SECTOR_SIZE define is set at compile-time,
** and that compile-time option is off by default and undocumented. The
** following code is for reference only.
*/
#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && \
defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
if( osIsVistaPlus() ){
winFile *pFile = (winFile*)id;
if( winIsDriveLetterAndColon(pFile->zPath) && winIsOnSameVolume(pFile) ){
WCHAR zDisk[] = L"\\\\.\\_:\0"; /* underscore will be drive letter */
HANDLE hDisk;
zDisk[4] = (WCHAR)pFile->zPath[0]; /* 'A' to 'Z' only, upper/lower case */
assert( (zDisk[4]>=L'A' && zDisk[4]<=L'Z')
|| (zDisk[4]>=L'a' && zDisk[4]<=L'z')
);
hDisk = osCreateFileW(zDisk, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if( hDisk!=NULL ){
STORAGE_PROPERTY_QUERY query;
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignment;
DWORD bytes = 0;
memset(&query, 0, sizeof(STORAGE_PROPERTY_QUERY));
memset(&alignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));
query.QueryType = PropertyStandardQuery;
query.PropertyId = StorageAccessAlignmentProperty;
if( osDeviceIoControl(hDisk, IOCTL_STORAGE_QUERY_PROPERTY, &query,
sizeof(STORAGE_PROPERTY_QUERY), &alignment,
sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
&bytes, NULL) ){
DWORD size = alignment.BytesPerPhysicalSector;
OSTRACE(("SECTOR file=%p, size=%lu\n", pFile->h, size));
if( size>0 && size<=2147483647 ){
return (int)size;
}
}else{
pFile->lastErrno = osGetLastError();
winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
"winSectorSize2", pFile->zPath);
}
osCloseHandle(hDisk);
}else{
pFile->lastErrno = osGetLastError();
winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
"winSectorSize3", pFile->zPath);
}
}
}
#endif
(void)id;
return SQLITE_DEFAULT_SECTOR_SIZE;
}
@@ -5923,7 +6132,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
assert( ArraySize(aSyscall)==80 );
assert( ArraySize(aSyscall)==83 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));