Make path names in cache files absolute (NB, cache format change) Stop

permitting cache files to be stored in font dirs. Bump cache magic.
    Don't include /fonts.cache-2 in cache hash construction.
reviewed by: Patrick Lam <plam@mit.edu>
This commit is contained in:
Keith Packard 2006-04-27 07:11:44 +00:00
parent 3b013a034a
commit c1c3ba06d5
7 changed files with 57 additions and 232 deletions

View File

@ -1,3 +1,33 @@
2006-04-27 Keith Packard <keithp@keithp.com>
reviewed by: Patrick Lam <plam@mit.edu>
* src/fccache.c: (FcDirCacheUnlink), (FcDirCacheHashName),
(FcDirCacheOpen), (FcDirCacheWrite):
* src/fcfreetype.c: (FcFreeTypeQuery):
* src/fcint.h:
* src/fclist.c: (FcListAppend):
* src/fcmatch.c: (FcFontRenderPrepare):
* src/fcpat.c: (FcPatternDestroy), (FcPatternBaseFreeze),
(FcPatternFreeze), (FcPatternGet), (FcPatternDuplicate),
(FcStrUnserialize):
Make path names in cache files absolute (NB, cache format change)
Stop permitting cache files to be stored in font dirs.
Bump cache magic.
Don't include /fonts.cache-2 in cache hash construction.
2006-04-26 Keith Packard <keithp@keithp.com>
* src/fccache.c: (FcDirCacheUnlink), (FcDirCacheOpen),
(FcDirCacheWrite):
* src/fcfreetype.c: (FcFreeTypeQuery):
* src/fcint.h:
* src/fclist.c: (FcListAppend):
* src/fcmatch.c: (FcFontRenderPrepare):
* src/fcpat.c: (FcPatternDestroy), (FcPatternBaseFreeze),
(FcPatternFreeze), (FcPatternGet), (FcPatternDuplicate),
(FcStrUnserialize):
2006-04-25 Patrick Lam <plam@mit.edu>
* ChangeLog:
* README:

View File

@ -48,7 +48,7 @@ static int
FcDirCacheOpen (const FcChar8 * dir);
static char *
FcDirCacheHashName (char * cache_file, int collisions);
FcDirCacheHashName (const FcChar8 * dir, int collisions);
static off_t
FcCacheSkipToArch (int fd, const char * arch);
@ -828,29 +828,21 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir)
FcBool
FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
{
char *cache_file;
char *cache_hashed = 0;
int fd, collisions;
struct stat cache_stat;
char name_buf[FC_MAX_FILE_LEN];
char dir_buf[FC_MAX_FILE_LEN];
dir = FcConfigNormalizeFontDir (config, dir);
cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
if (!cache_file)
return FcFalse;
/* First remove normal cache file. */
if (stat ((char *) cache_file, &cache_stat) == 0)
unlink ((char *)cache_file);
/* Next remove any applicable hashed files. */
/* Remove any applicable hashed files. */
fd = -1; collisions = 0;
do
{
if (cache_hashed)
FcStrFree ((FcChar8 *)cache_hashed);
cache_hashed = FcDirCacheHashName (cache_file, collisions++);
cache_hashed = FcDirCacheHashName (dir, collisions++);
if (!cache_hashed)
goto bail;
@ -860,16 +852,15 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
if (fd == -1)
{
FcStrFree ((FcChar8 *)cache_hashed);
FcStrFree ((FcChar8 *)cache_file);
return FcTrue;
}
if (!FcCacheReadString (fd, name_buf, sizeof (name_buf)) || !strlen(name_buf))
if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf))
{
FcStrFree ((FcChar8 *)cache_hashed);
goto bail;
}
} while (strcmp (name_buf, cache_file) != 0);
} while (strcmp ((char *) dir_buf, (char *) dir) != 0);
close (fd);
@ -880,12 +871,10 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
goto bail;
}
FcStrFree ((FcChar8 *)cache_file);
FcStrFree ((FcChar8 *)cache_hashed);
return FcTrue;
bail:
FcStrFree ((FcChar8 *)cache_file);
return FcFalse;
}
@ -1024,7 +1013,7 @@ static const char bin2hex[] = { '0', '1', '2', '3',
'c', 'd', 'e', 'f' };
static char *
FcDirCacheHashName (char * cache_file, int collisions)
FcDirCacheHashName (const FcChar8 * dir, int collisions)
{
unsigned char hash[16], hex_hash[33];
char *cache_hashed;
@ -1034,7 +1023,7 @@ FcDirCacheHashName (char * cache_file, int collisions)
struct MD5Context ctx;
MD5Init (&ctx);
MD5Update (&ctx, (unsigned char *)cache_file, strlen (cache_file));
MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir));
for (i = 0; i < collisions; i++)
MD5Update (&ctx, &uscore, 1);
@ -1066,60 +1055,40 @@ FcDirCacheOpen (const FcChar8 *dir)
{
FcBool found;
int fd = -1, collisions = 0;
char *cache_file, *cache_hashed;
char name_buf[FC_MAX_FILE_LEN];
char *cache_hashed;
char dir_buf[FC_MAX_FILE_LEN];
struct stat dir_stat;
if (stat ((char *)dir, &dir_stat) == -1)
return -1;
cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
if (!cache_file)
return -1;
found = FcFalse;
do
{
struct stat c;
FcChar8 *name_buf_dir;
if (fd >= 0)
close (fd);
cache_hashed = FcDirCacheHashName (cache_file, collisions++);
cache_hashed = FcDirCacheHashName (dir, collisions++);
if (!cache_hashed)
{
FcStrFree ((FcChar8 *)cache_file);
return -1;
}
fd = open(cache_hashed, O_RDONLY | O_BINARY);
FcStrFree ((FcChar8 *)cache_hashed);
if (fd == -1)
break;
if (!FcCacheReadString (fd, name_buf, sizeof (name_buf)) ||
!strlen(name_buf))
if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) ||
!strlen(dir_buf))
break;
name_buf_dir = FcStrDirname ((FcChar8 *)name_buf);
if (stat ((char *)name_buf_dir, &c) == -1)
{
FcStrFree (name_buf_dir);
if (stat ((char *)dir_buf, &c) == -1)
continue;
}
FcStrFree (name_buf_dir);
found = (c.st_ino == dir_stat.st_ino) && (c.st_dev == dir_stat.st_dev);
} while (!found);
if (!found || fd < 0)
{
if (fd >= 0)
close (fd);
fd = open(cache_file, O_RDONLY | O_BINARY);
}
FcStrFree ((FcChar8 *)cache_file);
return fd;
}
@ -1311,13 +1280,12 @@ FcDirCacheProduce (FcFontSet *set, FcCache *metadata)
FcBool
FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
{
char *cache_file;
char *cache_hashed;
int fd, fd_orig, i, dirs_count;
FcAtomic *atomic;
FcCache metadata;
off_t current_arch_start = 0, truncate_to;
char name_buf[FC_MAX_FILE_LEN];
char dir_buf[FC_MAX_FILE_LEN];
int collisions;
char *current_arch_machine_name, * header;
@ -1327,17 +1295,13 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
if (!dir)
return FcFalse;
cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
if (!cache_file)
goto bail;
/* Ensure that we're not trampling a cache for some other dir. */
/* This is slightly different from FcDirCacheOpen, since it
* needs the filename, not the file descriptor. */
fd = -1; collisions = 0;
do
{
cache_hashed = FcDirCacheHashName (cache_file, collisions++);
cache_hashed = FcDirCacheHashName (dir, collisions++);
if (!cache_hashed)
goto bail0;
@ -1346,7 +1310,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
fd = open(cache_hashed, O_RDONLY | O_BINARY);
if (fd == -1)
break;
if(!FcCacheReadString (fd, name_buf, sizeof (name_buf)) || !strlen(name_buf))
if(!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf))
{
close (fd);
FcStrFree ((FcChar8 *)cache_hashed);
@ -1354,7 +1318,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
}
close (fd);
if (strcmp (name_buf, cache_file) != 0)
if (strcmp (dir_buf, (char *) dir) != 0)
{
FcStrFree ((FcChar8 *)cache_hashed);
continue;
@ -1369,38 +1333,24 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
goto bail1;
if (FcDebug () & FC_DBG_CACHE)
printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
printf ("FcDirCacheWriteDir dir \"%s\" file \"%s\"\n",
dir, cache_hashed);
atomic = FcAtomicCreate ((FcChar8 *)cache_hashed);
if (!atomic)
goto bail1;
if (!FcAtomicLock (atomic))
{
/* Now try rewriting the original version of the file. */
FcAtomicDestroy (atomic);
goto bail2;
atomic = FcAtomicCreate ((FcChar8 *)cache_file);
fd_orig = open (cache_file, O_RDONLY | O_BINARY);
if (fd_orig == -1)
fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY | O_BINARY);
fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT | O_BINARY, 0666);
if (fd == -1)
goto bail2;
}
/* In all cases, try opening the real location of the cache file first. */
/* (even if that's not atomic.) */
fd_orig = open (cache_file, O_RDONLY | O_BINARY);
if (fd_orig == -1)
fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY | O_BINARY);
/* open the original file to save relevant portions */
fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY | O_BINARY);
fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT | O_BINARY, 0666);
if (fd == -1)
goto bail3;
FcCacheWriteString (fd, cache_file);
FcCacheWriteString (fd, (char *) dir);
current_arch_machine_name = FcCacheMachineSignature ();
current_arch_start = 0;
@ -1489,7 +1439,6 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
if (!FcAtomicReplaceOrig(atomic))
goto bail3;
FcStrFree ((FcChar8 *)cache_hashed);
FcStrFree ((FcChar8 *)cache_file);
FcAtomicUnlock (atomic);
FcAtomicDestroy (atomic);
return FcTrue;
@ -1505,11 +1454,8 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
bail1:
FcStrFree ((FcChar8 *)cache_hashed);
bail0:
unlink ((char *)cache_file);
FcStrFree ((FcChar8 *)cache_file);
if (current_dir_block)
free (current_dir_block);
bail:
return FcFalse;
}

