X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=fc-cache%2Ffc-cache.c;h=29974b2ce2b6161032642a7bd574ec13482e35fb;hb=db50cbdaf592349c204ab0af0e7061ea72237044;hp=2bb012d2025174fdbcbd4760dec821dcfa501d79;hpb=65018b4a468c3175790dc27dfe37987151ad97d5;p=fontconfig.git diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c index 2bb012d..29974b2 100644 --- a/fc-cache/fc-cache.c +++ b/fc-cache/fc-cache.c @@ -1,7 +1,7 @@ /* - * $XFree86: $ + * $RCSId: xc/lib/fontconfig/fc-cache/fc-cache.c,v 1.8tsi Exp $ * - * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * Copyright © 2002 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -22,19 +22,45 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include #ifdef HAVE_CONFIG_H #include #else +#ifdef linux +#define HAVE_GETOPT_LONG 1 +#endif #define HAVE_GETOPT 1 #endif +#include +#include +#include +#include +#include +#include +#include + +#if defined (_WIN32) +#define STRICT +#include +#define sleep(x) Sleep((x) * 1000) +#undef STRICT +#endif + +#ifndef HAVE_GETOPT +#define HAVE_GETOPT 0 +#endif +#ifndef HAVE_GETOPT_LONG +#define HAVE_GETOPT_LONG 0 +#endif + #if HAVE_GETOPT_LONG +#undef _GNU_SOURCE #define _GNU_SOURCE #include const struct option longopts[] = { + {"force", 0, 0, 'f'}, + {"really-force", 0, 0, 'r'}, + {"system-only", 0, 0, 's'}, {"version", 0, 0, 'V'}, {"verbose", 0, 0, 'v'}, {"help", 0, 0, '?'}, @@ -50,41 +76,235 @@ extern int optind, opterr, optopt; static void usage (char *program) { - fprintf (stderr, "usage: %s [-vV?] [--verbose] [--version] [--help] [dirs]\n", +#if HAVE_GETOPT_LONG + fprintf (stderr, "usage: %s [-frsvV?] [--force|--really-force] [--system-only] [--verbose] [--version] [--help] [dirs]\n", program); +#else + fprintf (stderr, "usage: %s [-frsvV?] [dirs]\n", + program); +#endif fprintf (stderr, "Build font information caches in [dirs]\n" "(all directories in font configuration by default).\n"); fprintf (stderr, "\n"); +#if HAVE_GETOPT_LONG + fprintf (stderr, " -f, --force scan directories with apparently valid caches\n"); + fprintf (stderr, " -r, --really-force erase all existing caches, then rescan\n"); + fprintf (stderr, " -s, --system-only scan system-wide directories only\n"); fprintf (stderr, " -v, --verbose display status information while busy\n"); fprintf (stderr, " -V, --version display font config version and exit\n"); fprintf (stderr, " -?, --help display this help and exit\n"); +#else + fprintf (stderr, " -f (force) scan directories with apparently valid caches\n"); + fprintf (stderr, " -r, (really force) erase all existing caches, then rescan\n"); + fprintf (stderr, " -s (system) scan system-wide directories only\n"); + fprintf (stderr, " -v (verbose) display status information while busy\n"); + fprintf (stderr, " -V (version) display font config version and exit\n"); + fprintf (stderr, " -? (help) display this help and exit\n"); +#endif exit (1); } -int -main (int argc, char **argv) +static FcStrSet *processed_dirs; + +static int +nsubdirs (FcStrSet *set) +{ + FcStrList *list; + int n = 0; + + list = FcStrListCreate (set); + if (!list) + return 0; + while (FcStrListNext (list)) + n++; + FcStrListDone (list); + return n; +} + +static int +scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool really_force, FcBool verbose) { int ret = 0; + const FcChar8 *dir; FcFontSet *set; - FcChar8 **dirs; - int verbose = 0; + FcStrSet *subdirs; + FcStrList *sublist; + struct stat statb; + + /* + * Now scan all of the directories into separate databases + * and write out the results + */ + while ((dir = FcStrListNext (list))) + { + if (verbose) + { + printf ("%s: \"%s\": ", program, dir); + fflush (stdout); + } + + if (!dir) + { + if (verbose) + printf ("skipping, no such directory\n"); + continue; + } + + if (FcStrSetMember (processed_dirs, dir)) + { + if (verbose) + printf ("skipping, looped directory detected\n"); + continue; + } + + set = FcFontSetCreate (); + if (!set) + { + fprintf (stderr, "Can't create font set\n"); + ret++; + continue; + } + subdirs = FcStrSetCreate (); + if (!subdirs) + { + fprintf (stderr, "Can't create directory set\n"); + ret++; + FcFontSetDestroy (set); + continue; + } + + if (access ((char *) dir, W_OK) < 0) + { + switch (errno) { + case ENOENT: + case ENOTDIR: + if (verbose) + printf ("skipping, no such directory\n"); + FcFontSetDestroy (set); + FcStrSetDestroy (subdirs); + continue; + case EACCES: + case EROFS: + /* That's ok, caches go to /var anyway. */ + /* Ideally we'd do an access on the hashed_name. */ + /* But we hid that behind an abstraction barrier. */ + break; + default: + fprintf (stderr, "\"%s\": ", dir); + perror (""); + ret++; + + FcFontSetDestroy (set); + FcStrSetDestroy (subdirs); + continue; + } + } + if (stat ((char *) dir, &statb) == -1) + { + fprintf (stderr, "\"%s\": ", dir); + perror (""); + FcFontSetDestroy (set); + FcStrSetDestroy (subdirs); + ret++; + continue; + } + if (!S_ISDIR (statb.st_mode)) + { + fprintf (stderr, "\"%s\": not a directory, skipping\n", dir); + FcFontSetDestroy (set); + FcStrSetDestroy (subdirs); + continue; + } + + if (really_force) + FcDirCacheUnlink (dir, config); + + if (!FcDirScanConfig (set, subdirs, 0, FcConfigGetBlanks (config), dir, force, config)) + { + fprintf (stderr, "\"%s\": error scanning\n", dir); + FcFontSetDestroy (set); + FcStrSetDestroy (subdirs); + ret++; + continue; + } + if (!force && FcDirCacheValid (dir, config) && + FcDirCacheHasCurrentArch (dir, config)) + { + if (verbose) + printf ("skipping, %d fonts, %d dirs\n", + set->nfont, nsubdirs(subdirs)); + } + else + { + if (verbose) + printf ("caching, %d fonts, %d dirs\n", + set->nfont, nsubdirs (subdirs)); + + /* This is the only reason we can't combine + * Valid w/HasCurrentArch... */ + if (!FcDirCacheValid (dir, config)) + if (!FcDirCacheUnlink (dir, config)) + ret++; + + if (!FcDirSave (set, subdirs, dir)) + { + fprintf (stderr, "Can't save cache for \"%s\"\n", dir); + ret++; + } + } + FcFontSetDestroy (set); + sublist = FcStrListCreate (subdirs); + FcStrSetDestroy (subdirs); + if (!sublist) + { + fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir); + ret++; + continue; + } + FcStrSetAdd (processed_dirs, dir); + ret += scanDirs (sublist, config, program, force, really_force, verbose); + } + FcStrListDone (list); + return ret; +} + +int +main (int argc, char **argv) +{ + FcStrSet *dirs; + FcStrList *list; + FcBool verbose = FcFalse; + FcBool force = FcFalse; + FcBool really_force = FcFalse; + FcBool systemOnly = FcFalse; + FcConfig *config; int i; + int ret; #if HAVE_GETOPT_LONG || HAVE_GETOPT int c; #if HAVE_GETOPT_LONG - while ((c = getopt_long (argc, argv, "Vv?", longopts, NULL)) != -1) + while ((c = getopt_long (argc, argv, "frsVv?", longopts, NULL)) != -1) #else - while ((c = getopt (argc, argv, "Vv?")) != -1) + while ((c = getopt (argc, argv, "frsVv?")) != -1) #endif { switch (c) { + case 'r': + really_force = FcTrue; + /* fall through */ + case 'f': + force = FcTrue; + break; + case 's': + systemOnly = FcTrue; + break; case 'V': fprintf (stderr, "fontconfig version %d.%d.%d\n", FC_MAJOR, FC_MINOR, FC_REVISION); exit (0); case 'v': - verbose = 1; + verbose = FcTrue; break; default: usage (argv[0]); @@ -95,51 +315,58 @@ main (int argc, char **argv) i = 1; #endif - if (!FcInitConfig ()) + if (systemOnly) + FcConfigEnableHome (FcFalse); + config = FcInitLoadConfig (); + if (!config) { - fprintf (stderr, "Can't init font config library\n"); + fprintf (stderr, "%s: Can't init font config library\n", argv[0]); return 1; } + FcConfigSetCurrent (config); + if (argv[i]) - dirs = (FcChar8 **) (argv+i); - else - dirs = FcConfigGetDirs (0); - /* - * Now scan all of the directories into separate databases - * and write out the results - */ - while (dirs && *dirs) { - if (verbose) - printf ("%s: Scanning directory \"%s\"\n", argv[0], *dirs); - set = FcFontSetCreate (); - if (!set) + dirs = FcStrSetCreate (); + if (!dirs) { - fprintf (stderr, "Out of memory in \"%s\"\n", *dirs); - ret++; + fprintf (stderr, "%s: Can't create list of directories\n", + argv[0]); + return 1; } - else + while (argv[i]) { - if (!FcDirScan (set, 0, FcConfigGetBlanks (0), *dirs, FcTrue)) + if (!FcStrSetAdd (dirs, (FcChar8 *) argv[i])) { - fprintf (stderr, "Can't scan directory \"%s\"\n", *dirs); - ret++; + fprintf (stderr, "%s: Can't add directory\n", argv[0]); + return 1; } - else - { - if (verbose) - printf ("%s: Saving %d font names for \"%s\"\n", - argv[0], set->nfont, *dirs); - if (!FcDirSave (set, *dirs)) - { - fprintf (stderr, "Can't save cache in \"%s\"\n", *dirs); - ret++; - } - } - FcFontSetDestroy (set); + i++; } - ++dirs; + list = FcStrListCreate (dirs); + FcStrSetDestroy (dirs); } + else + list = FcConfigGetConfigDirs (config); + + if ((processed_dirs = FcStrSetCreate()) == NULL) { + fprintf(stderr, "Cannot malloc\n"); + return 1; + } + + ret = scanDirs (list, config, argv[0], force, really_force, verbose); + + FcStrSetDestroy (processed_dirs); + + /* + * Now we need to sleep a second (or two, to be extra sure), to make + * sure that timestamps for changes after this run of fc-cache are later + * then any timestamps we wrote. We don't use gettimeofday() because + * sleep(3) can't be interrupted by a signal here -- this isn't in the + * library, and there aren't any signals flying around here. + */ + FcConfigDestroy (config); + sleep (2); if (verbose) printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded"); return ret;