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.
This commit is contained in:
Keith Packard 2006-08-30 13:51:03 -07:00
parent e3096d90fd
commit c02886485b
6 changed files with 110 additions and 75 deletions

View File

@ -53,6 +53,7 @@
#include <getopt.h> #include <getopt.h>
const struct option longopts[] = { const struct option longopts[] = {
{"version", 0, 0, 'V'}, {"version", 0, 0, 'V'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, '?'}, {"help", 0, 0, '?'},
{NULL,0,0,0}, {NULL,0,0,0},
}; };
@ -167,39 +168,22 @@ usage (char *program)
exit (1); exit (1);
} }
/* read serialized state from the cache file */ static int
static char * FcCacheFileOpen (char *cache_file, off_t *size)
FcCacheFileRead (FcFontSet * set, FcStrSet *dirs, char *cache_file)
{ {
FILE *file;
int fd; int fd;
char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1]; struct stat file_stat;
static char name_buf[8192];
FcChar8 * ls;
char * buf;
int i;
if (!cache_file) fd = open(cache_file, O_RDONLY | O_BINARY);
goto bail; if (fd < 0)
return -1;
file = fopen(cache_file, "rb"); if (fstat (fd, &file_stat) < 0) {
if (file == NULL) close (fd);
goto bail; return -1;
}
if (!FcDirCacheConsume (file, set, dirs, NULL, name_buf)) *size = file_stat.st_size;
goto bail1; return fd;
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;
} }
/* /*
@ -210,11 +194,10 @@ static const FcChar8 *
FcFileBaseName (const char *cache, const FcChar8 *file) FcFileBaseName (const char *cache, const FcChar8 *file)
{ {
const FcChar8 *cache_slash; const FcChar8 *cache_slash;
int cache_len = strlen (cache);
cache_slash = FcStrLastSlash ((const FcChar8 *)cache); if (!strncmp (cache, file, cache_len) && file[cache_len] == '/')
if (cache_slash && !strncmp ((const char *) cache, (const char *) file, return file + cache_len + 1;
(cache_slash + 1) - (const FcChar8 *)cache))
return file + ((cache_slash + 1) - (const FcChar8 *)cache);
return file; return file;
} }
@ -252,14 +235,15 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name)
for (n = 0; n < set->nfont; n++) 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) if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
goto bail3; goto bail3;
base = FcFileBaseName (base_name, file); base = FcFileBaseName (base_name, file);
if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch) if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
goto bail3; goto bail3;
if (FcDebug () & FC_DBG_CACHEV)
printf (" write file \"%s\"\n", base);
if (!FcCacheWriteStringOld (stdout, base)) if (!FcCacheWriteStringOld (stdout, base))
goto bail3; goto bail3;
if (PUTC (' ', stdout) == EOF) if (PUTC (' ', stdout) == EOF)
@ -293,17 +277,19 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
int i; int i;
int ret = 0;
FcFontSet *fs;
FcStrSet *dirs;
FcCache *cache;
FcConfig *config;
int verbose = 0;
#if HAVE_GETOPT_LONG || HAVE_GETOPT #if HAVE_GETOPT_LONG || HAVE_GETOPT
int c; int c;
FcFontSet *fs = FcFontSetCreate();
FcStrSet *dirs = FcStrSetCreate();
char *name_buf;
FcConfig *config;
#if HAVE_GETOPT_LONG #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 #else
while ((c = getopt (argc, argv, "fsVv?")) != -1) while ((c = getopt (argc, argv, "Vv?")) != -1)
#endif #endif
{ {
switch (c) { switch (c) {
@ -311,6 +297,9 @@ main (int argc, char **argv)
fprintf (stderr, "fontconfig version %d.%d.%d\n", fprintf (stderr, "fontconfig version %d.%d.%d\n",
FC_MAJOR, FC_MINOR, FC_REVISION); FC_MAJOR, FC_MINOR, FC_REVISION);
exit (0); exit (0);
case 'v':
verbose++;
break;
default: default:
usage (argv[0]); usage (argv[0]);
} }
@ -331,29 +320,48 @@ main (int argc, char **argv)
if (i >= argc) if (i >= argc)
usage (argv[0]); usage (argv[0]);
for (; i < argc; i++)
{
int fd;
int j;
off_t size;
intptr_t *cache_dirs;
if (FcFileIsDir ((const FcChar8 *)argv[i])) if (FcFileIsDir ((const FcChar8 *)argv[i]))
{ fd = FcDirCacheOpen (config, (const FcChar8 *) argv[i], &size);
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 else
fd = FcCacheFileOpen (argv[i], &size);
if (fd < 0)
{ {
/* sorry, we can't tell you where the cache file is. */ perror (argv[i]);
FcCachePrintSet (fs, dirs, dummy_name); ret++;
FcStrFree ((FcChar8 *)dummy_name); continue;
}
}
else if ((name_buf = FcCacheFileRead (fs, dirs, argv[i])) != 0)
FcCachePrintSet (fs, dirs, name_buf);
else
{
printf ("nothing to do\n");
} }
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); FcStrSetDestroy (dirs);
FcFontSetDestroy (fs);
FcDirCacheUnmap (cache);
}
return 0; return 0;
} }

