From: mistachkin Date: Fri, 16 Mar 2018 23:54:36 +0000 (+0000) Subject: Win32 portability fixes to the 'fileio' extension. X-Git-Tag: version-3.23.0~45^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42a0dbfe920a77a907ad12bc30b465938ed7e6b1;p=thirdparty%2Fsqlite.git Win32 portability fixes to the 'fileio' extension. FossilOrigin-Name: 9d2b0f8b84aac862b0572b183e3ba53ea8c0d8742aaa3c3fbe59f6036054fd1a --- diff --git a/ext/misc/fileio.c b/ext/misc/fileio.c index 83ba124375..8122b232c3 100644 --- a/ext/misc/fileio.c +++ b/ext/misc/fileio.c @@ -159,6 +159,97 @@ static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){ va_end(ap); } +#if defined(_WIN32) +/* +** This function is designed to convert a Win32 FILETIME structure into the +** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC). +*/ +static sqlite3_uint64 fileTimeToUnixTime( + LPFILETIME pFileTime +){ + SYSTEMTIME epochSystemTime; + ULARGE_INTEGER epochIntervals; + FILETIME epochFileTime; + ULARGE_INTEGER fileIntervals; + + memset(&epochSystemTime, 0, sizeof(SYSTEMTIME)); + epochSystemTime.wYear = 1970; + epochSystemTime.wMonth = 1; + epochSystemTime.wDay = 1; + SystemTimeToFileTime(&epochSystemTime, &epochFileTime); + epochIntervals.LowPart = epochFileTime.dwLowDateTime; + epochIntervals.HighPart = epochFileTime.dwHighDateTime; + + fileIntervals.LowPart = pFileTime->dwLowDateTime; + fileIntervals.HighPart = pFileTime->dwHighDateTime; + + return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000; +} + +/* +** This function attempts to normalize the time values found in the stat() +** buffer to UTC. This is necessary on Win32, where the runtime library +** appears to return these values as local times. +*/ +static void statTimesToUtc( + const char *zPath, + struct stat *pStatBuf +){ + HANDLE hFindFile; + WIN32_FIND_DATAW fd; + LPWSTR zUnicodeName; + extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*); + zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath); + if( zUnicodeName ){ + memset(&fd, 0, sizeof(WIN32_FIND_DATA)); + hFindFile = FindFirstFileW(zUnicodeName, &fd); + if( hFindFile!=NULL ){ + pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime); + pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime); + pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime); + FindClose(hFindFile); + } + sqlite3_free(zUnicodeName); + } +} +#endif + +/* +** This function is used in place of stat(). On Windows, special handling +** is required in order for the included time to be returned as UTC. On all +** other systems, this function simply calls stat(). +*/ +static int fileStat( + const char *zPath, + struct stat *pStatBuf +){ +#if defined(_WIN32) + int rc = stat(zPath, pStatBuf); + if( rc==0 ) statTimesToUtc(zPath, pStatBuf); + return rc; +#else + return stat(zPath, pStatBuf); +#endif +} + +/* +** This function is used in place of lstat(). On Windows, special handling +** is required in order for the included time to be returned as UTC. On all +** other systems, this function simply calls lstat(). +*/ +static int fileLinkStat( + const char *zPath, + struct stat *pStatBuf +){ +#if defined(_WIN32) + int rc = lstat(zPath, pStatBuf); + if( rc==0 ) statTimesToUtc(zPath, pStatBuf); + return rc; +#else + return lstat(zPath, pStatBuf); +#endif +} + /* ** Argument zFile is the name of a file that will be created and/or written ** by SQL function writefile(). This function ensures that the directory @@ -190,7 +281,7 @@ static int makeDirectory( if( i==nCopy ) break; zCopy[i] = '\0'; - rc2 = stat(zCopy, &sStat); + rc2 = fileStat(zCopy, &sStat); if( rc2!=0 ){ if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR; }else{ @@ -232,7 +323,7 @@ static int writeFile( ** to do so using chmod(), it is not an error. */ struct stat sStat; if( errno!=EEXIST - || 0!=stat(zFile, &sStat) + || 0!=fileStat(zFile, &sStat) || !S_ISDIR(sStat.st_mode) || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777)) ){ @@ -279,6 +370,9 @@ static int writeFile( lastWrite.dwLowDateTime = (DWORD)intervals; lastWrite.dwHighDateTime = intervals >> 32; zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile); + if( zUnicodeName==0 ){ + return 1; + } hFile = CreateFileW( zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL @@ -291,7 +385,7 @@ static int writeFile( }else{ return 1; } -#elif defined(AT_FDCWD) && 0 /* utimensat() is not univerally available */ +#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */ /* Recent unix */ struct timespec times[2]; times[0].tv_nsec = times[1].tv_nsec = 0; @@ -568,7 +662,7 @@ static int fsdirNext(sqlite3_vtab_cursor *cur){ sqlite3_free(pCur->zPath); pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name); if( pCur->zPath==0 ) return SQLITE_NOMEM; - if( lstat(pCur->zPath, &pCur->sStat) ){ + if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); return SQLITE_ERROR; } @@ -702,7 +796,7 @@ static int fsdirFilter( if( pCur->zPath==0 ){ return SQLITE_NOMEM; } - if( lstat(pCur->zPath, &pCur->sStat) ){ + if( fileLinkStat(pCur->zPath, &pCur->sStat) ){ fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath); return SQLITE_ERROR; } diff --git a/manifest b/manifest index 5acce98830..8e59ceab23 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\smore\s'zipfile'\stests\son\sWin32. -D 2018-03-16T23:54:26.457 +C Win32\sportability\sfixes\sto\sthe\s'fileio'\sextension. +D 2018-03-16T23:54:36.667 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3 @@ -277,7 +277,7 @@ F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f0 F ext/misc/csv.c 1a009b93650732e22334edc92459c4630b9fa703397cbb3c8ca279921a36ca11 F ext/misc/dbdump.c 22018e00eb50e9ebf9067c92d4e7162dc5006a3efc4e0c19bc3829825a1043b0 F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 -F ext/misc/fileio.c 673d6bde25cab00ad40cc95b89fa99c9f00870c565de3beaab9d6a9658bbc3e0 +F ext/misc/fileio.c da441efc13c0fa96a41b168bb8aa1014b12d36f3a0d619a2b77b3bdf2a3ccf5e F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984 @@ -1712,7 +1712,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 bc2af8e0aa28d8d10612ab9464c008a970348b4720bb34d0c546d341e2bc09e0 -R 7a8f6991afcb70824bbbe5f92582fa58 +P 49d2566c8e7d0df37494ee001fc6eae5f47f95e16f6a575f2d8d6777b62e6068 +R 2df366b18e22b23cff08d7e7d1c0c31e U mistachkin -Z 9baa572ff0bb0d7155a0ba438dc60407 +Z 0697d74ec8216cbe655401008c52a666 diff --git a/manifest.uuid b/manifest.uuid index f884950f1b..c867b8f217 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -49d2566c8e7d0df37494ee001fc6eae5f47f95e16f6a575f2d8d6777b62e6068 \ No newline at end of file +9d2b0f8b84aac862b0572b183e3ba53ea8c0d8742aaa3c3fbe59f6036054fd1a \ No newline at end of file