2006-08-04 Keith Packard (keithp@keithp.com) reviewed by: plam
Make cache directories configurable. Simplify and correct some code which deals with per-directory caches.
This commit is contained in:
parent
62a4a8459a
commit
7410e40bd9
24
ChangeLog
24
ChangeLog
|
@ -1,3 +1,27 @@
|
|||
2006-08-04 Keith Packard (keithp@keithp.com)
|
||||
reviewed by: plam
|
||||
|
||||
* configure.in:
|
||||
* fonts.conf.in:
|
||||
* fonts.dtd:
|
||||
* fc-cache/fc-cache.c (scanDirs):
|
||||
* fontconfig/fontconfig.h:
|
||||
* src/Makefile.am:
|
||||
* src/fcint.h:
|
||||
* src/fccache.c (FcDirCacheValid, FcDirHasCurrentArch,
|
||||
FcDirCacheUnlink, FcDirCacheBasename,
|
||||
FcCacheReadDirs, FcDirCacheOpen, FcDirCacheRead,
|
||||
FcMakeDirectory, FcDirCacheWrite):
|
||||
* src/fccfg.c (FcConfigCreate, FcConfigDestroy, FcConfigAddCacheDir,
|
||||
FcConfigGetCacheDirs):
|
||||
* src/fcdir.c (FcDirScanConfig, FcDirSave):
|
||||
* src/fcinit.c (FcInitFallbackConfig):
|
||||
* src/fcxml.c (fcElementMap, FcEndElement):
|
||||
* test/fonts.conf.in, test/run-test.sh:
|
||||
|
||||
Make cache directories configurable. Simplify and correct
|
||||
some code which deals with per-directory caches.
|
||||
|
||||
2006-07-19 Jon Burgess (jburgess@uklinux.net)
|
||||
reviewed by: plam
|
||||
|
||||
|
|
22
configure.in
22
configure.in
|
@ -431,6 +431,22 @@ esac
|
|||
|
||||
AC_SUBST(FC_FONTPATH)
|
||||
|
||||
#
|
||||
# Set default cache directory path
|
||||
#
|
||||
AC_ARG_WITH(cache-dir, [ --with-cache-dir=DIR Use DIR to store cache files (default /var/cache/fontconfig)], fc_cachedir="$withval", fc_cachedir=yes)
|
||||
|
||||
case $fc_cachedir in
|
||||
no|yes)
|
||||
fc_cachedir=`eval echo "${localstatedir}/cache/"${PACKAGE}`
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(fc_cachedir)
|
||||
FC_CACHEDIR=${fc_cachedir}
|
||||
AC_SUBST(FC_CACHEDIR)
|
||||
|
||||
FC_FONTDATE=`LC_ALL=C date`
|
||||
|
||||
AC_SUBST(FC_FONTDATE)
|
||||
|
@ -516,12 +532,6 @@ fi
|
|||
|
||||
AC_SUBST(DOCDIR)
|
||||
|
||||
#
|
||||
# Make /var/cache/fontconfig directory available to source code
|
||||
#
|
||||
|
||||
pkgcachedir='${localstatedir}/cache/'${PACKAGE}
|
||||
AC_SUBST(pkgcachedir)
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
|
|
|
@ -230,7 +230,8 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
|||
ret++;
|
||||
continue;
|
||||
}
|
||||
if (!force && FcDirCacheValid (dir) && FcDirCacheHasCurrentArch (dir))
|
||||
if (!force && FcDirCacheValid (dir, config) &&
|
||||
FcDirCacheHasCurrentArch (dir, config))
|
||||
{
|
||||
if (verbose)
|
||||
printf ("skipping, %d fonts, %d dirs\n",
|
||||
|
@ -244,14 +245,12 @@ scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool
|
|||
|
||||
/* This is the only reason we can't combine
|
||||
* Valid w/HasCurrentArch... */
|
||||
if (!FcDirCacheValid (dir))
|
||||
if (!FcDirCacheValid (dir, config))
|
||||
if (!FcDirCacheUnlink (dir, config))
|
||||
ret++;
|
||||
|
||||
if (!FcDirSave (set, subdirs, dir))
|
||||
{
|
||||
if (!ret)
|
||||
fprintf (stderr, "Caches are currently saved to \"%s\"\n", PKGCACHEDIR);
|
||||
fprintf (stderr, "Can't save cache for \"%s\"\n", dir);
|
||||
ret++;
|
||||
}
|
||||
|
|
|
@ -276,10 +276,10 @@ typedef struct _FcStrSet FcStrSet;
|
|||
_FCFUNCPROTOBEGIN
|
||||
|
||||
FcBool
|
||||
FcDirCacheValid (const FcChar8 *cache_file);
|
||||
FcDirCacheValid (const FcChar8 *cache_file, FcConfig *config);
|
||||
|
||||
FcBool
|
||||
FcDirCacheHasCurrentArch (const FcChar8 *dir);
|
||||
FcDirCacheHasCurrentArch (const FcChar8 *dir, FcConfig *config);
|
||||
|
||||
FcBool
|
||||
FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config);
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
@FC_FONTPATH@
|
||||
<dir>~/.fonts</dir>
|
||||
|
||||
<!-- Font cache directory list -->
|
||||
|
||||
<cachedir>@FC_CACHEDIR@</cachedir>
|
||||
<cachedir>~/.fonts/fontconfig</cachedir>
|
||||
|
||||
<!--
|
||||
Accept deprecated 'mono' alias, replacing it with 'monospace'
|
||||
-->
|
||||
|
|
12
fonts.dtd
12
fonts.dtd
|
@ -22,6 +22,18 @@
|
|||
<!ELEMENT cache (#PCDATA)>
|
||||
<!ATTLIST cache xml:space (default|preserve) 'preserve'>
|
||||
|
||||
<!--
|
||||
Add a directory that is searched for font cache files.
|
||||
These hold per-directory cache data and are searched in
|
||||
order for each directory. When writing cache files, the first
|
||||
directory which allows the cache file to be created is used.
|
||||
|
||||
A leading '~' in a directory name is replaced with the users
|
||||
home directory path.
|
||||
-->
|
||||
<!ELEMENT cachedir (#PCDATA)>
|
||||
<!ATTLIST cachedir xml:space (default|preserve) 'preserve'>
|
||||
|
||||
<!--
|
||||
Reference another configuration file; note that this
|
||||
is another complete font configuration file and not
|
||||
|
|
|
@ -63,8 +63,6 @@ uninstall-ms-import-lib:
|
|||
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -DPKGCACHEDIR='"${pkgcachedir}"'
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/src \
|
||||
|
@ -72,6 +70,7 @@ INCLUDES = \
|
|||
$(LIBXML2_CFLAGS) \
|
||||
$(EXPAT_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
-DFC_CACHEDIR='"$(FC_CACHEDIR)"' \
|
||||
-DFONTCONFIG_PATH='"$(CONFDIR)"'
|
||||
|
||||
EXTRA_DIST = fontconfig.def.in
|
||||
|
|
321
src/fccache.c
321
src/fccache.c
|
@ -45,10 +45,7 @@
|
|||
#endif
|
||||
|
||||
static int
|
||||
FcDirCacheOpen (const FcChar8 * dir);
|
||||
|
||||
static char *
|
||||
FcDirCacheHashName (const FcChar8 * dir, int collisions);
|
||||
FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, FcChar8 **cache_path);
|
||||
|
||||
static off_t
|
||||
FcCacheSkipToArch (int fd, const char * arch);
|
||||
|
@ -748,7 +745,7 @@ FcCacheCopyOld (int fd, int fd_orig, off_t start)
|
|||
* cache, and the hashed location has an up-to-date cache. Oh well,
|
||||
* sucks to be you in that case! */
|
||||
FcBool
|
||||
FcDirCacheValid (const FcChar8 *dir)
|
||||
FcDirCacheValid (const FcChar8 *dir, FcConfig *config)
|
||||
{
|
||||
struct stat file_stat, dir_stat;
|
||||
int fd;
|
||||
|
@ -756,7 +753,7 @@ FcDirCacheValid (const FcChar8 *dir)
|
|||
if (stat ((char *) dir, &dir_stat) < 0)
|
||||
return FcFalse;
|
||||
|
||||
fd = FcDirCacheOpen (dir);
|
||||
fd = FcDirCacheOpen (config, dir, NULL);
|
||||
|
||||
if (fd < 0)
|
||||
return FcFalse;
|
||||
|
@ -782,7 +779,7 @@ FcDirCacheValid (const FcChar8 *dir)
|
|||
/* Assumes that the cache file in 'dir' exists.
|
||||
* Checks that the cache has the appropriate arch section. */
|
||||
FcBool
|
||||
FcDirCacheHasCurrentArch (const FcChar8 *dir)
|
||||
FcDirCacheHasCurrentArch (const FcChar8 *dir, FcConfig *config)
|
||||
{
|
||||
int fd;
|
||||
off_t current_arch_start;
|
||||
|
@ -790,7 +787,7 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir)
|
|||
FcCache metadata;
|
||||
char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1];
|
||||
|
||||
fd = FcDirCacheOpen (dir);
|
||||
fd = FcDirCacheOpen (config, dir, NULL);
|
||||
if (fd < 0)
|
||||
goto bail;
|
||||
|
||||
|
@ -827,57 +824,81 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir)
|
|||
return FcFalse;
|
||||
}
|
||||
|
||||
#define CACHEBASE_LEN (1 + 32 + sizeof (FC_CACHE_SUFFIX))
|
||||
|
||||
static const char bin2hex[] = { '0', '1', '2', '3',
|
||||
'4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b',
|
||||
'c', 'd', 'e', 'f' };
|
||||
|
||||
static FcChar8 *
|
||||
FcDirCacheBasename (const FcChar8 * dir, FcChar8 cache_base[CACHEBASE_LEN])
|
||||
{
|
||||
unsigned char hash[16];
|
||||
FcChar8 *hex_hash;
|
||||
int cnt;
|
||||
struct MD5Context ctx;
|
||||
|
||||
MD5Init (&ctx);
|
||||
MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir));
|
||||
|
||||
MD5Final (hash, &ctx);
|
||||
|
||||
cache_base[0] = '/';
|
||||
hex_hash = cache_base + 1;
|
||||
for (cnt = 0; cnt < 16; ++cnt)
|
||||
{
|
||||
hex_hash[2*cnt ] = bin2hex[hash[cnt] >> 4];
|
||||
hex_hash[2*cnt+1] = bin2hex[hash[cnt] & 0xf];
|
||||
}
|
||||
hex_hash[2*cnt] = 0;
|
||||
strcat ((char *) cache_base, FC_CACHE_SUFFIX);
|
||||
|
||||
return cache_base;
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
|
||||
{
|
||||
char *cache_hashed = 0;
|
||||
int fd, collisions;
|
||||
struct stat cache_stat;
|
||||
int fd = -1;
|
||||
FcChar8 *cache_hashed = NULL;
|
||||
FcChar8 cache_base[CACHEBASE_LEN];
|
||||
FcStrList *list;
|
||||
FcChar8 *cache_dir;
|
||||
char dir_buf[FC_MAX_FILE_LEN];
|
||||
|
||||
dir = FcConfigNormalizeFontDir (config, dir);
|
||||
|
||||
/* Remove any applicable hashed files. */
|
||||
fd = -1; collisions = 0;
|
||||
do
|
||||
FcDirCacheBasename (dir, cache_base);
|
||||
|
||||
list = FcStrListCreate (config->cacheDirs);
|
||||
if (!list)
|
||||
return FcFalse;
|
||||
|
||||
while ((cache_dir = FcStrListNext (list)))
|
||||
{
|
||||
if (cache_hashed)
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
|
||||
cache_hashed = FcDirCacheHashName (dir, collisions++);
|
||||
if (!cache_hashed)
|
||||
goto bail;
|
||||
|
||||
if (fd > 0)
|
||||
close (fd);
|
||||
fd = open(cache_hashed, O_RDONLY | O_BINARY);
|
||||
if (fd == -1)
|
||||
cache_hashed = FcStrPlus (cache_dir, cache_base);
|
||||
if (!cache_hashed)
|
||||
break;
|
||||
fd = open((char *) cache_hashed, O_RDONLY | O_BINARY);
|
||||
FcStrFree (cache_hashed);
|
||||
if (fd >= 0)
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
return FcTrue;
|
||||
if (FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) &&
|
||||
strcmp (dir_buf, (char *) dir) == 0)
|
||||
{
|
||||
close (fd);
|
||||
if (unlink ((char *) cache_hashed) < 0)
|
||||
break;
|
||||
} else
|
||||
close (fd);
|
||||
}
|
||||
|
||||
if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf))
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
goto bail;
|
||||
}
|
||||
} while (strcmp ((char *) dir_buf, (char *) dir) != 0);
|
||||
|
||||
close (fd);
|
||||
|
||||
if (stat ((char *) cache_hashed, &cache_stat) == 0 &&
|
||||
unlink ((char *)cache_hashed) != 0)
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
FcStrListDone (list);
|
||||
/* return FcFalse if something went wrong */
|
||||
if (cache_dir)
|
||||
return FcFalse;
|
||||
return FcTrue;
|
||||
|
||||
bail:
|
||||
return FcFalse;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -949,8 +970,8 @@ FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache,
|
|||
FcStrSetDestroy (subdirs);
|
||||
continue;
|
||||
}
|
||||
if (FcDirCacheValid (dir) &&
|
||||
FcDirCacheHasCurrentArch (dir) &&
|
||||
if (FcDirCacheValid (dir, config) &&
|
||||
FcDirCacheHasCurrentArch (dir, config) &&
|
||||
FcDirCacheRead (set, subdirs, dir, config))
|
||||
{
|
||||
/* if an old entry is found in the global cache, disable it */
|
||||
|
@ -1009,87 +1030,53 @@ FcCacheRead (FcConfig *config, FcGlobalCache * cache)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char bin2hex[] = { '0', '1', '2', '3',
|
||||
'4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b',
|
||||
'c', 'd', 'e', 'f' };
|
||||
|
||||
static char *
|
||||
FcDirCacheHashName (const FcChar8 * dir, int collisions)
|
||||
{
|
||||
unsigned char hash[16], hex_hash[33];
|
||||
char *cache_hashed;
|
||||
unsigned char uscore = '_';
|
||||
int cnt, i;
|
||||
FcChar8 *tmp;
|
||||
struct MD5Context ctx;
|
||||
|
||||
MD5Init (&ctx);
|
||||
MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir));
|
||||
|
||||
for (i = 0; i < collisions; i++)
|
||||
MD5Update (&ctx, &uscore, 1);
|
||||
|
||||
MD5Final (hash, &ctx);
|
||||
|
||||
for (cnt = 0; cnt < 16; ++cnt)
|
||||
{
|
||||
hex_hash[2*cnt] = bin2hex[hash[cnt] >> 4];
|
||||
hex_hash[2*cnt+1] = bin2hex[hash[cnt] & 0xf];
|
||||
}
|
||||
hex_hash[32] = 0;
|
||||
|
||||
tmp = FcStrPlus ((FcChar8 *)hex_hash, (FcChar8 *)FC_CACHE_SUFFIX);
|
||||
if (!tmp)
|
||||
return 0;
|
||||
|
||||
cache_hashed = (char *)FcStrPlus ((FcChar8 *)PKGCACHEDIR"/", tmp);
|
||||
free (tmp);
|
||||
|
||||
return cache_hashed;
|
||||
}
|
||||
|
||||
/* Opens the hashed name for cache_file.
|
||||
* This would fail in the unlikely event of a collision and subsequent
|
||||
* removal of the file which originally caused the collision. */
|
||||
/* Opens the cache file for 'dir' for reading.
|
||||
* This searches the list of cache dirs for the relevant cache file,
|
||||
* returning the first one found.
|
||||
*/
|
||||
static int
|
||||
FcDirCacheOpen (const FcChar8 *dir)
|
||||
FcDirCacheOpen (FcConfig *config, const FcChar8 *dir, FcChar8 **cache_path)
|
||||
{
|
||||
FcBool found;
|
||||
int fd = -1, collisions = 0;
|
||||
char *cache_hashed;
|
||||
int fd = -1;
|
||||
FcChar8 *cache_hashed = NULL;
|
||||
FcChar8 cache_base[CACHEBASE_LEN];
|
||||
FcStrList *list;
|
||||
FcChar8 *cache_dir;
|
||||
char dir_buf[FC_MAX_FILE_LEN];
|
||||
struct stat dir_stat;
|
||||
|
||||
if (stat ((char *)dir, &dir_stat) == -1)
|
||||
return -1;
|
||||
FcDirCacheBasename (dir, cache_base);
|
||||
|
||||
found = FcFalse;
|
||||
do
|
||||
list = FcStrListCreate (config->cacheDirs);
|
||||
if (!list)
|
||||
return -1;
|
||||
|
||||
while ((cache_dir = FcStrListNext (list)))
|
||||
{
|
||||
struct stat c;
|
||||
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
|
||||
cache_hashed = FcDirCacheHashName (dir, collisions++);
|
||||
if (!cache_hashed)
|
||||
return -1;
|
||||
|
||||
fd = open(cache_hashed, O_RDONLY | O_BINARY);
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
|
||||
if (fd == -1)
|
||||
cache_hashed = FcStrPlus (cache_dir, cache_base);
|
||||
if (!cache_hashed)
|
||||
break;
|
||||
if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) ||
|
||||
!strlen(dir_buf))
|
||||
fd = open((char *) cache_hashed, O_RDONLY | O_BINARY);
|
||||
if (fd >= 0)
|
||||
break;
|
||||
FcStrFree (cache_hashed);
|
||||
}
|
||||
FcStrListDone (list);
|
||||
|
||||
if (stat ((char *)dir_buf, &c) == -1)
|
||||
continue;
|
||||
|
||||
found = (c.st_ino == dir_stat.st_ino) && (c.st_dev == dir_stat.st_dev);
|
||||
} while (!found);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) ||
|
||||
strcmp (dir_buf, (char *) dir) != 0)
|
||||
{
|
||||
close (fd);
|
||||
FcStrFree (cache_hashed);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cache_path)
|
||||
*cache_path = cache_hashed;
|
||||
else
|
||||
FcStrFree (cache_hashed);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
@ -1104,7 +1091,7 @@ FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *
|
|||
off_t current_arch_start = 0;
|
||||
char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1];
|
||||
|
||||
fd = FcDirCacheOpen (dir);
|
||||
fd = FcDirCacheOpen (config, dir, NULL);
|
||||
if (fd < 0)
|
||||
goto bail;
|
||||
|
||||
|
@ -1278,56 +1265,77 @@ FcDirCacheProduce (FcFontSet *set, FcCache *metadata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static FcBool
|
||||
FcMakeDirectory (const FcChar8 *dir)
|
||||
{
|
||||
FcChar8 *parent;
|
||||
FcBool ret;
|
||||
|
||||
if (strlen ((char *) dir) == 0)
|
||||
return FcFalse;
|
||||
|
||||
parent = FcStrDirname (dir);
|
||||
if (!parent)
|
||||
return FcFalse;
|
||||
if (access ((char *) parent, W_OK|X_OK) == 0)
|
||||
ret = mkdir ((char *) dir, 0777) == 0;
|
||||
else if (access ((char *) parent, F_OK) == -1)
|
||||
ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0777) == 0);
|
||||
else
|
||||
ret = FcFalse;
|
||||
FcStrFree (parent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* write serialized state to the cache file */
|
||||
FcBool
|
||||
FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
||||
FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *config)
|
||||
{
|
||||
char *cache_hashed;
|
||||
FcChar8 cache_base[CACHEBASE_LEN];
|
||||
FcChar8 *cache_hashed;
|
||||
int fd, fd_orig, i, dirs_count;
|
||||
FcAtomic *atomic;
|
||||
FcCache metadata;
|
||||
off_t current_arch_start = 0, truncate_to;
|
||||
char dir_buf[FC_MAX_FILE_LEN];
|
||||
int collisions;
|
||||
|
||||
FcStrList *list;
|
||||
char *current_arch_machine_name, * header;
|
||||
void *current_dir_block = 0;
|
||||
FcChar8 *cache_dir;
|
||||
|
||||
dir = FcConfigNormalizeFontDir (FcConfigGetCurrent(), dir);
|
||||
if (!dir)
|
||||
return FcFalse;
|
||||
|
||||
/* 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 (dir, collisions++);
|
||||
if (!cache_hashed)
|
||||
goto bail0;
|
||||
/*
|
||||
* Check for an existing cache file and dump stuff in the same place
|
||||
*/
|
||||
fd = FcDirCacheOpen (config, dir, &cache_hashed);
|
||||
|
||||
if (fd > 0)
|
||||
close (fd);
|
||||
fd = open(cache_hashed, O_RDONLY | O_BINARY);
|
||||
if (fd == -1)
|
||||
break;
|
||||
if(!FcCacheReadString (fd, dir_buf, sizeof (dir_buf)) || !strlen(dir_buf))
|
||||
{
|
||||
close (fd);
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
continue;
|
||||
}
|
||||
if (fd >= 0)
|
||||
close (fd);
|
||||
|
||||
if (strcmp (dir_buf, (char *) dir) != 0)
|
||||
{
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (1);
|
||||
else {
|
||||
list = FcStrListCreate (config->cacheDirs);
|
||||
if (!list)
|
||||
return FcFalse;
|
||||
while ((cache_dir = FcStrListNext (list))) {
|
||||
if (access ((char *) cache_dir, W_OK|X_OK) == 0)
|
||||
break;
|
||||
/*
|
||||
* If the directory doesn't exist, try to create it
|
||||
*/
|
||||
if (access ((char *) cache_dir, F_OK) == -1) {
|
||||
if (FcMakeDirectory (cache_dir))
|
||||
break;
|
||||
}
|
||||
}
|
||||
FcStrListDone (list);
|
||||
if (!cache_dir)
|
||||
return FcFalse;
|
||||
FcDirCacheBasename (dir, cache_base);
|
||||
cache_hashed = FcStrPlus (cache_dir, cache_base);
|
||||
if (!cache_hashed)
|
||||
return FcFalse;
|
||||
}
|
||||
|
||||
current_dir_block = FcDirCacheProduce (set, &metadata);
|
||||
|
||||
|
@ -1455,7 +1463,6 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
|
|||
FcAtomicDestroy (atomic);
|
||||
bail1:
|
||||
FcStrFree ((FcChar8 *)cache_hashed);
|
||||
bail0:
|
||||
if (current_dir_block)
|
||||
free (current_dir_block);
|
||||
return FcFalse;
|
||||
|
|
28
src/fccfg.c
28
src/fccfg.c
|
@ -100,13 +100,17 @@ FcConfigCreate (void)
|
|||
if (!FcConfigSetCache (config, cache_dir))
|
||||
{
|
||||
FcStrFree (cache_dir);
|
||||
goto bail6;
|
||||
goto bail8;
|
||||
}
|
||||
FcStrFree (cache_dir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
config->cacheDirs = FcStrSetCreate ();
|
||||
if (!config->cacheDirs)
|
||||
goto bail9;
|
||||
|
||||
config->blanks = 0;
|
||||
|
||||
config->substPattern = 0;
|
||||
|
@ -120,6 +124,8 @@ FcConfigCreate (void)
|
|||
|
||||
return config;
|
||||
|
||||
bail9:
|
||||
FcStrFree (config->cache);
|
||||
bail8:
|
||||
FcFontSetDestroy (config->rejectPatterns);
|
||||
bail7:
|
||||
|
@ -226,6 +232,7 @@ FcConfigDestroy (FcConfig *config)
|
|||
|
||||
FcStrSetDestroy (config->configDirs);
|
||||
FcStrSetDestroy (config->fontDirs);
|
||||
FcStrSetDestroy (config->cacheDirs);
|
||||
FcStrSetDestroy (config->configFiles);
|
||||
FcStrSetDestroy (config->acceptGlobs);
|
||||
FcStrSetDestroy (config->rejectGlobs);
|
||||
|
@ -512,6 +519,25 @@ FcConfigGetFontDirs (FcConfig *config)
|
|||
return FcStrListCreate (config->fontDirs);
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcConfigAddCacheDir (FcConfig *config,
|
||||
const FcChar8 *d)
|
||||
{
|
||||
return FcStrSetAddFilename (config->cacheDirs, d);
|
||||
}
|
||||
|
||||
FcStrList *
|
||||
FcConfigGetCacheDirs (FcConfig *config)
|
||||
{
|
||||
if (!config)
|
||||
{
|
||||
config = FcConfigGetCurrent ();
|
||||
if (!config)
|
||||
return 0;
|
||||
}
|
||||
return FcStrListCreate (config->cacheDirs);
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcConfigAddConfigFile (FcConfig *config,
|
||||
const FcChar8 *f)
|
||||
|
|
|
@ -151,8 +151,8 @@ FcDirScanConfig (FcFontSet *set,
|
|||
if (cache && FcGlobalCacheReadDir (set, dirs, cache, (char *)dir, config))
|
||||
return FcTrue;
|
||||
|
||||
if (FcDirCacheValid (dir) &&
|
||||
FcDirCacheHasCurrentArch (dir) &&
|
||||
if (FcDirCacheValid (dir, config) &&
|
||||
FcDirCacheHasCurrentArch (dir, config) &&
|
||||
FcDirCacheRead (set, dirs, dir, config))
|
||||
return FcTrue;
|
||||
}
|
||||
|
@ -277,5 +277,5 @@ FcDirScan (FcFontSet *set,
|
|||
FcBool
|
||||
FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
|
||||
{
|
||||
return FcDirCacheWrite (set, dirs, dir);
|
||||
return FcDirCacheWrite (set, dirs, dir, FcConfigGetCurrent ());
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ FcInitFallbackConfig (void)
|
|||
goto bail0;
|
||||
if (!FcConfigAddDir (config, (FcChar8 *) FC_DEFAULT_FONTS))
|
||||
goto bail1;
|
||||
if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR))
|
||||
goto bail1;
|
||||
return config;
|
||||
|
||||
bail1:
|
||||
|
|
13
src/fcint.h
13
src/fcint.h
|
@ -388,6 +388,10 @@ struct _FcConfig {
|
|||
* of configured directories
|
||||
*/
|
||||
FcStrSet *fontDirs;
|
||||
/*
|
||||
* List of directories containing cache files.
|
||||
*/
|
||||
FcStrSet *cacheDirs;
|
||||
/*
|
||||
* Names of all of the configuration files used
|
||||
* to create this configuration
|
||||
|
@ -476,7 +480,7 @@ FcFontSet *
|
|||
FcCacheRead (FcConfig *config, FcGlobalCache * cache);
|
||||
|
||||
FcBool
|
||||
FcDirCacheWrite (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir);
|
||||
FcDirCacheWrite (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);
|
||||
|
||||
FcBool
|
||||
FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config);
|
||||
|
@ -508,6 +512,13 @@ FcBool
|
|||
FcConfigAddDir (FcConfig *config,
|
||||
const FcChar8 *d);
|
||||
|
||||
FcBool
|
||||
FcConfigAddCacheDir (FcConfig *config,
|
||||
const FcChar8 *d);
|
||||
|
||||
FcStrList *
|
||||
FcConfigGetCacheDirs (FcConfig *config);
|
||||
|
||||
FcBool
|
||||
FcConfigAddConfigFile (FcConfig *config,
|
||||
const FcChar8 *f);
|
||||
|
|
17
src/fcxml.c
17
src/fcxml.c
|
@ -285,6 +285,7 @@ typedef enum _FcElement {
|
|||
FcElementNone,
|
||||
FcElementFontconfig,
|
||||
FcElementDir,
|
||||
FcElementCacheDir,
|
||||
FcElementCache,
|
||||
FcElementInclude,
|
||||
FcElementConfig,
|
||||
|
@ -345,6 +346,7 @@ static const struct {
|
|||
} fcElementMap[] = {
|
||||
{ "fontconfig", FcElementFontconfig },
|
||||
{ "dir", FcElementDir },
|
||||
{ "cachedir", FcElementCacheDir },
|
||||
{ "cache", FcElementCache },
|
||||
{ "include", FcElementInclude },
|
||||
{ "config", FcElementConfig },
|
||||
|
@ -2053,6 +2055,21 @@ FcEndElement(void *userData, const XML_Char *name)
|
|||
}
|
||||
FcStrFree (data);
|
||||
break;
|
||||
case FcElementCacheDir:
|
||||
data = FcStrBufDone (&parse->pstack->str);
|
||||
if (!data)
|
||||
{
|
||||
FcConfigMessage (parse, FcSevereError, "out of memory");
|
||||
break;
|
||||
}
|
||||
if (!FcStrUsesHome (data) || FcConfigHome ())
|
||||
{
|
||||
if (!FcConfigAddCacheDir (parse->config, data))
|
||||
FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data);
|
||||
}
|
||||
FcStrFree (data);
|
||||
break;
|
||||
|
||||
case FcElementCache:
|
||||
data = FcStrBufDone (&parse->pstack->str);
|
||||
if (!data)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<fontconfig>
|
||||
<dir>@FONTDIR@</dir>
|
||||
<cache>@CACHEFILE@</cache>
|
||||
<cachedir>@CACHEDIR@</cachedir>
|
||||
</fontconfig>
|
||||
|
|
|
@ -3,6 +3,7 @@ TESTDIR=${srcdir-`pwd`}
|
|||
|
||||
FONTDIR=`pwd`/fonts
|
||||
CACHEFILE=`pwd`/fonts.cache
|
||||
CACHEDIR=`pwd`/cache.dir
|
||||
|
||||
ECHO=true
|
||||
|
||||
|
@ -39,7 +40,8 @@ dotest () {
|
|||
}
|
||||
|
||||
sed "s!@FONTDIR@!$FONTDIR!
|
||||
s!@CACHEFILE@!$CACHEFILE!" < $TESTDIR/fonts.conf.in > fonts.conf
|
||||
s!@CACHEFILE@!$CACHEFILE!
|
||||
s!@CACHEDIR@!$CACHEDIR!" < $TESTDIR/fonts.conf.in > fonts.conf
|
||||
|
||||
FONTCONFIG_FILE=`pwd`/fonts.conf
|
||||
export FONTCONFIG_FILE
|
||||
|
@ -89,4 +91,4 @@ mkdir $FONTDIR/a
|
|||
cp $FONT2 $FONTDIR/a
|
||||
check
|
||||
|
||||
rm -rf $FONTDIR $CACHEFILE $FONTCONFIG_FILE out
|
||||
rm -rf $FONTDIR $CACHEFILE $CACHEDIR $FONTCONFIG_FILE out
|
||||
|
|
Loading…
Reference in New Issue