Bug#539338: mkfontscale: add option to recurse subdirectories
Hi, thanks, Julien, for the comments, and sorry about the half-baked patch... Julien Cristau wrote: + && (stat(filename, &statbuf) == 0) && S_ISDIR(statbuf.st_mode)) { this can lead to an infinite loop since you follow symlinks. Juliusz suggested limiting the recursion to something like 100. Indeed. There would be an implicit upper bound of 2048 by the dsprintf implementation, but that's one more reason to check the return value and probably not good to rely on. Please find attached a revised patch. The fixes to the manpage are mainly for reminding myself and I can split out the unrelated parts for cleaner commits. Kind regards T. -- Thomas Viehmann, http://thomas.viehmann.net/ diff -Nru xfonts-utils-7.4+1/mkfontscale/mkfontscale.c xfonts-utils-7.4+1/mkfontscale/mkfontscale.c --- xfonts-utils-7.4+1/mkfontscale/mkfontscale.c 2008-05-11 00:01:42.0 +0200 +++ xfonts-utils-7.4+1/mkfontscale/mkfontscale.c 2009-08-01 23:34:02.0 +0200 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,8 @@ #define MAXFONTNAMELEN 1024 #endif +#define MAXDEPTHINRECURSIVESCAN 100 + char *encodings_array[] = { "ascii-0", "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5", @@ -103,6 +106,7 @@ static FT_Library ft_library; static float bigEncodingFuzz = 0.02; +static int recurse; static int relative; static int doScalable; static int doBitmaps; @@ -118,8 +122,8 @@ { fprintf(stderr, "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n" -"[ -a encoding ] [ -f fuzz ] [ -l ] " -"[ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n" +"[ -a encoding ] [ -f fuzz ] [ -l ]\n" +"[ -e directory ] [ -p prefix ] [ -n ] [ -r ] [ -R ] \n" "[-u] [-U] [ directory ]...\n"); } @@ -154,6 +158,7 @@ doScalable = 1; onlyEncodings = 0; relative = 0; +recurse = 0; reencodeLegacy = 1; encodingsToDo = NULL; @@ -217,6 +222,9 @@ } else if(strcmp(argv[argn], "-r") == 0) { relative = 1; argn++; +} else if(strcmp(argv[argn], "-R") == 0) { +recurse = 1; +argn++; } else if(strcmp(argv[argn], "-l") == 0) { reencodeLegacy = !reencodeLegacy; argn++; @@ -749,57 +757,20 @@ return 0; } + static int -doDirectory(char *dirname_given, int numEncodings, ListPtr encodingsToDo) +scanDirectory(char *dirname, char *dir_prefix, int xl, HashTablePtr entries, int depthtogo) { -char *dirname, *fontscale_name, *filename, *encdir; -FILE *fontscale, *encfile; DIR *dirp; struct dirent *entry; +struct stat statbuf; +ListPtr encoding, xlfd, lp; +char* filename; +char* prefixedname; +int rc, found; +int isBitmap=0; FT_Error ftrc; FT_Face face; -ListPtr encoding, xlfd, lp; -HashTablePtr entries; -HashBucketPtr *array; -int i, n, found, rc; -int isBitmap=0,xl=0; - -if (exclusionSuffix) -xl = strlen (exclusionSuffix); - -i = strlen(dirname_given); -if(i == 0) -dirname = dsprintf("./"); -else if(dirname_given[i - 1] != '/') -dirname = dsprintf("%s/", dirname_given); -else -dirname = dsprintf("%s", dirname_given); - -if(dirname == NULL) { -perror("dirname"); -exit(1); -} - -if (onlyEncodings) - goto encodings; - -entries = makeHashTable(); -if(doBitmaps && !doScalable) { -readFontScale(entries, dirname); -} - -if(strcmp(outfilename, "-") == 0) -fontscale_name = NULL; -else { -if(outfilename[0] == '/') -fontscale_name = dsprintf("%s", outfilename); -else -fontscale_name = dsprintf("%s%s", dirname, outfilename); -if(fontscale_name == NULL) { -perror("fontscale_name"); -exit(1); -} -} dirp = opendir(dirname); if(dirp == NULL) { @@ -808,17 +779,6 @@ return 0; } -if(fontscale_name == NULL) -fontscale = stdout; -else -fontscale = fopen(fontscale_name, "wb"); - -if(fontscale == NULL) { -fprintf(stderr, "%s: ", fontscale_name); -perror("fopen(w)"); -return 0; -} - while((entry = readdir(dirp)) != NULL) { int have_face = 0; char *xlfd_name = NULL; @@ -831,7 +791,33 @@ } filename = dsprintf("%s%s", dirname, entry->d_name); - +if (recurse && depthtogo>0 && strcmp(entry->d_name, ".") != 0 + && strcmp(entry->d_name, "..") != 0 + && stat(filename, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { + char* prefix; + int retval; + free(filename); + filename = dsprintf("%s%s/", dirname, entry->d_name); + prefix = dsprintf("%s%s/", dir_prefix, entry->d_name); + if (filename == NULL || p
Bug#539338: mkfontscale: add option to recurse subdirectories
Hi Thomas, a couple comments on the patch. On Thu, Jul 30, 2009 at 21:00:05 +0200, Thomas Viehmann wrote: > @@ -831,7 +789,24 @@ > } > > filename = dsprintf("%s%s", dirname, entry->d_name); > +if (recurse & (strcmp(entry->d_name, ".") != 0) && > (strcmp(entry->d_name, "..") != 0) ^^ should be && > + && (stat(filename, &statbuf) == 0) && S_ISDIR(statbuf.st_mode)) { this can lead to an infinite loop since you follow symlinks. Juliusz suggested limiting the recursion to something like 100. > + char* prefix; > + int retval; > + free(filename); > + filename = dsprintf("%s%s/", dirname, entry->d_name); > + prefix = dsprintf("%s%s/", dir_prefix, entry->d_name); probably need to check the return value of dsprintf here. Cheers, Julien -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Bug#539338: mkfontscale: add option to recurse subdirectories
X-Debbugs-CC: Juliusz Chroboczek Package: xfonts-utils Version: 1:7.4+1 Severity: wishlist Hi Juliusz, everyone, in the medium run it might be nice to use /usr/share/fonts/truetype in the X font path. However, fonts seem to be organized into subdirectories. To facilitate using the directory with adding only one element to the X font path, the attached patch implements recursive scanning of subdirectories in mkfontscale. I appreciate feedback and if you could consider adopting it. Acknowledgement: Julien Cristau answered questions on IRC, so if I have gotten anything right here, it's to his credit, all errors are my own. Kind regards and thanks for your work on Debian and X T. P.S.: If this patch seems feasible (even if only in Debian), I would submit a follow-up to add a packaging system trigger to keep font information up to date in that directory. -- Thomas Viehmann, http://thomas.viehmann.net/ diff -dur orig/xfonts-utils-7.4+1/mkfontscale/mkfontscale.c xfonts-utils-7.4+1/mkfontscale/mkfontscale.c --- orig/xfonts-utils-7.4+1/mkfontscale/mkfontscale.c 2008-05-11 00:01:42.0 +0200 +++ xfonts-utils-7.4+1/mkfontscale/mkfontscale.c 2009-07-30 20:49:23.0 +0200 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,7 @@ static FT_Library ft_library; static float bigEncodingFuzz = 0.02; +static int recurse; static int relative; static int doScalable; static int doBitmaps; @@ -154,6 +156,7 @@ doScalable = 1; onlyEncodings = 0; relative = 0; +recurse = 0; reencodeLegacy = 1; encodingsToDo = NULL; @@ -217,6 +220,9 @@ } else if(strcmp(argv[argn], "-r") == 0) { relative = 1; argn++; +} else if(strcmp(argv[argn], "-R") == 0) { +recurse = 1; +argn++; } else if(strcmp(argv[argn], "-l") == 0) { reencodeLegacy = !reencodeLegacy; argn++; @@ -749,57 +755,20 @@ return 0; } + static int -doDirectory(char *dirname_given, int numEncodings, ListPtr encodingsToDo) +scanDirectory(char *dirname, char *dir_prefix, int xl, HashTablePtr entries) { -char *dirname, *fontscale_name, *filename, *encdir; -FILE *fontscale, *encfile; DIR *dirp; struct dirent *entry; +struct stat statbuf; +ListPtr encoding, xlfd, lp; +char* filename; +char* prefixedname; +int rc, found; +int isBitmap=0; FT_Error ftrc; FT_Face face; -ListPtr encoding, xlfd, lp; -HashTablePtr entries; -HashBucketPtr *array; -int i, n, found, rc; -int isBitmap=0,xl=0; - -if (exclusionSuffix) -xl = strlen (exclusionSuffix); - -i = strlen(dirname_given); -if(i == 0) -dirname = dsprintf("./"); -else if(dirname_given[i - 1] != '/') -dirname = dsprintf("%s/", dirname_given); -else -dirname = dsprintf("%s", dirname_given); - -if(dirname == NULL) { -perror("dirname"); -exit(1); -} - -if (onlyEncodings) - goto encodings; - -entries = makeHashTable(); -if(doBitmaps && !doScalable) { -readFontScale(entries, dirname); -} - -if(strcmp(outfilename, "-") == 0) -fontscale_name = NULL; -else { -if(outfilename[0] == '/') -fontscale_name = dsprintf("%s", outfilename); -else -fontscale_name = dsprintf("%s%s", dirname, outfilename); -if(fontscale_name == NULL) { -perror("fontscale_name"); -exit(1); -} -} dirp = opendir(dirname); if(dirp == NULL) { @@ -808,17 +777,6 @@ return 0; } -if(fontscale_name == NULL) -fontscale = stdout; -else -fontscale = fopen(fontscale_name, "wb"); - -if(fontscale == NULL) { -fprintf(stderr, "%s: ", fontscale_name); -perror("fopen(w)"); -return 0; -} - while((entry = readdir(dirp)) != NULL) { int have_face = 0; char *xlfd_name = NULL; @@ -831,7 +789,24 @@ } filename = dsprintf("%s%s", dirname, entry->d_name); +if (recurse & (strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0) + && (stat(filename, &statbuf) == 0) && S_ISDIR(statbuf.st_mode)) { + char* prefix; + int retval; + free(filename); + filename = dsprintf("%s%s/", dirname, entry->d_name); + prefix = dsprintf("%s%s/", dir_prefix, entry->d_name); + retval = scanDirectory(filename, prefix, xl, entries); + free(filename); + free(prefix); + if (retval == 0) { + closedir(dirp); + return 0; + } + continue; + } +prefixedname = dsprintf("%s%s", dir_prefix, entry->d_name); if(doBitmaps) rc = bitmapIdentify(filename, &xlfd_name); else @@ -892,7 +867,7 @@ xlfd = listCons(s, xlfd); } else { /* Not a reencodable font -- skip all the r