From 37e3f33c7ec32432260b0ef750ac415763d6044f Mon Sep 17 00:00:00 2001 From: Patrick Lam Date: Wed, 8 Mar 2006 19:19:05 +0000 Subject: [PATCH] Sort directory entries while scanning them from disk; prevents Heisenbugs due to file ordering in a directory. reviewed by: plam --- ChangeLog | 8 ++++++++ src/fcdir.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a5e36e..b969083 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2006-03-08 Egmont Koblinger + 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 reviewed by: keithp diff --git a/src/fcdir.c b/src/fcdir.c index 974886d..ad64ca8 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -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); /* -- 2.39.2