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.000000000 +0200
+++ xfonts-utils-7.4+1/mkfontscale/mkfontscale.c 2009-08-01 23:34:02.000000000 +0200
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
+#include <sys/stat.h>
#include <X11/Xos.h>
#include <X11/fonts/fontenc.h>
@@ -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 || prefix == NULL) {
+ perror("error allocating string (maximal length exeeded?)");
+ return 0;
+ }
+ retval = scanDirectory(filename, prefix, xl, entries, depthtogo-1);
+ free(filename);
+ free(prefix);
+ if (retval == 0) {
+ closedir(dirp);
+ return 0;
+ }
+ continue;
+ }
+
+ prefixedname = dsprintf("%s%s", dir_prefix, entry->d_name);
+ if (prefixedname == NULL) {
+ perror("error allocating string (maximal length exeeded?)");
+ return 0;
+ }
if(doBitmaps)
rc = bitmapIdentify(filename, &xlfd_name);
else
@@ -892,7 +878,7 @@
xlfd = listCons(s, xlfd);
} else {
/* Not a reencodable font -- skip all the rest of the loop body */
- putHash(entries, xlfd_name, entry->d_name, filePrio(entry->d_name));
+ putHash(entries, xlfd_name, prefixedname, filePrio(entry->d_name));
goto done;
}
}
@@ -926,7 +912,7 @@
found = 1;
snprintf(buf, MAXFONTNAMELEN, "%s-%s",
lp->value, encoding->value);
- putHash(entries, buf, entry->d_name, filePrio(entry->d_name));
+ putHash(entries, buf, prefixedname, filePrio(entry->d_name));
}
}
for(encoding = extra_encodings; encoding;
@@ -935,7 +921,7 @@
/* Do not set found! */
snprintf(buf, MAXFONTNAMELEN, "%s-%s",
lp->value, encoding->value);
- putHash(entries, buf, entry->d_name, filePrio(entry->d_name));
+ putHash(entries, buf, prefixedname, filePrio(entry->d_name));
}
}
}
@@ -946,10 +932,76 @@
}
deepDestroyList(xlfd);
xlfd = NULL;
+ free(prefixedname);
free(filename);
}
closedir(dirp);
+ return 1;
+}
+
+
+static int
+doDirectory(char *dirname_given, int numEncodings, ListPtr encodingsToDo)
+{
+ char *dirname, *fontscale_name, *encdir;
+ FILE *fontscale, *encfile;
+ HashTablePtr entries;
+ HashBucketPtr *array;
+ ListPtr lp;
+ int i, n;
+ int 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 (scanDirectory(dirname, "", xl, entries, MAXDEPTHINRECURSIVESCAN) == 0)
+ return 0;
+
+ 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);
+ }
+ }
+
+ 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;
+ }
+
n = hashElements(entries);
fprintf(fontscale, "%d\n", n);
array = hashArray(entries, 1);
diff -Nru xfonts-utils-7.4+1/mkfontscale/mkfontscale.man xfonts-utils-7.4+1/mkfontscale/mkfontscale.man
--- xfonts-utils-7.4+1/mkfontscale/mkfontscale.man 2008-04-28 21:23:47.000000000 +0200
+++ xfonts-utils-7.4+1/mkfontscale/mkfontscale.man 2009-08-01 23:41:55.000000000 +0200
@@ -31,10 +31,10 @@
.I prefix
] [
.B \-r
-.I prefix
+] [
+.B \-R
] [
.B \-n
-.I prefix
] [
.B \-\-
] [
@@ -107,7 +107,7 @@
directory is scanned for encoding files, the list of which is then
written to an "encodings.dir" file in every font directory.
.TP
-.B -p
+.BI \-p " prefix"
Specifies a prefix that is prepended to the encoding file path names
when they are written to the "encodings.dir" file. The prefix is
prepended litterally: if a `/' is required between the prefix and the path
@@ -122,6 +122,10 @@
.B \-e
options.
.TP
+.B \-R
+Recurse into subdirectories. Scan subdirectories recursively and add
+fonts with relative paths. Also recurse into symlinked directories.
+.TP
.B \-n
do not scan for fonts, do not write font directory files. This option
is useful when generating encoding directories only.
Reply to: