2002-02-15 00:34:13 +01:00
|
|
|
|
/*
|
2002-09-01 00:17:32 +02:00
|
|
|
|
* $XFree86: xc/lib/fontconfig/src/fccache.c,v 1.12 2002/08/22 07:36:44 keithp Exp $
|
2002-02-15 00:34:13 +01:00
|
|
|
|
*
|
|
|
|
|
* Copyright <EFBFBD> 2000 Keith Packard, member of The XFree86 Project, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
|
* 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
|
|
|
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
|
|
|
* specific, written prior permission. Keith Packard makes 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,
|
|
|
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
|
|
|
* EVENT SHALL KEITH PACKARD 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 "fcint.h"
|
|
|
|
|
|
2002-08-19 21:32:05 +02:00
|
|
|
|
/*
|
|
|
|
|
* POSIX has broken stdio so that getc must do thread-safe locking,
|
|
|
|
|
* this is a serious performance problem for applications doing large
|
|
|
|
|
* amounts of IO with getc (as is done here). If available, use
|
|
|
|
|
* the getc_unlocked varient instead.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#if defined(getc_unlocked) || defined(_IO_getc_unlocked)
|
|
|
|
|
#define GETC(f) getc_unlocked(f)
|
|
|
|
|
#define PUTC(c,f) putc_unlocked(c,f)
|
|
|
|
|
#else
|
|
|
|
|
#define GETC(f) getc(f)
|
|
|
|
|
#define PUTC(c,f) putc(c,f)
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
#define FC_DBG_CACHE_REF 1024
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
static FcChar8 *
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcCacheReadString (FILE *f, FcChar8 *dest, int len)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-02-15 07:01:28 +01:00
|
|
|
|
int c;
|
|
|
|
|
FcBool escape;
|
|
|
|
|
FcChar8 *d;
|
|
|
|
|
int size;
|
|
|
|
|
int i;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-08-19 21:32:05 +02:00
|
|
|
|
while ((c = GETC (f)) != EOF)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (c == '"')
|
|
|
|
|
break;
|
|
|
|
|
if (c == EOF)
|
|
|
|
|
return FcFalse;
|
|
|
|
|
if (len == 0)
|
|
|
|
|
return FcFalse;
|
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
size = len;
|
|
|
|
|
i = 0;
|
|
|
|
|
d = dest;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
escape = FcFalse;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
while ((c = GETC (f)) != EOF)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
|
|
|
|
if (!escape)
|
|
|
|
|
{
|
|
|
|
|
switch (c) {
|
|
|
|
|
case '"':
|
2002-02-15 07:01:28 +01:00
|
|
|
|
c = '\0';
|
|
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
case '\\':
|
|
|
|
|
escape = FcTrue;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (i == size)
|
|
|
|
|
{
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcChar8 *new = malloc (size * 2); /* freed in caller */
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (!new)
|
|
|
|
|
break;
|
|
|
|
|
memcpy (new, d, size);
|
|
|
|
|
size *= 2;
|
|
|
|
|
if (d != dest)
|
|
|
|
|
free (d);
|
|
|
|
|
d = new;
|
|
|
|
|
}
|
|
|
|
|
d[i++] = c;
|
|
|
|
|
if (c == '\0')
|
|
|
|
|
return d;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
escape = FcFalse;
|
|
|
|
|
}
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (d != dest)
|
|
|
|
|
free (d);
|
|
|
|
|
return 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcCacheReadUlong (FILE *f, unsigned long *dest)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
|
|
|
|
unsigned long t;
|
|
|
|
|
int c;
|
|
|
|
|
|
2002-08-19 21:32:05 +02:00
|
|
|
|
while ((c = GETC (f)) != EOF)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
|
|
|
|
if (!isspace (c))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (c == EOF)
|
|
|
|
|
return FcFalse;
|
|
|
|
|
t = 0;
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
if (c == EOF || isspace (c))
|
|
|
|
|
break;
|
|
|
|
|
if (!isdigit (c))
|
|
|
|
|
return FcFalse;
|
|
|
|
|
t = t * 10 + (c - '0');
|
2002-08-19 21:32:05 +02:00
|
|
|
|
c = GETC (f);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
*dest = t;
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcCacheReadInt (FILE *f, int *dest)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
|
|
|
|
unsigned long t;
|
|
|
|
|
FcBool ret;
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
ret = FcCacheReadUlong (f, &t);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (ret)
|
|
|
|
|
*dest = (int) t;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcCacheReadTime (FILE *f, time_t *dest)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
|
|
|
|
unsigned long t;
|
|
|
|
|
FcBool ret;
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
ret = FcCacheReadUlong (f, &t);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (ret)
|
|
|
|
|
*dest = (time_t) t;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcCacheWriteChars (FILE *f, const FcChar8 *chars)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcChar8 c;
|
|
|
|
|
while ((c = *chars++))
|
|
|
|
|
{
|
|
|
|
|
switch (c) {
|
|
|
|
|
case '"':
|
|
|
|
|
case '\\':
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('\\', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
/* fall through */
|
|
|
|
|
default:
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (c, f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
static FcBool
|
|
|
|
|
FcCacheWriteString (FILE *f, const FcChar8 *string)
|
|
|
|
|
{
|
|
|
|
|
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('"', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
if (!FcCacheWriteChars (f, string))
|
|
|
|
|
return FcFalse;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('"', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
|
FcCacheWritePath (FILE *f, const FcChar8 *dir, const FcChar8 *file)
|
|
|
|
|
{
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('"', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
if (dir)
|
|
|
|
|
if (!FcCacheWriteChars (f, dir))
|
|
|
|
|
return FcFalse;
|
|
|
|
|
if (dir && dir[strlen((const char *) dir) - 1] != '/')
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('/', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
if (!FcCacheWriteChars (f, file))
|
|
|
|
|
return FcFalse;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('"', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
|
FcCacheWriteUlong (FILE *f, unsigned long t)
|
|
|
|
|
{
|
|
|
|
|
int pow;
|
|
|
|
|
unsigned long temp, digit;
|
|
|
|
|
|
|
|
|
|
temp = t;
|
|
|
|
|
pow = 1;
|
|
|
|
|
while (temp >= 10)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
temp /= 10;
|
|
|
|
|
pow *= 10;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
2002-07-28 12:50:59 +02:00
|
|
|
|
temp = t;
|
|
|
|
|
while (pow)
|
|
|
|
|
{
|
|
|
|
|
digit = temp / pow;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ((char) digit + '0', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
temp = temp - pow * digit;
|
|
|
|
|
pow = pow / 10;
|
|
|
|
|
}
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
|
FcCacheWriteInt (FILE *f, int i)
|
|
|
|
|
{
|
|
|
|
|
return FcCacheWriteUlong (f, (unsigned long) i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
|
FcCacheWriteTime (FILE *f, time_t t)
|
|
|
|
|
{
|
|
|
|
|
return FcCacheWriteUlong (f, (unsigned long) t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
|
FcCacheFontSetAdd (FcFontSet *set,
|
|
|
|
|
FcStrSet *dirs,
|
|
|
|
|
const FcChar8 *dir,
|
|
|
|
|
int dir_len,
|
|
|
|
|
const FcChar8 *file,
|
|
|
|
|
const FcChar8 *name)
|
|
|
|
|
{
|
|
|
|
|
FcChar8 path_buf[8192], *path;
|
|
|
|
|
int len;
|
|
|
|
|
FcBool ret = FcFalse;
|
|
|
|
|
FcPattern *font;
|
2002-08-22 09:36:45 +02:00
|
|
|
|
FcPattern *frozen;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
|
|
|
|
|
path = path_buf;
|
|
|
|
|
len = (dir_len + 1 + strlen ((const char *) file) + 1);
|
|
|
|
|
if (len > sizeof (path_buf))
|
|
|
|
|
{
|
2002-09-01 00:17:32 +02:00
|
|
|
|
path = malloc (len); /* freed down below */
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!path)
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
strncpy ((char *) path, (const char *) dir, dir_len);
|
|
|
|
|
if (dir[dir_len - 1] != '/')
|
|
|
|
|
path[dir_len++] = '/';
|
|
|
|
|
strcpy ((char *) path + dir_len, (const char *) file);
|
|
|
|
|
if (!FcStrCmp (name, FC_FONT_FILE_DIR))
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHEV)
|
|
|
|
|
printf (" dir cache dir \"%s\"\n", path);
|
|
|
|
|
ret = FcStrSetAdd (dirs, path);
|
|
|
|
|
}
|
|
|
|
|
else if (!FcStrCmp (name, FC_FONT_FILE_INVALID))
|
|
|
|
|
{
|
|
|
|
|
ret = FcTrue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
font = FcNameParse (name);
|
|
|
|
|
if (font)
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHEV)
|
|
|
|
|
printf (" dir cache file \"%s\"\n", file);
|
2002-08-22 09:36:45 +02:00
|
|
|
|
ret = FcPatternAddString (font, FC_FILE, path);
|
|
|
|
|
if (ret)
|
|
|
|
|
{
|
|
|
|
|
frozen = FcPatternFreeze (font);
|
|
|
|
|
ret = (frozen != 0);
|
|
|
|
|
if (ret)
|
|
|
|
|
ret = FcFontSetAdd (set, frozen);
|
|
|
|
|
}
|
|
|
|
|
FcPatternDestroy (font);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (path != path_buf) free (path);
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
|
FcCacheHash (const FcChar8 *string)
|
|
|
|
|
{
|
|
|
|
|
unsigned int h = 0;
|
|
|
|
|
FcChar8 c;
|
|
|
|
|
|
|
|
|
|
while ((c = *string++))
|
|
|
|
|
h = (h << 1) ^ c;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Verify the saved timestamp for a file
|
|
|
|
|
*/
|
|
|
|
|
FcBool
|
|
|
|
|
FcGlobalCacheCheckTime (FcGlobalCacheInfo *info)
|
|
|
|
|
{
|
|
|
|
|
struct stat statb;
|
|
|
|
|
|
|
|
|
|
if (stat ((char *) info->file, &statb) < 0)
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf (" file missing\n");
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
if (statb.st_mtime != info->time)
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf (" timestamp mismatch (was %d is %d)\n",
|
|
|
|
|
(int) info->time, (int) statb.st_mtime);
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FcGlobalCacheReferenced (FcGlobalCache *cache,
|
|
|
|
|
FcGlobalCacheInfo *info)
|
|
|
|
|
{
|
|
|
|
|
if (!info->referenced)
|
|
|
|
|
{
|
|
|
|
|
info->referenced = FcTrue;
|
|
|
|
|
cache->referenced++;
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE_REF)
|
|
|
|
|
printf ("Reference %d %s\n", cache->referenced, info->file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Break a path into dir/base elements and compute the base hash
|
|
|
|
|
* and the dir length. This is shared between the functions
|
|
|
|
|
* which walk the file caches
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef struct _FcFilePathInfo {
|
|
|
|
|
const FcChar8 *dir;
|
|
|
|
|
int dir_len;
|
|
|
|
|
const FcChar8 *base;
|
|
|
|
|
unsigned int base_hash;
|
|
|
|
|
} FcFilePathInfo;
|
|
|
|
|
|
|
|
|
|
static FcFilePathInfo
|
|
|
|
|
FcFilePathInfoGet (const FcChar8 *path)
|
|
|
|
|
{
|
|
|
|
|
FcFilePathInfo i;
|
|
|
|
|
FcChar8 *slash;
|
|
|
|
|
|
|
|
|
|
slash = (FcChar8 *) strrchr ((const char *) path, '/');
|
|
|
|
|
if (slash)
|
|
|
|
|
{
|
|
|
|
|
i.dir = path;
|
|
|
|
|
i.dir_len = slash - path;
|
|
|
|
|
if (!i.dir_len)
|
|
|
|
|
i.dir_len = 1;
|
|
|
|
|
i.base = slash + 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
i.dir = (const FcChar8 *) ".";
|
|
|
|
|
i.dir_len = 1;
|
|
|
|
|
i.base = path;
|
|
|
|
|
}
|
|
|
|
|
i.base_hash = FcCacheHash (i.base);
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcGlobalCacheDir *
|
|
|
|
|
FcGlobalCacheDirGet (FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *dir,
|
|
|
|
|
int len,
|
|
|
|
|
FcBool create_missing)
|
|
|
|
|
{
|
|
|
|
|
unsigned int hash = FcCacheHash (dir);
|
|
|
|
|
FcGlobalCacheDir *d, **prev;
|
|
|
|
|
|
|
|
|
|
for (prev = &cache->ents[hash % FC_GLOBAL_CACHE_DIR_HASH_SIZE];
|
|
|
|
|
(d = *prev);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
prev = &(*prev)->next)
|
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (d->info.hash == hash && d->len == len &&
|
|
|
|
|
!strncmp ((const char *) d->info.file,
|
|
|
|
|
(const char *) dir, len))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!(d = *prev))
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
if (!create_missing)
|
|
|
|
|
return 0;
|
|
|
|
|
d = malloc (sizeof (FcGlobalCacheDir) + len + 1);
|
|
|
|
|
if (!d)
|
|
|
|
|
return 0;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + len + 1);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
d->next = *prev;
|
|
|
|
|
*prev = d;
|
|
|
|
|
d->info.hash = hash;
|
|
|
|
|
d->info.file = (FcChar8 *) (d + 1);
|
|
|
|
|
strncpy ((char *) d->info.file, (const char *) dir, len);
|
|
|
|
|
d->info.file[len] = '\0';
|
|
|
|
|
d->info.time = 0;
|
|
|
|
|
d->info.referenced = FcFalse;
|
|
|
|
|
d->len = len;
|
|
|
|
|
for (i = 0; i < FC_GLOBAL_CACHE_FILE_HASH_SIZE; i++)
|
|
|
|
|
d->ents[i] = 0;
|
|
|
|
|
d->subdirs = 0;
|
|
|
|
|
}
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FcGlobalCacheInfo *
|
|
|
|
|
FcGlobalCacheDirAdd (FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *dir,
|
|
|
|
|
time_t time,
|
|
|
|
|
FcBool replace)
|
|
|
|
|
{
|
|
|
|
|
FcGlobalCacheDir *d;
|
|
|
|
|
FcFilePathInfo i;
|
|
|
|
|
FcGlobalCacheSubdir *subdir;
|
|
|
|
|
FcGlobalCacheDir *parent;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Add this directory to the cache
|
|
|
|
|
*/
|
|
|
|
|
d = FcGlobalCacheDirGet (cache, dir, strlen ((const char *) dir), FcTrue);
|
|
|
|
|
if (!d)
|
|
|
|
|
return 0;
|
|
|
|
|
d->info.time = time;
|
|
|
|
|
i = FcFilePathInfoGet (dir);
|
|
|
|
|
/*
|
|
|
|
|
* Add this directory to the subdirectory list of the parent
|
|
|
|
|
*/
|
|
|
|
|
parent = FcGlobalCacheDirGet (cache, i.dir, i.dir_len, FcTrue);
|
|
|
|
|
if (!parent)
|
|
|
|
|
return 0;
|
|
|
|
|
subdir = malloc (sizeof (FcGlobalCacheSubdir) +
|
|
|
|
|
strlen ((const char *) i.base) + 1);
|
|
|
|
|
if (!subdir)
|
|
|
|
|
return 0;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir) +
|
|
|
|
|
strlen ((const char *) i.base) + 1);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
subdir->file = (FcChar8 *) (subdir + 1);
|
|
|
|
|
strcpy ((char *) subdir->file, (const char *) i.base);
|
|
|
|
|
subdir->next = parent->subdirs;
|
|
|
|
|
parent->subdirs = subdir;
|
|
|
|
|
return &d->info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
FcGlobalCacheDirDestroy (FcGlobalCacheDir *d)
|
|
|
|
|
{
|
|
|
|
|
FcGlobalCacheFile *f, *next;
|
|
|
|
|
int h;
|
|
|
|
|
FcGlobalCacheSubdir *s, *nexts;
|
|
|
|
|
|
|
|
|
|
for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
|
|
|
|
|
for (f = d->ents[h]; f; f = next)
|
|
|
|
|
{
|
|
|
|
|
next = f->next;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
|
|
|
|
|
strlen ((char *) f->info.file) + 1 +
|
|
|
|
|
strlen ((char *) f->name) + 1);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
free (f);
|
|
|
|
|
}
|
|
|
|
|
for (s = d->subdirs; s; s = nexts)
|
|
|
|
|
{
|
|
|
|
|
nexts = s->next;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir) +
|
|
|
|
|
strlen ((char *) s->file) + 1);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
free (s);
|
|
|
|
|
}
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + d->len + 1);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
free (d);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
|
FcGlobalCacheScanDir (FcFontSet *set,
|
|
|
|
|
FcStrSet *dirs,
|
|
|
|
|
FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *dir)
|
|
|
|
|
{
|
|
|
|
|
FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, dir,
|
|
|
|
|
strlen ((const char *) dir),
|
|
|
|
|
FcFalse);
|
|
|
|
|
FcGlobalCacheFile *f;
|
|
|
|
|
int h;
|
|
|
|
|
int dir_len;
|
|
|
|
|
FcGlobalCacheSubdir *subdir;
|
|
|
|
|
|
|
|
|
|
if (FcDebug() & FC_DBG_CACHE)
|
|
|
|
|
printf ("FcGlobalCacheScanDir %s\n", dir);
|
|
|
|
|
|
|
|
|
|
if (!d)
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf ("\tNo dir cache entry\n");
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!FcGlobalCacheCheckTime (&d->info))
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf ("\tdir cache entry time mismatch\n");
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dir_len = strlen ((const char *) dir);
|
|
|
|
|
for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
|
|
|
|
|
for (f = d->ents[h]; f; f = f->next)
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug() & FC_DBG_CACHEV)
|
|
|
|
|
printf ("FcGlobalCacheScanDir add file %s\n", f->info.file);
|
|
|
|
|
if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
|
|
|
|
|
f->info.file, f->name))
|
|
|
|
|
{
|
|
|
|
|
cache->broken = FcTrue;
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
FcGlobalCacheReferenced (cache, &f->info);
|
|
|
|
|
}
|
|
|
|
|
for (subdir = d->subdirs; subdir; subdir = subdir->next)
|
|
|
|
|
{
|
|
|
|
|
if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
|
|
|
|
|
subdir->file, FC_FONT_FILE_DIR))
|
|
|
|
|
{
|
|
|
|
|
cache->broken = FcTrue;
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcGlobalCacheReferenced (cache, &d->info);
|
|
|
|
|
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Locate the cache entry for a particular file
|
|
|
|
|
*/
|
|
|
|
|
FcGlobalCacheFile *
|
|
|
|
|
FcGlobalCacheFileGet (FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *file,
|
|
|
|
|
int id,
|
|
|
|
|
int *count)
|
|
|
|
|
{
|
|
|
|
|
FcFilePathInfo i = FcFilePathInfoGet (file);
|
|
|
|
|
FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, i.dir,
|
|
|
|
|
i.dir_len, FcFalse);
|
|
|
|
|
FcGlobalCacheFile *f, *match = 0;
|
|
|
|
|
int max = -1;
|
|
|
|
|
|
|
|
|
|
if (!d)
|
|
|
|
|
return 0;
|
|
|
|
|
for (f = d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE]; f; f = f->next)
|
|
|
|
|
{
|
|
|
|
|
if (f->info.hash == i.base_hash &&
|
|
|
|
|
!strcmp ((const char *) f->info.file, (const char *) i.base))
|
|
|
|
|
{
|
|
|
|
|
if (f->id == id)
|
|
|
|
|
match = f;
|
|
|
|
|
if (f->id > max)
|
|
|
|
|
max = f->id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (count)
|
|
|
|
|
*count = max;
|
|
|
|
|
return match;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Add a file entry to the cache
|
|
|
|
|
*/
|
|
|
|
|
static FcGlobalCacheInfo *
|
|
|
|
|
FcGlobalCacheFileAdd (FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *path,
|
|
|
|
|
int id,
|
|
|
|
|
time_t time,
|
|
|
|
|
const FcChar8 *name,
|
|
|
|
|
FcBool replace)
|
|
|
|
|
{
|
|
|
|
|
FcFilePathInfo i = FcFilePathInfoGet (path);
|
|
|
|
|
FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, i.dir,
|
|
|
|
|
i.dir_len, FcTrue);
|
|
|
|
|
FcGlobalCacheFile *f, **prev;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
int size;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
|
|
|
|
|
if (!d)
|
|
|
|
|
return 0;
|
|
|
|
|
for (prev = &d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE];
|
|
|
|
|
(f = *prev);
|
|
|
|
|
prev = &(*prev)->next)
|
|
|
|
|
{
|
|
|
|
|
if (f->info.hash == i.base_hash &&
|
|
|
|
|
f->id == id &&
|
|
|
|
|
!strcmp ((const char *) f->info.file, (const char *) i.base))
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (*prev)
|
|
|
|
|
{
|
|
|
|
|
if (!replace)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
return 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
f = *prev;
|
|
|
|
|
if (f->info.referenced)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
cache->referenced--;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
*prev = f->next;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
|
|
|
|
|
strlen ((char *) f->info.file) + 1 +
|
|
|
|
|
strlen ((char *) f->name) + 1);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
free (f);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
2002-09-01 00:17:32 +02:00
|
|
|
|
size = (sizeof (FcGlobalCacheFile) +
|
|
|
|
|
strlen ((char *) i.base) + 1 +
|
|
|
|
|
strlen ((char *) name) + 1);
|
|
|
|
|
f = malloc (size);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!f)
|
|
|
|
|
return 0;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemAlloc (FC_MEM_CACHE, size);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
f->next = *prev;
|
|
|
|
|
*prev = f;
|
|
|
|
|
f->info.hash = i.base_hash;
|
|
|
|
|
f->info.file = (FcChar8 *) (f + 1);
|
|
|
|
|
f->info.time = time;
|
|
|
|
|
f->info.referenced = FcFalse;
|
|
|
|
|
f->id = id;
|
|
|
|
|
f->name = f->info.file + strlen ((char *) i.base) + 1;
|
|
|
|
|
strcpy ((char *) f->info.file, (const char *) i.base);
|
|
|
|
|
strcpy ((char *) f->name, (const char *) name);
|
|
|
|
|
return &f->info;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCache *
|
|
|
|
|
FcGlobalCacheCreate (void)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCache *cache;
|
|
|
|
|
int h;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
cache = malloc (sizeof (FcGlobalCache));
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (!cache)
|
|
|
|
|
return 0;
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCache));
|
2002-07-28 12:50:59 +02:00
|
|
|
|
for (h = 0; h < FC_GLOBAL_CACHE_DIR_HASH_SIZE; h++)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
cache->ents[h] = 0;
|
|
|
|
|
cache->entries = 0;
|
|
|
|
|
cache->referenced = 0;
|
|
|
|
|
cache->updated = FcFalse;
|
2002-08-06 21:00:43 +02:00
|
|
|
|
cache->broken = FcFalse;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
return cache;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCacheDestroy (FcGlobalCache *cache)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCacheDir *d, *next;
|
|
|
|
|
int h;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
for (h = 0; h < FC_GLOBAL_CACHE_DIR_HASH_SIZE; h++)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
for (d = cache->ents[h]; d; d = next)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
next = d->next;
|
|
|
|
|
FcGlobalCacheDirDestroy (d);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCache));
|
2002-02-15 00:34:13 +01:00
|
|
|
|
free (cache);
|
|
|
|
|
}
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
/*
|
|
|
|
|
* Cache file syntax is quite simple:
|
|
|
|
|
*
|
|
|
|
|
* "file_name" id time "font_name" \n
|
|
|
|
|
*/
|
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
|
void
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCacheLoad (FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *cache_file)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FILE *f;
|
|
|
|
|
FcChar8 file_buf[8192], *file;
|
|
|
|
|
int id;
|
|
|
|
|
time_t time;
|
|
|
|
|
FcChar8 name_buf[8192], *name;
|
|
|
|
|
FcGlobalCacheInfo *info;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
f = fopen ((char *) cache_file, "r");
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (!f)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
cache->updated = FcFalse;
|
2002-02-15 07:01:28 +01:00
|
|
|
|
file = 0;
|
|
|
|
|
name = 0;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
while ((file = FcCacheReadString (f, file_buf, sizeof (file_buf))) &&
|
|
|
|
|
FcCacheReadInt (f, &id) &&
|
|
|
|
|
FcCacheReadTime (f, &time) &&
|
|
|
|
|
(name = FcCacheReadString (f, name_buf, sizeof (name_buf))))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (FcDebug () & FC_DBG_CACHEV)
|
|
|
|
|
printf ("FcGlobalCacheLoad \"%s\" \"%20.20s\"\n", file, name);
|
|
|
|
|
if (!FcStrCmp (name, FC_FONT_FILE_DIR))
|
|
|
|
|
info = FcGlobalCacheDirAdd (cache, file, time, FcFalse);
|
|
|
|
|
else
|
|
|
|
|
info = FcGlobalCacheFileAdd (cache, file, id, time, name, FcFalse);
|
|
|
|
|
if (!info)
|
|
|
|
|
cache->broken = FcTrue;
|
|
|
|
|
else
|
|
|
|
|
cache->entries++;
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE_REF)
|
|
|
|
|
printf ("FcGlobalCacheLoad entry %d %s\n",
|
|
|
|
|
cache->entries, file);
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (file != file_buf)
|
|
|
|
|
free (file);
|
|
|
|
|
if (name != name_buf)
|
|
|
|
|
free (name);
|
|
|
|
|
file = 0;
|
|
|
|
|
name = 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (file && file != file_buf)
|
|
|
|
|
free (file);
|
|
|
|
|
if (name && name != name_buf)
|
|
|
|
|
free (name);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
fclose (f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCacheUpdate (FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *file,
|
|
|
|
|
int id,
|
|
|
|
|
const FcChar8 *name)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
const FcChar8 *match;
|
|
|
|
|
struct stat statb;
|
|
|
|
|
FcGlobalCacheInfo *info;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
|
|
match = file;
|
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (stat ((char *) file, &statb) < 0)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
return FcFalse;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (S_ISDIR (statb.st_mode))
|
|
|
|
|
info = FcGlobalCacheDirAdd (cache, file, statb.st_mtime,
|
|
|
|
|
FcTrue);
|
|
|
|
|
else
|
|
|
|
|
info = FcGlobalCacheFileAdd (cache, file, id, statb.st_mtime,
|
|
|
|
|
name, FcTrue);
|
|
|
|
|
if (info)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCacheReferenced (cache, info);
|
|
|
|
|
cache->updated = FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
2002-07-28 12:50:59 +02:00
|
|
|
|
else
|
|
|
|
|
cache->broken = FcTrue;
|
|
|
|
|
return info != 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcGlobalCacheSave (FcGlobalCache *cache,
|
|
|
|
|
const FcChar8 *cache_file)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FILE *f;
|
|
|
|
|
int dir_hash, file_hash;
|
|
|
|
|
FcGlobalCacheDir *dir;
|
|
|
|
|
FcGlobalCacheFile *file;
|
|
|
|
|
FcAtomic *atomic;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
|
|
if (!cache->updated && cache->referenced == cache->entries)
|
|
|
|
|
return FcTrue;
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (cache->broken)
|
|
|
|
|
return FcFalse;
|
|
|
|
|
|
2002-03-03 01:19:43 +01:00
|
|
|
|
/* Set-UID programs can't safely update the cache */
|
|
|
|
|
if (getuid () != geteuid ())
|
|
|
|
|
return FcFalse;
|
|
|
|
|
|
2002-03-01 23:06:30 +01:00
|
|
|
|
atomic = FcAtomicCreate (cache_file);
|
|
|
|
|
if (!atomic)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail0;
|
2002-03-01 23:06:30 +01:00
|
|
|
|
if (!FcAtomicLock (atomic))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail1;
|
2002-03-01 23:06:30 +01:00
|
|
|
|
f = fopen ((char *) FcAtomicNewFile(atomic), "w");
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (!f)
|
|
|
|
|
goto bail2;
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
for (dir_hash = 0; dir_hash < FC_GLOBAL_CACHE_DIR_HASH_SIZE; dir_hash++)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
for (dir = cache->ents[dir_hash]; dir; dir = dir->next)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!dir->info.referenced)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
continue;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcCacheWriteString (f, dir->info.file))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcCacheWriteInt (f, 0))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcCacheWriteTime (f, dir->info.time))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcCacheWriteString (f, (FcChar8 *) FC_FONT_FILE_DIR))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('\n', f) == EOF)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail4;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
|
|
|
|
|
for (file_hash = 0; file_hash < FC_GLOBAL_CACHE_FILE_HASH_SIZE; file_hash++)
|
|
|
|
|
{
|
|
|
|
|
for (file = dir->ents[file_hash]; file; file = file->next)
|
|
|
|
|
{
|
|
|
|
|
if (!file->info.referenced)
|
|
|
|
|
continue;
|
|
|
|
|
if (!FcCacheWritePath (f, dir->info.file, file->info.file))
|
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail4;
|
|
|
|
|
if (!FcCacheWriteInt (f, file->id < 0 ? 0 : file->id))
|
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail4;
|
|
|
|
|
if (!FcCacheWriteTime (f, file->info.time))
|
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail4;
|
|
|
|
|
if (!FcCacheWriteString (f, file->name))
|
|
|
|
|
goto bail4;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('\n', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail4;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fclose (f) == EOF)
|
|
|
|
|
goto bail3;
|
|
|
|
|
|
2002-03-01 23:06:30 +01:00
|
|
|
|
if (!FcAtomicReplaceOrig (atomic))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
goto bail3;
|
|
|
|
|
|
2002-03-01 23:06:30 +01:00
|
|
|
|
FcAtomicUnlock (atomic);
|
|
|
|
|
FcAtomicDestroy (atomic);
|
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
|
cache->updated = FcFalse;
|
|
|
|
|
return FcTrue;
|
|
|
|
|
|
|
|
|
|
bail4:
|
|
|
|
|
fclose (f);
|
|
|
|
|
bail3:
|
2002-03-01 23:06:30 +01:00
|
|
|
|
FcAtomicDeleteNew (atomic);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
bail2:
|
2002-03-01 23:06:30 +01:00
|
|
|
|
FcAtomicUnlock (atomic);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
bail1:
|
2002-03-01 23:06:30 +01:00
|
|
|
|
FcAtomicDestroy (atomic);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
bail0:
|
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcDirCacheValid (const FcChar8 *dir)
|
2002-05-21 19:06:22 +02:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
|
2002-05-21 19:06:22 +02:00
|
|
|
|
struct stat file_stat, dir_stat;
|
|
|
|
|
|
|
|
|
|
if (stat ((char *) dir, &dir_stat) < 0)
|
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcStrFree (cache_file);
|
2002-05-21 19:06:22 +02:00
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|
|
|
|
|
if (stat ((char *) cache_file, &file_stat) < 0)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
{
|
|
|
|
|
FcStrFree (cache_file);
|
2002-05-21 19:06:22 +02:00
|
|
|
|
return FcFalse;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
}
|
|
|
|
|
FcStrFree (cache_file);
|
2002-05-21 19:06:22 +02:00
|
|
|
|
/*
|
|
|
|
|
* If the directory has been modified more recently than
|
|
|
|
|
* the cache file, the cache is not valid
|
|
|
|
|
*/
|
|
|
|
|
if (dir_stat.st_mtime - file_stat.st_mtime > 0)
|
|
|
|
|
return FcFalse;
|
|
|
|
|
return FcTrue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
FILE *f;
|
2002-02-15 07:01:28 +01:00
|
|
|
|
FcChar8 *base;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
int id;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
int dir_len;
|
|
|
|
|
FcChar8 file_buf[8192], *file;
|
2002-02-15 07:01:28 +01:00
|
|
|
|
FcChar8 name_buf[8192], *name;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
FcBool ret = FcFalse;
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!cache_file)
|
|
|
|
|
goto bail0;
|
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
printf ("FcDirCacheReadDir cache_file \"%s\"\n", cache_file);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
f = fopen ((char *) cache_file, "r");
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (!f)
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf (" no cache file\n");
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail1;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcDirCacheValid (dir))
|
2002-05-21 19:06:22 +02:00
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf (" cache file older than directory\n");
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail2;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
base = (FcChar8 *) strrchr ((char *) cache_file, '/');
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (!base)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail2;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
base++;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
dir_len = base - cache_file;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
file = 0;
|
|
|
|
|
name = 0;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
while ((file = FcCacheReadString (f, file_buf, sizeof (file_buf))) &&
|
|
|
|
|
FcCacheReadInt (f, &id) &&
|
|
|
|
|
(name = FcCacheReadString (f, name_buf, sizeof (name_buf))))
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcCacheFontSetAdd (set, dirs, cache_file, dir_len,
|
|
|
|
|
file, name))
|
|
|
|
|
goto bail3;
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (file != file_buf)
|
|
|
|
|
free (file);
|
|
|
|
|
if (name != name_buf)
|
|
|
|
|
free (name);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
file = name = 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf (" cache loaded\n");
|
|
|
|
|
|
|
|
|
|
ret = FcTrue;
|
2002-07-28 12:50:59 +02:00
|
|
|
|
bail3:
|
2002-02-15 07:01:28 +01:00
|
|
|
|
if (file && file != file_buf)
|
|
|
|
|
free (file);
|
|
|
|
|
if (name && name != name_buf)
|
|
|
|
|
free (name);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
bail2:
|
2002-02-15 00:34:13 +01:00
|
|
|
|
fclose (f);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
bail1:
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcStrFree (cache_file);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
bail0:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
|
/*
|
|
|
|
|
* return the path from the directory containing 'cache' to 'file'
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static const FcChar8 *
|
|
|
|
|
FcFileBaseName (const FcChar8 *cache, const FcChar8 *file)
|
|
|
|
|
{
|
|
|
|
|
const FcChar8 *cache_slash;
|
|
|
|
|
|
|
|
|
|
cache_slash = (const FcChar8 *) strrchr ((const char *) cache, '/');
|
|
|
|
|
if (cache_slash && !strncmp ((const char *) cache, (const char *) file,
|
|
|
|
|
(cache_slash + 1) - cache))
|
|
|
|
|
return file + ((cache_slash + 1) - cache);
|
|
|
|
|
return file;
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
|
FcBool
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
2002-02-15 00:34:13 +01:00
|
|
|
|
{
|
2002-07-28 12:50:59 +02:00
|
|
|
|
FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
FcPattern *font;
|
|
|
|
|
FILE *f;
|
2002-02-15 07:01:28 +01:00
|
|
|
|
FcChar8 *name;
|
|
|
|
|
const FcChar8 *file, *base;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
int n;
|
|
|
|
|
int id;
|
|
|
|
|
FcBool ret;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
FcStrList *list;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!cache_file)
|
|
|
|
|
goto bail0;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
|
f = fopen ((char *) cache_file, "w");
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (!f)
|
|
|
|
|
{
|
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf (" can't create \"%s\"\n", cache_file);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail1;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
|
|
|
|
|
|
list = FcStrListCreate (dirs);
|
|
|
|
|
if (!list)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail2;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
|
|
|
|
|
while ((dir = FcStrListNext (list)))
|
|
|
|
|
{
|
|
|
|
|
base = FcFileBaseName (cache_file, dir);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcCacheWriteString (f, base))
|
|
|
|
|
goto bail3;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
|
|
|
|
if (!FcCacheWriteInt (f, 0))
|
|
|
|
|
goto bail3;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
|
|
|
|
if (!FcCacheWriteString (f, FC_FONT_FILE_DIR))
|
|
|
|
|
goto bail3;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('\n', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
|
for (n = 0; n < set->nfont; n++)
|
|
|
|
|
{
|
|
|
|
|
font = set->fonts[n];
|
2002-02-19 08:50:44 +01:00
|
|
|
|
if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
base = FcFileBaseName (cache_file, file);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (FcDebug () & FC_DBG_CACHEV)
|
|
|
|
|
printf (" write file \"%s\"\n", base);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
if (!FcCacheWriteString (f, base))
|
|
|
|
|
goto bail3;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
|
|
|
|
if (!FcCacheWriteInt (f, id))
|
|
|
|
|
goto bail3;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC (' ', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
name = FcNameUnparse (font);
|
|
|
|
|
if (!name)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
|
|
|
|
ret = FcCacheWriteString (f, name);
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcStrFree (name);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (!ret)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
2002-08-19 21:32:05 +02:00
|
|
|
|
if (PUTC ('\n', f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail3;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
|
|
|
|
|
|
FcStrListDone (list);
|
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (fclose (f) == EOF)
|
2002-07-28 12:50:59 +02:00
|
|
|
|
goto bail1;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcStrFree (cache_file);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
|
if (FcDebug () & FC_DBG_CACHE)
|
|
|
|
|
printf (" cache written\n");
|
|
|
|
|
return FcTrue;
|
|
|
|
|
|
2002-07-28 12:50:59 +02:00
|
|
|
|
bail3:
|
2002-05-21 19:06:22 +02:00
|
|
|
|
FcStrListDone (list);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
bail2:
|
2002-02-15 00:34:13 +01:00
|
|
|
|
fclose (f);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
bail1:
|
2002-02-15 07:01:28 +01:00
|
|
|
|
unlink ((char *) cache_file);
|
2002-09-01 00:17:32 +02:00
|
|
|
|
FcStrFree (cache_file);
|
2002-07-28 12:50:59 +02:00
|
|
|
|
bail0:
|
2002-02-15 00:34:13 +01:00
|
|
|
|
return FcFalse;
|
|
|
|
|
}
|