Hi, > I'll try to do it tomorrow. Sorry, I am a bit late due to technical issues. I attach the patch that sorts directory entries before scanning them. I send two versions, for 2.3.2 and for 2.3.94. The older one is easier to test since fonts.cache-1 is more human-readable. Scandir() would have been an easier choice but that is not really portable according to its manpage. So I rather chose to manually store the results of readdir() and sort them using qsort. They are stored in a "char**" called dirlist where this array is first initialized to contain 8 "char*"s (this number is quite arbitrary) and doubled each time this limit is exceeded. dirlistalloc is the allocated size of this array, dirlistlen is the number of elements already in use. Of course I tested the patch and it seems to be okay, however that doesn't guarantee for sure that it is perfect, so please verify it. The only bug I see is that if a malloc fails and hence the function bails out, then the result of some earlier malloc's may remain unfreed. I hope it's acceptable since the whole utility will soon exit then. thx, Egmont
diff -Naur fontconfig-2.3.2.orig/src/fcdir.c fontconfig-2.3.2/src/fcdir.c --- fontconfig-2.3.2.orig/src/fcdir.c 2005-02-10 21:20:02.000000000 +0100 +++ fontconfig-2.3.2/src/fcdir.c 2006-03-07 16:41:05.000000000 +0100 @@ -169,6 +169,16 @@ } /* + * 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 @@ { 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 @@ 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); /*
diff -Naur fontconfig-2.3.94.orig/src/fcdir.c fontconfig-2.3.94/src/fcdir.c --- fontconfig-2.3.94.orig/src/fcdir.c 2006-02-21 16:45:51.000000000 +0100 +++ fontconfig-2.3.94/src/fcdir.c 2006-03-07 16:29:30.000000000 +0100 @@ -101,6 +101,16 @@ } /* + * 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' */ @@ -116,6 +126,8 @@ { DIR *d; struct dirent *e; + FcChar8 **dirlist; + int dirlistlen, dirlistalloc; FcChar8 *file; const FcChar8 *d_can = 0; FcChar8 *base; @@ -174,14 +186,40 @@ 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 (tmpSet, 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 (tmpSet, dirs, cache, blanks, file, force, config); + i++; + } + for (i = 0; i < dirlistlen; i++) + free(dirlist[i]); + free (dirlist); free (file); closedir (d); /*
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/fontconfig