[Fontconfig] stat()-related Win32 patch to fontconfig

Tor Lillqvist tml at iki.fi
Wed Sep 20 01:14:58 PDT 2006


I first sent this by mistake directly to Keith, which I guess was not
the right thing to do; sending to the list now instead in the hope of
some discussion...

This patch should fix a couple of longstanding problems with
fontconfig on Windows that manifest themselves especially in GIMP. The
root cause to the problems is in Microsoft's incredibly stupid stat()
implementation. Basically, stat() returns wrong timestamp fields for
files on NTFS filesystems on machines that use automatic DST
switching.

See for instance http://bugzilla.gnome.org/show_bug.cgi?id=154968 and
http://www.codeproject.com/datetime/dstbugs.asp

This patch is against 2.3.2, I haven't looked at the current code.

--tml

--- /tmp/fontconfig-2.3.2/src/fccache.c	Tue Jan  4 23:53:36 2005
+++ src/fccache.c	Fri Aug 25 05:27:06 2006
@@ -43,0 +44,58 @@
+#ifdef _WIN32
+
+#include <windows.h>
+
+#ifdef __GNUC__
+typedef long long INT64;
+#define EPOCH_OFFSET 11644473600ll
+#else
+#define EPOCH_OFFSET 11644473600i64
+typedef __int64 INT64;
+#endif
+
+/* Workaround for problems in the stat() in the Microsoft C library:
+ *
+ * 1) stat() uses FindFirstFile() to get the file or directory
+ * attributes. Unfortunately this API doesn't return correct values
+ * for modification time of a directory until some time after a file
+ * or subdirectory has been added to the directory. (This causes
+ * run-test.sh to fail, for instance.) GetFileAttributesEx() is
+ * better, it returns the updated timestamp right away.
+ *
+ * 2) stat() does some very strange crap related to backward
+ * compatibility with the local time timestamps on FAT volumes and
+ * daylight saving time. This causes problems after the switches
+ * to/from daylight saving time. See
+ * http://bugzilla.gnome.org/show_bug.cgi?id=154968 , especially
+ * comment #30, and http://www.codeproject.com/datetime/dstbugs.asp .
+ * We don't need any of that crap, just use the UTC timestamps
+ * from NTFS, converted to the Unix epoch.
+ */
+
+static int
+FcStat (const FcChar8 *file, struct stat *statb)
+{
+  WIN32_FILE_ATTRIBUTE_DATA wfad;
+
+  if (!GetFileAttributesEx (file, GetFileExInfoStandard, &wfad))
+    return -1;
+
+  statb->st_mtime = (*(INT64 *)&wfad.ftLastWriteTime)/10000000 - EPOCH_OFFSET;
+  
+  if (wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+    statb->st_mode = _S_IFDIR;
+  else
+    statb->st_mode = _S_IFREG;
+
+  /* Don't bother with other mode bits or other fields, they aren't
+   * looked at by the code in this file.
+   */
+  return 0;
+}
+
+#else
+
+#define FcStat stat
+
+#endif
+
@@ -342 +400 @@ FcGlobalCacheCheckTime (const FcChar8 *f
-    if (stat ((char *) file, &statb) < 0)
+    if (FcStat ((char *) file, &statb) < 0)
@@ -836 +894 @@ FcGlobalCacheUpdate (FcGlobalCache  *cac
-    if (stat ((char *) file, &statb) < 0)
+    if (FcStat ((char *) file, &statb) < 0)
@@ -965 +1023 @@ FcDirCacheValid (const FcChar8 *dir)
-    if (stat ((char *) dir, &dir_stat) < 0)
+    if (FcStat ((char *) dir, &dir_stat) < 0)
@@ -970 +1028 @@ FcDirCacheValid (const FcChar8 *dir)
-    if (stat ((char *) cache_file, &file_stat) < 0)
+    if (FcStat ((char *) cache_file, &file_stat) < 0)





More information about the Fontconfig mailing list