]> git.wh0rd.org Git - fontconfig.git/commitdiff
Sort directory entries while scanning them from disk; prevents Heisenbugs
authorPatrick Lam <plam@MIT.EDU>
Wed, 8 Mar 2006 19:19:05 +0000 (19:19 +0000)
committerPatrick Lam <plam@MIT.EDU>
Wed, 8 Mar 2006 19:19:05 +0000 (19:19 +0000)
    due to file ordering in a directory.
reviewed by: plam

ChangeLog
src/fcdir.c

index 2a5e36e6d6b414ae21d775907ed8a48c41dd5e7d..b969083f9714f3e264d9289595937b4e361e5f95 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-08  Egmont Koblinger  <egmont@uhulinux.hu>
+       reviewed by: plam
+
+       * src/fcdir.c (FcDirScanConfig):
+
+       Sort directory entries while scanning them from disk;
+       prevents Heisenbugs due to file ordering in a directory.
+
 2005-12-13  Carl Worth  <cworth@cworth.org>
        reviewed by: keithp
 
index 974886d362c0ab19e4561e70056d6c12d27da46b..ad64ca83c21b896d07bc538348c6ae03d93147d4 100644 (file)
@@ -168,6 +168,16 @@ FcFileScan (FcFontSet          *set,
     return FcFileScanConfig (set, dirs, cache, blanks, file, force, 0);
 }
 
+/*
+ * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
+ */
+
+static int
+cmpstringp(const void *p1, const void *p2)
+{
+    return strcmp(* (char **) p1, * (char **) p2);
+}
+
 /*
  * Scan 'dir', adding font files to 'set' and
  * subdirectories to 'dirs'
@@ -184,9 +194,12 @@ FcDirScanConfig (FcFontSet *set,
 {
     DIR                        *d;
     struct dirent      *e;
+    FcChar8            **dirlist;
+    int                        dirlistlen, dirlistalloc;
     FcChar8            *file;
     FcChar8            *base;
     FcBool             ret = FcTrue;
+    int                        i;
 
     if (config && !FcConfigAcceptFilename (config, dir))
        return FcTrue;
@@ -232,14 +245,40 @@ FcDirScanConfig (FcFontSet        *set,
            return FcTrue;
        return FcFalse;
     }
-    while (ret && (e = readdir (d)))
+    dirlistlen = 0;
+    dirlistalloc = 8;
+    dirlist = malloc(dirlistalloc * sizeof(FcChar8 *));
+    if (!dirlist)
+       return FcFalse;
+    while ((e = readdir (d)))
     {
        if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
        {
-           strcpy ((char *) base, (char *) e->d_name);
-           ret = FcFileScanConfig (set, dirs, cache, blanks, file, force, config);
+           if (dirlistlen == dirlistalloc)
+           {
+               dirlistalloc *= 2;
+               dirlist = realloc(dirlist, dirlistalloc * sizeof(FcChar8 *));
+               if (!dirlist)
+                   return FcFalse;
+           }
+           dirlist[dirlistlen] = malloc(strlen (e->d_name) + 1);
+           if (!dirlist[dirlistlen])
+               return FcFalse;
+           strcpy(dirlist[dirlistlen], e->d_name);
+           dirlistlen++;
        }
     }
+    qsort(dirlist, dirlistlen, sizeof(FcChar8 *), cmpstringp);
+    i = 0;
+    while (ret && i < dirlistlen)
+    {
+       strcpy ((char *) base, (char *) dirlist[i]);
+       ret = FcFileScanConfig (set, dirs, cache, blanks, file, force, config);
+       i++;
+    }
+    for (i = 0; i < dirlistlen; i++)
+       free(dirlist[i]);
+    free (dirlist);
     free (file);
     closedir (d);
     /*