X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=fc-cache%2Ffc-cache.c;h=9bac25d7f3e6db825d85ef7a7be111df3a6cfb72;hb=refs%2Fheads%2Fcache-conv;hp=5fc409200b88c46cf1c185600bd0138bd6e566b3;hpb=f57783d2e9c7362b1e5d5e3a967ba90fa49ade6e;p=fontconfig.git diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c index 5fc4092..9bac25d 100644 --- a/fc-cache/fc-cache.c +++ b/fc-cache/fc-cache.c @@ -1,5 +1,5 @@ /* - * $RCSId: xc/lib/fontconfig/fc-cache/fc-cache.c,v 1.8tsi Exp $ + * fontconfig/fc-cache/fc-cache.c * * Copyright © 2002 Keith Packard * @@ -7,21 +7,23 @@ * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in + * documentation, and that the name of the author(s) not be used in * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no + * specific, written prior permission. The authors make no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +#include "../src/fcarch.h" + #ifdef HAVE_CONFIG_H #include #else @@ -31,7 +33,7 @@ #define HAVE_GETOPT 1 #endif -#include "fcint.h" +#include #include #include #include @@ -40,6 +42,7 @@ #include #include #include +#include #if defined (_WIN32) #define STRICT @@ -64,12 +67,14 @@ #define _GNU_SOURCE #include const struct option longopts[] = { + {"convert", 0, 0, 'c'}, {"force", 0, 0, 'f'}, {"really-force", 0, 0, 'r'}, + {"root", 1, 0, 'R'}, {"system-only", 0, 0, 's'}, {"version", 0, 0, 'V'}, {"verbose", 0, 0, 'v'}, - {"help", 0, 0, '?'}, + {"help", 0, 0, 'h'}, {NULL,0,0,0}, }; #else @@ -80,63 +85,52 @@ extern int optind, opterr, optopt; #endif static void -usage (char *program) +usage (char *program, int error) { + FILE *file = error ? stderr : stdout; #if HAVE_GETOPT_LONG - fprintf (stderr, "usage: %s [-frsvV?] [--force|--really-force] [--system-only] [--verbose] [--version] [--help] [dirs]\n", + fprintf (file, "usage: %s [-frRsvVh] [--force|--really-force] [--root ] [--system-only] [--verbose] [--version] [--help] [dirs]\n", program); #else - fprintf (stderr, "usage: %s [-frsvV?] [dirs]\n", + fprintf (file, "usage: %s [-frRsvVh] [dirs]\n", program); #endif - fprintf (stderr, "Build font information caches in [dirs]\n" + fprintf (file, "Build font information caches in [dirs]\n" "(all directories in font configuration by default).\n"); - fprintf (stderr, "\n"); + fprintf (file, "\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"); + fprintf (file, " -f, --force scan directories with apparently valid caches\n"); + fprintf (file, " -r, --really-force erase all existing caches, then rescan\n"); + fprintf (file, " -R, --root change to before loading files\n"); + fprintf (file, " -s, --system-only scan system-wide directories only\n"); + fprintf (file, " -v, --verbose display status information while busy\n"); + fprintf (file, " -V, --version display font config version and exit\n"); + fprintf (file, " -h, --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"); + fprintf (file, " -f (force) scan directories with apparently valid caches\n"); + fprintf (file, " -r, (really force) erase all existing caches, then rescan\n"); + fprintf (file, " -R (root) change to before loading files\n"); + fprintf (file, " -s (system) scan system-wide directories only\n"); + fprintf (file, " -v (verbose) display status information while busy\n"); + fprintf (file, " -V (version) display font config version and exit\n"); + fprintf (file, " -h (help) display this help and exit\n"); #endif - exit (1); + exit (error); } 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) +scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, int *changed) { - int ret = 0; - const FcChar8 *dir; - FcFontSet *set; - FcStrSet *subdirs; - FcStrList *sublist; - struct stat statb; - FcBool was_valid; + int ret = 0; + const FcChar8 *dir; + FcStrSet *subdirs; + FcStrList *sublist; + FcCache *cache; + struct stat statb; + FcBool was_valid; + int i; /* * Now scan all of the directories into separate databases @@ -146,7 +140,7 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool { if (verbose) { - printf ("%s: \"%s\": ", program, dir); + printf ("%s: ", dir); fflush (stdout); } @@ -164,90 +158,63 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool continue; } - set = FcFontSetCreate (); - if (!set) - { - fprintf (stderr, "%s: Can't create font set\n", dir); - ret++; - continue; - } - subdirs = FcStrSetCreate (); - if (!subdirs) - { - fprintf (stderr, "%s: Can't create directory set\n", dir); - ret++; - FcFontSetDestroy (set); - continue; - } - - if (access ((char *) dir, W_OK) < 0) + if (FcStat (config, dir, &statb) == -1) { 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; + break; } - } - 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 (!force) - was_valid = FcDirCacheValid (dir); + cache = NULL; + was_valid = FcFalse; + if (!force) { + cache = FcDirCacheLoad (dir, config, NULL); + if (cache) + was_valid = FcTrue; + } - if (!FcDirScanConfig (set, subdirs, FcConfigGetBlanks (config), dir, force, config)) + if (!cache) { - fprintf (stderr, "%s: error scanning\n", dir); - FcFontSetDestroy (set); - FcStrSetDestroy (subdirs); - ret++; - continue; + (*changed)++; + cache = FcDirCacheRead (dir, FcTrue, config); + if (!cache) + { + fprintf (stderr, "%s: error scanning\n", dir); + ret++; + continue; + } } - if (!force && was_valid) + + if (was_valid) { if (verbose) - printf ("skipping, %d fonts, %d dirs\n", - set->nfont, nsubdirs(subdirs)); + printf ("skipping, existing cache is valid: %d fonts, %d dirs\n", + FcCacheNumFont (cache), FcCacheNumSubdir (cache)); } else { if (verbose) - printf ("caching, %d fonts, %d dirs\n", - set->nfont, nsubdirs (subdirs)); + printf ("caching, new cache contents: %d fonts, %d dirs\n", + FcCacheNumFont (cache), FcCacheNumSubdir (cache)); if (!FcDirCacheValid (dir)) { @@ -256,7 +223,20 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool ret++; } } - FcFontSetDestroy (set); + + subdirs = FcStrSetCreate (); + if (!subdirs) + { + fprintf (stderr, "%s: Can't create subdir set\n", dir); + ret++; + FcDirCacheUnload (cache); + continue; + } + for (i = 0; i < FcCacheNumSubdir (cache); i++) + FcStrSetAdd (subdirs, FcCacheSubdir (cache, i)); + + FcDirCacheUnload (cache); + sublist = FcStrListCreate (subdirs); FcStrSetDestroy (subdirs); if (!sublist) @@ -266,108 +246,106 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool continue; } FcStrSetAdd (processed_dirs, dir); - ret += scanDirs (sublist, config, program, force, really_force, verbose); + ret += scanDirs (sublist, config, force, really_force, verbose, changed); } FcStrListDone (list); return ret; } -FcCache * -FcCacheFileMap (const FcChar8 *file, struct stat *file_stat) -{ - FcCache *cache; - int fd; - - fd = open (file, O_RDONLY | O_BINARY); - if (fd < 0) - return NULL; - if (fstat (fd, file_stat) < 0) { - close (fd); - return NULL; - } - if (FcDirCacheLoad (fd, file_stat->st_size, &cache)) { - close (fd); - return cache; - } - close (fd); - return NULL; -} - static FcBool cleanCacheDirectory (FcConfig *config, FcChar8 *dir, FcBool verbose) { DIR *d; struct dirent *ent; - char *dir_base; + FcChar8 *fullDir; + FcChar8 *checkDir; FcBool ret = FcTrue; FcBool remove; FcCache *cache; - struct stat file_stat; struct stat target_stat; - dir_base = FcStrPlus (dir, "/"); - if (access ((char *) dir, W_OK|X_OK) != 0) + fullDir = FcConfigGetRootPlus (config, dir); + if (fullDir) + checkDir = fullDir; + else + checkDir = dir; + + if (access ((char *) checkDir, W_OK) != 0) { if (verbose) - printf ("%s: skipping unwritable cache directory\n", dir); - return FcTrue; + printf ("%s: not cleaning %s cache directory\n", dir, + access ((char *) dir, F_OK) == 0 ? "unwritable" : "non-existent"); + goto done; } - d = opendir (dir); + if (verbose) + printf ("%s: cleaning cache directory\n", dir); + d = opendir ((char *) checkDir); if (!d) { - perror (dir); - return FcFalse; + perror ((char *) dir); + ret = FcFalse; + goto done; } while ((ent = readdir (d))) { FcChar8 *file_name; - FcChar8 *target_dir; + const FcChar8 *target_dir; if (ent->d_name[0] == '.') continue; - file_name = FcStrPlus (dir_base, ent->d_name); + /* skip cache files for different architectures and */ + /* files which are not cache files at all */ + if (strlen(ent->d_name) != 32 + strlen ("-" FC_ARCHITECTURE FC_CACHE_SUFFIX) || + strcmp(ent->d_name + 32, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX)) + continue; + + file_name = FcStrPathPlus (dir, (const FcChar8 *) ent->d_name, NULL); if (!file_name) { fprintf (stderr, "%s: allocation failure\n", dir); ret = FcFalse; break; } - cache = FcCacheFileMap (file_name, &file_stat); - if (!cache) - { - fprintf (stderr, "%s: invalid cache file: %s\n", dir, ent->d_name); - FcStrFree (file_name); - ret = FcFalse; - continue; - } - target_dir = FcCacheDir (cache); remove = FcFalse; - if (stat (target_dir, &target_stat) < 0) + cache = FcDirCacheLoadFile2 (file_name, config, NULL); + if (!cache) { if (verbose) - printf ("%s: %s: missing directory: %s \n", - dir, ent->d_name, target_dir); + printf ("%s: invalid cache file: %s\n", dir, ent->d_name); remove = FcTrue; } - else if (target_stat.st_mtime > file_stat.st_mtime) + else { - if (verbose) - printf ("%s: %s: cache outdated: %s\n", - dir, ent->d_name, target_dir); - remove = FcTrue; + target_dir = FcCacheDir (cache); + if (FcStat (config, target_dir, &target_stat) < 0) + { + if (verbose) + printf ("%s: %s: missing directory: %s \n", + dir, ent->d_name, target_dir); + remove = FcTrue; + } } if (remove) { - if (unlink (file_name) < 0) + FcChar8 *unlink_file = FcConfigGetRootPlus (config, file_name); + if (!unlink_file) + unlink_file = file_name; + if (unlink ((char *) unlink_file) < 0) { - perror (file_name); + perror ((char *) unlink_file); ret = FcFalse; } + if (unlink_file != file_name) + FcStrFree (unlink_file); } + FcDirCacheUnload (cache); FcStrFree (file_name); } closedir (d); + done: + if (fullDir) + FcStrFree (fullDir); return ret; } @@ -402,24 +380,34 @@ main (int argc, char **argv) FcBool really_force = FcFalse; FcBool systemOnly = FcFalse; FcConfig *config; + const char *rootDir; int i; + int changed; int ret; #if HAVE_GETOPT_LONG || HAVE_GETOPT int c; +FcBool convert = FcFalse; + #if HAVE_GETOPT_LONG - while ((c = getopt_long (argc, argv, "frsVv?", longopts, NULL)) != -1) + while ((c = getopt_long (argc, argv, "cfrR:sVvh", longopts, NULL)) != -1) #else - while ((c = getopt (argc, argv, "frsVv?")) != -1) + while ((c = getopt (argc, argv, "cfrR:sVvh")) != -1) #endif { switch (c) { + case 'c': + convert = FcTrue; + break; case 'r': really_force = FcTrue; /* fall through */ case 'f': force = FcTrue; break; + case 'R': + rootDir = optarg; + break; case 's': systemOnly = FcTrue; break; @@ -430,8 +418,10 @@ main (int argc, char **argv) case 'v': verbose = FcTrue; break; + case 'h': + usage (argv[0], 0); default: - usage (argv[0]); + usage (argv[0], 1); } } i = optind; @@ -439,6 +429,20 @@ main (int argc, char **argv) i = 1; #endif + if (convert) + { + const FcChar8 *src_cache, *dst_cache, *src_type, *dst_type; + + src_cache = (const FcChar8 *) argv[i++]; + src_type = (const FcChar8 *) argv[i++]; + dst_cache = (const FcChar8 *) argv[i++]; + dst_type = (const FcChar8 *) argv[i++]; + + FcDirCacheConvert (src_cache, src_type, dst_cache, dst_type); + + return 0; + } + if (systemOnly) FcConfigEnableHome (FcFalse); config = FcInitLoadConfig (); @@ -448,6 +452,7 @@ main (int argc, char **argv) return 1; } FcConfigSetCurrent (config); + FcConfigSetRoot (config, (const FcChar8 *) rootDir); if (argv[i]) { @@ -460,7 +465,7 @@ main (int argc, char **argv) } while (argv[i]) { - if (!FcStrSetAdd (dirs, (FcChar8 *) argv[i])) + if (!FcStrSetAddFilename (dirs, (FcChar8 *) argv[i])) { fprintf (stderr, "%s: Can't add directory\n", argv[0]); return 1; @@ -478,7 +483,8 @@ main (int argc, char **argv) return 1; } - ret = scanDirs (list, config, argv[0], force, really_force, verbose); + changed = 0; + ret = scanDirs (list, config, force, really_force, verbose, &changed); FcStrSetDestroy (processed_dirs); @@ -492,7 +498,9 @@ main (int argc, char **argv) * library, and there aren't any signals flying around here. */ FcConfigDestroy (config); - sleep (2); + FcFini (); + if (changed) + sleep (2); if (verbose) printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded"); return ret;