View File

@ -255,8 +255,7 @@ FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, off_t *size)
return fd; return fd;
} }
#if 0 void
static void
FcDirCacheUnmap (FcCache *cache) FcDirCacheUnmap (FcCache *cache)
{ {
if (cache->magic == FC_CACHE_MAGIC_COPY) if (cache->magic == FC_CACHE_MAGIC_COPY)
@ -270,10 +269,9 @@ FcDirCacheUnmap (FcCache *cache)
UnmapViewOfFile (cache); UnmapViewOfFile (cache);
#endif #endif
} }
#endif
/* read serialized state from the cache file */ /* read serialized state from the cache file */
static FcCache * FcCache *
FcDirCacheMap (int fd, off_t size) FcDirCacheMap (int fd, off_t size)
{ {
FcCache *cache; FcCache *cache;

View File

@ -1320,7 +1320,8 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
if (!leaf_serialized) if (!leaf_serialized)
return NULL; return NULL;
*leaf_serialized = *leaf; *leaf_serialized = *leaf;
leaves_serialized[i] = FcPtrToOffset (leaves_serialized, leaf); leaves_serialized[i] = FcPtrToOffset (leaves_serialized,
leaf_serialized);
numbers_serialized[i] = numbers[i]; numbers_serialized[i] = numbers[i];
} }

View File

@ -100,12 +100,26 @@ void
FcCharSetPrint (const FcCharSet *c) FcCharSetPrint (const FcCharSet *c)
{ {
int i, j; 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++) for (i = 0; i < c->num; i++)
{ {
FcCharLeaf *leaf = FcCharSetLeaf(c, i); printf ("Page %d: %04x +%d = 0x%x\n",
i, numbers[i], leaves[i],
(intptr_t) FcOffsetToPtr (leaves, leaves[i], FcCharLeaf));
}
printf ("%04x:", FcCharSetNumbers(c)[i]); for (i = 0; i < c->num; i++)
{
intptr_t leaf_offset = leaves[i];
FcCharLeaf *leaf = FcOffsetToPtr (leaves, leaf_offset, FcCharLeaf);
printf ("%04x:", numbers[i]);
for (j = 0; j < 256/32; j++) for (j = 0; j < 256/32; j++)
printf (" %08x", leaf->map[j]); printf (" %08x", leaf->map[j]);
printf ("\n"); printf ("\n");

View File

@ -199,11 +199,12 @@ struct _FcPattern {
#define FcPatternElts(p) FcOffsetMember(p,elts_offset,FcPatternElt) #define FcPatternElts(p) FcOffsetMember(p,elts_offset,FcPatternElt)
#define FcFontSetFonts(fs) FcPointerMember(fs,fonts,FcPattern *) #define FcFontSetFonts(fs) FcPointerMember(fs,fonts,FcPattern *)
/*
#define FcFontSetFont(fs,i) (FcIsEncodedOffset((fs)->fonts) ? \ #define FcFontSetFont(fs,i) (FcIsEncodedOffset((fs)->fonts) ? \
FcOffsetToPtr(FcFontSetFonts(fs), \ FcEncodedOffsetToPtr(FcFontSetFonts(fs), \
FcFontSetFonts(fs)[i]) : \ FcFontSetFonts(fs)[i], \
fs->fonts[i])*/ FcPattern) : \
fs->fonts[i])
typedef enum _FcOp { typedef enum _FcOp {
FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpBool, FcOpCharSet, FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpBool, FcOpCharSet,
@ -490,6 +491,12 @@ FcBool
FcDirCacheConsume (FILE *file, FcFontSet *set, FcStrSet *dirs, FcDirCacheConsume (FILE *file, FcFontSet *set, FcStrSet *dirs,
const FcChar8 *dir, char *dirname); const FcChar8 *dir, char *dirname);
FcCache *
FcDirCacheMap (int fd, off_t size);
void
FcDirCacheUnmap (FcCache *cache);
FcBool FcBool
FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config); FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);

View File

@ -1096,6 +1096,13 @@ FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
values_serialized, values_serialized,
FcValueList); FcValueList);
} }
if (FcDebug() & FC_DBG_CACHEV) {
printf ("Raw pattern:\n");
FcPatternPrint (pat);
printf ("Serialized pattern:\n");
FcPatternPrint (pat_serialized);
printf ("\n");
}
return pat_serialized; return pat_serialized;
} }