Sort directory entries while scanning them from disk; prevents Heisenbugs

due to file ordering in a directory.
reviewed by: plam
This commit is contained in:
Patrick Lam 2006-03-08 19:19:05 +00:00
parent a7683cafe1
commit 37e3f33c7e
2 changed files with 50 additions and 3 deletions

View File

@ -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

View 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);
/*