]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Win32 portability fixes to the 'fileio' extension.
authormistachkin <mistachkin@noemail.net>
Fri, 16 Mar 2018 23:54:36 +0000 (23:54 +0000)
committermistachkin <mistachkin@noemail.net>
Fri, 16 Mar 2018 23:54:36 +0000 (23:54 +0000)
FossilOrigin-Name: 9d2b0f8b84aac862b0572b183e3ba53ea8c0d8742aaa3c3fbe59f6036054fd1a

ext/misc/fileio.c
manifest
manifest.uuid

index 83ba1243754d410b5f42134e669bf1ed99b42f5b..8122b232c35df96acbc79f047989e3209a21d443 100644 (file)
@@ -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;
   }
index 5acce9883053a1adcc327faf0f7dc5516adf9cb7..8e59ceab23f298241aef6e23bc5679b1263fb228 100644 (file)
--- 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
index f884950f1ba511dac77315f8bfe300b069650516..c867b8f217faf993d6752e7d707d80b7e4bfa2f7 100644 (file)
@@ -1 +1 @@
-49d2566c8e7d0df37494ee001fc6eae5f47f95e16f6a575f2d8d6777b62e6068
\ No newline at end of file
+9d2b0f8b84aac862b0572b183e3ba53ea8c0d8742aaa3c3fbe59f6036054fd1a
\ No newline at end of file