diff options
author | Patrick Lam <plam@MIT.EDU> | 2006-03-08 19:19:05 +0000 |
---|---|---|
committer | Patrick Lam <plam@MIT.EDU> | 2006-03-08 19:19:05 +0000 |
commit | 37e3f33c7ec32432260b0ef750ac415763d6044f (patch) | |
tree | 59bf1ba1b6dc7e02a173adff190716444bf705af | |
parent | a7683cafe10925d09855f927cb7602a90e10516f (diff) | |
download | fontconfig-37e3f33c7ec32432260b0ef750ac415763d6044f.tar.gz |
Sort directory entries while scanning them from disk; prevents Heisenbugs
due to file ordering in a directory.
reviewed by: plam
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | src/fcdir.c | 45 |
2 files changed, 50 insertions, 3 deletions
@@ -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 diff --git a/src/fcdir.c b/src/fcdir.c index 974886d..ad64ca8 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -169,6 +169,16 @@ FcFileScan (FcFontSet *set, } /* + * 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); /* |