View File

@ -997,7 +997,6 @@ FcFreeTypeQuery (const FcChar8 *file,
FcChar8 *family = 0;
#endif
FcChar8 *complex;
FcChar8 *file2;
const FcChar8 *foundry = 0;
int spacing;
TT_OS2 *os2;
@ -1278,15 +1277,8 @@ FcFreeTypeQuery (const FcChar8 *file,
printf ("Saving unique fullname %s\n", full);
}
file2 = FcStrCopy (file);
if (!FcPatternAddString (pat, FC_FILE, FcStrBasename(file2)))
{
FcStrFree (file2);
if (!FcPatternAddString (pat, FC_FILE, file))
goto bail1;
}
FcStrFree (file2);
FcPatternAddFullFname (pat, (const char *)FcStrCopy (file));
if (!FcPatternAddInteger (pat, FC_INDEX, id))
goto bail1;

View File

@ -333,7 +333,7 @@ typedef struct _FcCaseFold {
* cache which is then rewritten to the users home directory
*/
#define FC_CACHE_MAGIC 0xFC02FC03
#define FC_CACHE_MAGIC 0xFC02FC04
typedef struct _FcGlobalCacheDir FcGlobalCacheDir;
@ -871,12 +871,6 @@ FcPatternFini (void);
FcBool
FcPatternAppend (FcPattern *p, FcPattern *s);
void
FcPatternAddFullFname (const FcPattern *p, const char *fname);
void
FcPatternTransferFullFname (const FcPattern *new, const FcPattern *orig);
const FcChar8 *
FcStrStaticName (const FcChar8 *name);

View File

@ -422,10 +422,6 @@ FcListAppend (FcListHashTable *table,
else
defidx = 0;
/* Also, copy over the full path info. */
if (!strcmp (os->objects[o], FC_FILE))
FcPatternTransferFullFname (bucket->pattern, font);
e = FcPatternFindElt (font, os->objects[o]);
if (e)
{

View File

@ -495,9 +495,6 @@ FcFontRenderPrepare (FcConfig *config,
FcValueCanonicalize(&FcValueListPtrU(pe->values)->value), FcTrue);
}
if (FcPatternFindElt (font, FC_FILE))
FcPatternTransferFullFname (new, font);
FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
return new;
}

View File

@ -39,16 +39,6 @@ FcPatternEltPtrCreateDynamic (FcPatternElt * e);
static FcBool
FcStrHashed (const FcChar8 *name);
static const char *
FcPatternFindFullFname (const FcPattern *p);
/* If you are trying to duplicate an FcPattern which will be used for
* rendering, be aware that (internally) you also have to use
* FcPatternTransferFullFname to transfer the associated filename. If
* you are copying the font (externally) using FcPatternGetString,
* then everything's fine; this caveat only applies if you're copying
* the bits individually. */
FcPattern *
FcPatternCreate (void)
{
@ -311,12 +301,6 @@ FcPatternDestroy (FcPattern *p)
if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
return;
if (FcPatternFindFullFname (p))
{
FcStrFree ((FcChar8 *)FcPatternFindFullFname (p));
FcPatternAddFullFname (p, 0);
}
for (i = 0; i < p->num; i++)
FcValueListDestroy ((FcPatternEltU(p->elts)+i)->values);
@ -602,9 +586,6 @@ FcPatternBaseFreeze (FcPattern *b)
(FcPatternEltU(b->elts)+i)->object;
}
if (FcPatternFindElt (b, FC_FILE))
FcPatternTransferFullFname (ep, b);
ent->hash = hash;
ent->next = *bucket;
*bucket = ent;
@ -679,9 +660,6 @@ FcPatternFreeze (FcPattern *p)
}
}
if (FcPatternFindElt (p, FC_FILE))
FcPatternTransferFullFname (b, p);
/*
* Freeze base
*/
@ -1112,39 +1090,6 @@ FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
return FcPatternAdd (p, object, v, FcTrue);
}
static FcResult
FcPatternGetFile (const FcPattern *p, const char *object, int id, FcChar8 ** s)
{
const char *fn, *fpath;
FcChar8 *fname;
int size;
fn = FcPatternFindFullFname(p);
if (fn)
{
*s = (FcChar8 *) fn;
return FcResultMatch;
}
if (!p->bank)
return FcResultMatch;
fpath = FcCacheFindBankDir (p->bank);
size = strlen((char *)fpath) + 1 + strlen ((char *)*s) + 1;
fname = malloc (size);
if (!fname)
return FcResultOutOfMemory;
FcMemAlloc (FC_MEM_STRING, size);
strcpy ((char *)fname, (char *)fpath);
strcat ((char *)fname, "/");
strcat ((char *)fname, (char *)*s);
FcPatternAddFullFname (p, (const char *)fname);
*s = (FcChar8 *)fname;
return FcResultMatch;
}
FcResult
FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
{
@ -1159,12 +1104,6 @@ FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
if (!id)
{
*v = FcValueCanonicalize(&FcValueListPtrU(l)->value);
/* Pull the FC_FILE trick here too. */
if (v->type == FcTypeString &&
FcObjectToPtr(object) == FcObjectToPtr(FC_FILE))
return FcPatternGetFile (p, object, id, (FcChar8 **)&(v->u.s));
return FcResultMatch;
}
id--;
@ -1332,7 +1271,6 @@ FcPatternDuplicate (const FcPattern *orig)
FcTrue))
goto bail1;
}
FcPatternTransferFullFname (new, orig);
return new;
@ -2025,71 +1963,3 @@ FcStrUnserialize (FcCache * metadata, void *block_ptr)
return block_ptr;
}
/* we don't store these in the FcPattern itself because
* we don't want to serialize the directory names */
/* I suppose this should be cleaned upon termination, too... */
typedef struct _FcPatternDirMapping {
const FcPattern *p;
const char *fname;
} FcPatternDirMapping;
#define PATTERNDIR_HASH_SIZE 31
static struct patternDirBucket {
struct patternDirBucket *next;
FcPatternDirMapping m;
} FcPatternDirBuckets[PATTERNDIR_HASH_SIZE];
void
FcPatternAddFullFname (const FcPattern *p, const char *fname)
{
struct patternDirBucket *pb;
/* N.B. FcPatternHash fails, since it's contents-based, not
* address-based, and we're in the process of mutating the FcPattern. */
for (pb = &FcPatternDirBuckets
[((unsigned long)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
pb->m.p != p && pb->next;
pb = pb->next)
;
if (pb->m.p == p)
{
pb->m.fname = fname;
return;
}
pb->next = malloc (sizeof (struct patternDirBucket));
if (!pb->next)
return;
FcMemAlloc (FC_MEM_CACHE, sizeof (struct patternDirBucket));
pb->next->next = 0;
pb->next->m.p = p;
pb->next->m.fname = fname;
}
static const char *
FcPatternFindFullFname (const FcPattern *p)
{
struct patternDirBucket *pb;
for (pb = &FcPatternDirBuckets
[((unsigned long)p / sizeof (FcPattern *)) % PATTERNDIR_HASH_SIZE];
pb; pb = pb->next)
if (pb->m.p == p)
return pb->m.fname;
return 0;
}
void
FcPatternTransferFullFname (const FcPattern *new, const FcPattern *orig)
{
FcChar8 * s;
FcPatternGetString (orig, FC_FILE, 0, &s);
FcPatternAddFullFname (new,
(char *)FcStrCopy
((FcChar8 *)FcPatternFindFullFname(orig)));
}