From c02886485b293179e8492cad9a34eb431dd4bfc9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 30 Aug 2006 13:51:03 -0700 Subject: [PATCH] FcCharSetSerialize was using wrong offset for leaves. Make fc-cat work. FcCharSetSerialize was computing the offset to the unserialized leaf, which left it pointing at random data when the cache was reloaded. fc-cat has been updated to work with the new cache structure. Various debug messages extended to help diagnose serialization errors. --- fc-cat/fc-cat.c | 134 +++++++++++++++++++++++++----------------------- src/fccache.c | 6 +-- src/fccharset.c | 3 +- src/fcdbg.c | 20 ++++++-- src/fcint.h | 15 ++++-- src/fcpat.c | 7 +++ 6 files changed, 110 insertions(+), 75 deletions(-) diff --git a/fc-cat/fc-cat.c b/fc-cat/fc-cat.c index 36f8bd9..b988a29 100644 --- a/fc-cat/fc-cat.c +++ b/fc-cat/fc-cat.c @@ -53,6 +53,7 @@ #include const struct option longopts[] = { {"version", 0, 0, 'V'}, + {"verbose", 0, 0, 'v'}, {"help", 0, 0, '?'}, {NULL,0,0,0}, }; @@ -167,39 +168,22 @@ usage (char *program) exit (1); } -/* read serialized state from the cache file */ -static char * -FcCacheFileRead (FcFontSet * set, FcStrSet *dirs, char *cache_file) +static int +FcCacheFileOpen (char *cache_file, off_t *size) { - FILE *file; int fd; - char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1]; - static char name_buf[8192]; - FcChar8 * ls; - char * buf; - int i; + struct stat file_stat; - if (!cache_file) - goto bail; + fd = open(cache_file, O_RDONLY | O_BINARY); + if (fd < 0) + return -1; - file = fopen(cache_file, "rb"); - if (file == NULL) - goto bail; - - if (!FcDirCacheConsume (file, set, dirs, NULL, name_buf)) - goto bail1; - - fclose (file); - - printf ("fc-cat: printing directory cache for cache which would be named %s\n", - name_buf); - - return name_buf; - - bail1: - fclose (file); - bail: - return 0; + if (fstat (fd, &file_stat) < 0) { + close (fd); + return -1; + } + *size = file_stat.st_size; + return fd; } /* @@ -210,11 +194,10 @@ static const FcChar8 * FcFileBaseName (const char *cache, const FcChar8 *file) { const FcChar8 *cache_slash; + int cache_len = strlen (cache); - cache_slash = FcStrLastSlash ((const FcChar8 *)cache); - if (cache_slash && !strncmp ((const char *) cache, (const char *) file, - (cache_slash + 1) - (const FcChar8 *)cache)) - return file + ((cache_slash + 1) - (const FcChar8 *)cache); + if (!strncmp (cache, file, cache_len) && file[cache_len] == '/') + return file + cache_len + 1; return file; } @@ -252,14 +235,15 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name) for (n = 0; n < set->nfont; n++) { - font = set->fonts[n]; + FcPattern **fonts = FcFontSetFonts (set); + FcPattern *encoded_font = fonts[n]; + FcPattern *font = FcEncodedOffsetToPtr (set, encoded_font, FcPattern); + if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch) goto bail3; base = FcFileBaseName (base_name, file); if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch) goto bail3; - if (FcDebug () & FC_DBG_CACHEV) - printf (" write file \"%s\"\n", base); if (!FcCacheWriteStringOld (stdout, base)) goto bail3; if (PUTC (' ', stdout) == EOF) @@ -293,17 +277,19 @@ int main (int argc, char **argv) { int i; + int ret = 0; + FcFontSet *fs; + FcStrSet *dirs; + FcCache *cache; + FcConfig *config; + int verbose = 0; #if HAVE_GETOPT_LONG || HAVE_GETOPT int c; - FcFontSet *fs = FcFontSetCreate(); - FcStrSet *dirs = FcStrSetCreate(); - char *name_buf; - FcConfig *config; #if HAVE_GETOPT_LONG - while ((c = getopt_long (argc, argv, "fsVv?", longopts, NULL)) != -1) + while ((c = getopt_long (argc, argv, "Vv?", longopts, NULL)) != -1) #else - while ((c = getopt (argc, argv, "fsVv?")) != -1) + while ((c = getopt (argc, argv, "Vv?")) != -1) #endif { switch (c) { @@ -311,6 +297,9 @@ main (int argc, char **argv) fprintf (stderr, "fontconfig version %d.%d.%d\n", FC_MAJOR, FC_MINOR, FC_REVISION); exit (0); + case 'v': + verbose++; + break; default: usage (argv[0]); } @@ -331,29 +320,48 @@ main (int argc, char **argv) if (i >= argc) usage (argv[0]); - if (FcFileIsDir ((const FcChar8 *)argv[i])) - { - char * dummy_name = (char *)FcStrPlus ((FcChar8 *)argv[i], - (FcChar8 *)"/dummy"); - if (!FcDirScanConfig (fs, dirs, 0, - (const FcChar8 *)argv[i], FcFalse, config)) - fprintf (stderr, "couldn't load font dir %s\n", argv[i]); - else - { - /* sorry, we can't tell you where the cache file is. */ - FcCachePrintSet (fs, dirs, dummy_name); - FcStrFree ((FcChar8 *)dummy_name); - } - } - else if ((name_buf = FcCacheFileRead (fs, dirs, argv[i])) != 0) - FcCachePrintSet (fs, dirs, name_buf); - else + for (; i < argc; i++) { - printf ("nothing to do\n"); - } + int fd; + int j; + off_t size; + intptr_t *cache_dirs; + + if (FcFileIsDir ((const FcChar8 *)argv[i])) + fd = FcDirCacheOpen (config, (const FcChar8 *) argv[i], &size); + else + fd = FcCacheFileOpen (argv[i], &size); + if (fd < 0) + { + perror (argv[i]); + ret++; + continue; + } + + cache = FcDirCacheMap (fd, size); + close (fd); + if (!cache) + { + fprintf (stderr, "%s: cannot map cache\n", argv[i]); + ret++; + continue; + } + dirs = FcStrSetCreate (); + fs = FcCacheSet (cache); + cache_dirs = FcCacheDirs (cache); + for (j = 0; j < cache->dirs_count; j++) + FcStrSetAdd (dirs, FcOffsetToPtr (cache_dirs, + cache_dirs[j], + FcChar8)); + + if (verbose) + printf ("Name: %s\nDirectory: %s\n", argv[i], FcCacheDir(cache)); + FcCachePrintSet (fs, dirs, FcCacheDir (cache)); - FcStrSetDestroy (dirs); - FcFontSetDestroy (fs); + FcStrSetDestroy (dirs); + + FcDirCacheUnmap (cache); + } return 0; } diff --git a/src/fccache.c b/src/fccache.c index c1c58fb..9f35f29 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -255,8 +255,7 @@ FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, off_t *size) return fd; } -#if 0 -static void +void FcDirCacheUnmap (FcCache *cache) { if (cache->magic == FC_CACHE_MAGIC_COPY) @@ -270,10 +269,9 @@ FcDirCacheUnmap (FcCache *cache) UnmapViewOfFile (cache); #endif } -#endif /* read serialized state from the cache file */ -static FcCache * +FcCache * FcDirCacheMap (int fd, off_t size) { FcCache *cache; diff --git a/src/fccharset.c b/src/fccharset.c index d55c611..96dcbe7 100644 --- a/src/fccharset.c +++ b/src/fccharset.c @@ -1320,7 +1320,8 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs) if (!leaf_serialized) return NULL; *leaf_serialized = *leaf; - leaves_serialized[i] = FcPtrToOffset (leaves_serialized, leaf); + leaves_serialized[i] = FcPtrToOffset (leaves_serialized, + leaf_serialized); numbers_serialized[i] = numbers[i]; } diff --git a/src/fcdbg.c b/src/fcdbg.c index 16b6bfd..c82dd3a 100644 --- a/src/fcdbg.c +++ b/src/fcdbg.c @@ -100,12 +100,26 @@ void FcCharSetPrint (const FcCharSet *c) { int i, j; - + intptr_t *leaves = FcCharSetLeaves (c); + FcChar16 *numbers = FcCharSetNumbers (c); + + printf ("CharSet 0x%x\n", (intptr_t) c); + printf ("Leaves: +%d = 0x%x\n", c->leaves_offset, (intptr_t) leaves); + printf ("Numbers: +%d = 0x%x\n", c->numbers_offset, (intptr_t) numbers); + + for (i = 0; i < c->num; i++) + { + printf ("Page %d: %04x +%d = 0x%x\n", + i, numbers[i], leaves[i], + (intptr_t) FcOffsetToPtr (leaves, leaves[i], FcCharLeaf)); + } + for (i = 0; i < c->num; i++) { - FcCharLeaf *leaf = FcCharSetLeaf(c, i); + intptr_t leaf_offset = leaves[i]; + FcCharLeaf *leaf = FcOffsetToPtr (leaves, leaf_offset, FcCharLeaf); - printf ("%04x:", FcCharSetNumbers(c)[i]); + printf ("%04x:", numbers[i]); for (j = 0; j < 256/32; j++) printf (" %08x", leaf->map[j]); printf ("\n"); diff --git a/src/fcint.h b/src/fcint.h index 2f656cb..adb3b16 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -199,11 +199,12 @@ struct _FcPattern { #define FcPatternElts(p) FcOffsetMember(p,elts_offset,FcPatternElt) #define FcFontSetFonts(fs) FcPointerMember(fs,fonts,FcPattern *) -/* + #define FcFontSetFont(fs,i) (FcIsEncodedOffset((fs)->fonts) ? \ - FcOffsetToPtr(FcFontSetFonts(fs), \ - FcFontSetFonts(fs)[i]) : \ - fs->fonts[i])*/ + FcEncodedOffsetToPtr(FcFontSetFonts(fs), \ + FcFontSetFonts(fs)[i], \ + FcPattern) : \ + fs->fonts[i]) typedef enum _FcOp { FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpBool, FcOpCharSet, @@ -490,6 +491,12 @@ FcBool FcDirCacheConsume (FILE *file, FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, char *dirname); +FcCache * +FcDirCacheMap (int fd, off_t size); + +void +FcDirCacheUnmap (FcCache *cache); + FcBool FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config); diff --git a/src/fcpat.c b/src/fcpat.c index 7432745..3eb8a73 100644 --- a/src/fcpat.c +++ b/src/fcpat.c @@ -1096,6 +1096,13 @@ FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat) values_serialized, FcValueList); } + if (FcDebug() & FC_DBG_CACHEV) { + printf ("Raw pattern:\n"); + FcPatternPrint (pat); + printf ("Serialized pattern:\n"); + FcPatternPrint (pat_serialized); + printf ("\n"); + } return pat_serialized; } -- 2.39.2