So, I whacked fontconfig to no longer support saving cache files directly in the font directory. However, this means that users cannot have per-dir cache files unless they can write to the global cache directory. I suggest that the correct fix for this is to replace the single cache directory with a path that can include a home-relative directory. I''m not sure what the default should be; I''d like to stick it in ~/.fonts, but I''m concerned that this would cause extra scanning to happen after the cache is built. -- keith.packard@intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://lists.freedesktop.org/archives/fontconfig/attachments/20060427/d5670d5b/attachment.pgp
Keith Packard wrote:> So, I whacked fontconfig to no longer support saving cache files > directly in the font directory. However, this means that users cannot > have per-dir cache files unless they can write to the global cache > directory.I knew we forgot a case...> I suggest that the correct fix for this is to replace the single cache > directory with a path that can include a home-relative directory. I''m > not sure what the default should be; I''d like to stick it in ~/.fonts, > but I''m concerned that this would cause extra scanning to happen after > the cache is built.So, let''s see. Of course ~/.fonts needs to be first in the path so that stale cache files don''t kill you. Actually this makes this a bit messy, I guess, but perhaps not too bad. Initially: user fonts are in ~/.fonts. 1. no caches. fc-cache creates cache files for ~/.fonts and puts them in ~/.fonts 2. ok, now there are caches. but ~/.fonts is newer than the cache file. recreate caches. 3. repeat Is that what you''re worried about? Well, if we had ~/.fonts/cache that ought to take care of the above situation... pat
On Thu, 2006-04-27 at 17:44 -0700, Patrick Lam wrote:> I knew we forgot a case...Yeah, I figured we''d left something out.> Is that what you''re worried about? Well, if we had ~/.fonts/cache that > ought to take care of the above situation...Ah, nm, the solution is obvious -- have the dir scanning code skip the cache directory. Either by comparing path names, or by sticking a magic marker file in the cache directory. Don''t care which. I''ll see if I can''t code something up this evening. -- keith.packard@intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://lists.freedesktop.org/archives/fontconfig/attachments/20060427/cc3ed9d0/attachment.pgp
Keith Packard wrote:> On Thu, 2006-04-27 at 17:44 -0700, Patrick Lam wrote: > >> I knew we forgot a case... > > Yeah, I figured we''d left something out. > >> Is that what you''re worried about? Well, if we had ~/.fonts/cache that >> ought to take care of the above situation... > > Ah, nm, the solution is obvious -- have the dir scanning code skip the > cache directory. Either by comparing path names, or by sticking a magic > marker file in the cache directory. Don''t care which. > > I''ll see if I can''t code something up this evening.Right. That works best when you don''t stick cache files in ~/.fonts directly, of course. pat
On Thu, 2006-04-27 at 18:27 -0700, Patrick Lam wrote:> Right. That works best when you don''t stick cache files in ~/.fonts > directly, of course.Here''s just the cache dir piece of the patch, without the magic avoid-the-rescan stuff added. It''s a huge patch because it rewrites all of the cache file lookup code. Note that this *also* removes the collision avoidence code, which was busted. It should still identify collisions and fail to save the cache file in that case, which should be fairly harmless (just dumping stuff in the per-user cache). Note that MD5 is a strong hash, so this ''shouldn''t happen''. -keith Index: configure.in ==================================================================RCS file: /cvs/fontconfig/fontconfig/configure.in,v retrieving revision 1.66.2.12 diff -u -p -r1.66.2.12 configure.in --- configure.in 25 Apr 2006 15:33:07 -0000 1.66.2.12 +++ configure.in 28 Apr 2006 08:15:26 -0000 @@ -1,5 +1,5 @@ dnl -dnl $Id: configure.in,v 1.66.2.12 2006-04-25 15:33:07 plam Exp $ +dnl $Id: configure.in,v 1.66.2.12 2006/04/25 15:33:07 plam Exp $ dnl dnl Copyright ? 2003 Keith Packard dnl @@ -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 Index: fonts.conf.in ==================================================================RCS file: /cvs/fontconfig/fontconfig/fonts.conf.in,v retrieving revision 1.32.2.7 diff -u -p -r1.32.2.7 fonts.conf.in --- fonts.conf.in 15 Apr 2006 00:25:20 -0000 1.32.2.7 +++ fonts.conf.in 28 Apr 2006 08:18:21 -0000 @@ -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'' --> Index: fonts.dtd ==================================================================RCS file: /cvs/fontconfig/fontconfig/fonts.dtd,v retrieving revision 1.11 diff -u -p -r1.11 fonts.dtd --- fonts.dtd 4 Dec 2004 19:41:10 -0000 1.11 +++ fonts.dtd 28 Apr 2006 06:39:21 -0000 @@ -23,6 +23,18 @@ <!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 just a file included by the XML parser. Index: fc-cache/fc-cache.c ==================================================================RCS file: /cvs/fontconfig/fontconfig/fc-cache/fc-cache.c,v retrieving revision 1.17.2.21 diff -u -p -r1.17.2.21 fc-cache.c --- fc-cache/fc-cache.c 25 Apr 2006 05:57:41 -0000 1.17.2.21 +++ fc-cache/fc-cache.c 28 Apr 2006 07:47:05 -0000 @@ -230,7 +230,8 @@ scanDirs (FcStrList *list, FcConfig *con 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 *con /* 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++; } Index: fontconfig/fontconfig.h ==================================================================RCS file: /cvs/fontconfig/fontconfig/fontconfig/fontconfig.h,v retrieving revision 1.69.2.21 diff -u -p -r1.69.2.21 fontconfig.h --- fontconfig/fontconfig.h 19 Apr 2006 16:17:19 -0000 1.69.2.21 +++ fontconfig/fontconfig.h 28 Apr 2006 07:28:41 -0000 @@ -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); Index: src/Makefile.am ==================================================================RCS file: /cvs/fontconfig/fontconfig/src/Makefile.am,v retrieving revision 1.12.4.7 diff -u -p -r1.12.4.7 Makefile.am --- src/Makefile.am 25 Apr 2006 15:33:07 -0000 1.12.4.7 +++ src/Makefile.am 28 Apr 2006 04:54:09 -0000 @@ -1,5 +1,5 @@ # -# $Id: Makefile.am,v 1.12.4.7 2006-04-25 15:33:07 plam Exp $ +# $Id: Makefile.am,v 1.12.4.7 2006/04/25 15:33:07 plam Exp $ # # Copyright ? 2003 Keith Packard # @@ -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 Index: src/fccache.c ==================================================================RCS file: /cvs/fontconfig/fontconfig/src/fccache.c,v retrieving revision 1.23.4.88 diff -u -p -r1.23.4.88 fccache.c --- src/fccache.c 27 Apr 2006 07:11:44 -0000 1.23.4.88 +++ src/fccache.c 28 Apr 2006 08:05:19 -0000 @@ -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); @@ -746,7 +743,7 @@ FcCacheCopyOld (int fd, int fd_orig, off * 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; @@ -754,7 +751,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; @@ -780,7 +777,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; @@ -788,7 +785,7 @@ FcDirCacheHasCurrentArch (const FcChar8 FcCache metadata; char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1]; - fd = FcDirCacheOpen (dir); + fd = FcDirCacheOpen (config, dir, NULL); if (fd < 0) goto bail; @@ -825,57 +822,81 @@ FcDirCacheHasCurrentArch (const FcChar8 return FcFalse; } -FcBool -FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) +#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]) { - char *cache_hashed = 0; - int fd, collisions; - struct stat cache_stat; - char dir_buf[FC_MAX_FILE_LEN]; + unsigned char hash[16]; + FcChar8 *hex_hash; + int cnt; + struct MD5Context ctx; - dir = FcConfigNormalizeFontDir (config, dir); + MD5Init (&ctx); + MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir)); - /* Remove any applicable hashed files. */ - fd = -1; collisions = 0; - do + MD5Final (hash, &ctx); + + cache_base[0] = ''/''; + hex_hash = cache_base + 1; + for (cnt = 0; cnt < 16; ++cnt) { - if (cache_hashed) - FcStrFree ((FcChar8 *)cache_hashed); + 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); - cache_hashed = FcDirCacheHashName (dir, collisions++); - if (!cache_hashed) - goto bail; + return cache_base; +} - if (fd > 0) - close (fd); - fd = open(cache_hashed, O_RDONLY | O_BINARY); - if (fd == -1) - { - FcStrFree ((FcChar8 *)cache_hashed); - return FcTrue; - } +FcBool +FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) +{ + int fd = -1; + FcChar8 *cache_hashed = NULL; + FcChar8 cache_base[CACHEBASE_LEN]; + FcStrList *list; + FcChar8 *cache_dir; + char dir_buf[FC_MAX_FILE_LEN]; - 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); + dir = FcConfigNormalizeFontDir (config, dir); - close (fd); + FcDirCacheBasename (dir, cache_base); - if (stat ((char *) cache_hashed, &cache_stat) == 0 && - unlink ((char *)cache_hashed) != 0) + list = FcStrListCreate (config->cacheDirs); + if (!list) + return FcFalse; + + while ((cache_dir = FcStrListNext (list))) { - FcStrFree ((FcChar8 *)cache_hashed); - goto bail; + 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) + { + 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); + } } - - FcStrFree ((FcChar8 *)cache_hashed); + FcStrListDone (list); + /* return FcFalse if something went wrong */ + if (cache_dir) + return FcFalse; return FcTrue; - - bail: - return FcFalse; } static int @@ -947,8 +968,8 @@ FcCacheReadDirs (FcConfig * config, FcGl 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 */ @@ -1007,87 +1028,53 @@ FcCacheRead (FcConfig *config, FcGlobalC 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; } @@ -1102,7 +1089,7 @@ FcDirCacheRead (FcFontSet * set, FcStrSe 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; @@ -1276,56 +1263,77 @@ FcDirCacheProduce (FcFontSet *set, FcCac 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; - - 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; - } - close (fd); - - if (strcmp (dir_buf, (char *) dir) != 0) - { - FcStrFree ((FcChar8 *)cache_hashed); - continue; - } + /* + * Check for an existing cache file and dump stuff in the same place + */ + fd = FcDirCacheOpen (config, dir, &cache_hashed); - break; - } while (1); + if (fd >= 0) + close (fd); + 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); @@ -1453,7 +1461,6 @@ FcDirCacheWrite (FcFontSet *set, FcStrSe FcAtomicDestroy (atomic); bail1: FcStrFree ((FcChar8 *)cache_hashed); - bail0: if (current_dir_block) free (current_dir_block); return FcFalse; Index: src/fccfg.c ==================================================================RCS file: /cvs/fontconfig/fontconfig/src/fccfg.c,v retrieving revision 1.49.2.29 diff -u -p -r1.49.2.29 fccfg.c --- src/fccfg.c 25 Apr 2006 05:57:41 -0000 1.49.2.29 +++ src/fccfg.c 28 Apr 2006 04:49:28 -0000 @@ -22,9 +22,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include "fcint.h" #include <dirent.h> #include <sys/types.h> +#include "fcint.h" #if defined (_WIN32) && (defined (PIC) || defined (DLL_EXPORT)) #define STRICT @@ -100,13 +100,17 @@ FcConfigCreate (void) if (!FcConfigSetCache (config, cache_dir)) { FcStrFree (cache_dir); - goto bail6; + goto bail7; } 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); @@ -513,6 +520,25 @@ FcConfigGetFontDirs (FcConfig *config) } 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) { Index: src/fcdir.c ==================================================================RCS file: /cvs/fontconfig/fontconfig/src/fcdir.c,v retrieving revision 1.20.4.19 diff -u -p -r1.20.4.19 fcdir.c --- src/fcdir.c 10 Apr 2006 16:06:42 -0000 1.20.4.19 +++ src/fcdir.c 28 Apr 2006 07:34:56 -0000 @@ -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 ()); } Index: src/fcinit.c ==================================================================RCS file: /cvs/fontconfig/fontconfig/src/fcinit.c,v retrieving revision 1.12.4.7 diff -u -p -r1.12.4.7 fcinit.c --- src/fcinit.c 27 Apr 2006 07:54:07 -0000 1.12.4.7 +++ src/fcinit.c 28 Apr 2006 04:52:46 -0000 @@ -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: Index: src/fcint.h ==================================================================RCS file: /cvs/fontconfig/fontconfig/src/fcint.h,v retrieving revision 1.47.4.44 diff -u -p -r1.47.4.44 fcint.h --- src/fcint.h 27 Apr 2006 07:54:07 -0000 1.47.4.44 +++ src/fcint.h 28 Apr 2006 07:33:21 -0000 @@ -389,6 +389,10 @@ struct _FcConfig { */ 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); @@ -509,6 +513,13 @@ FcConfigAddDir (FcConfig *config, const FcChar8 *d); FcBool +FcConfigAddCacheDir (FcConfig *config, + const FcChar8 *d); + +FcStrList * +FcConfigGetCacheDirs (FcConfig *config); + +FcBool FcConfigAddConfigFile (FcConfig *config, const FcChar8 *f); Index: src/fcxml.c ==================================================================RCS file: /cvs/fontconfig/fontconfig/src/fcxml.c,v retrieving revision 1.37.4.22 diff -u -p -r1.37.4.22 fcxml.c --- src/fcxml.c 27 Apr 2006 07:54:07 -0000 1.37.4.22 +++ src/fcxml.c 28 Apr 2006 07:35:24 -0000 @@ -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_C } 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) Index: test/fonts.conf.in ==================================================================RCS file: /cvs/fontconfig/fontconfig/test/fonts.conf.in,v retrieving revision 1.1 diff -u -p -r1.1 fonts.conf.in --- test/fonts.conf.in 1 Mar 2003 05:54:42 -0000 1.1 +++ test/fonts.conf.in 28 Apr 2006 08:08:01 -0000 @@ -1,4 +1,5 @@ <fontconfig> <dir>@FONTDIR@</dir> <cache>@CACHEFILE@</cache> +<cachedir>@CACHEDIR@</cachedir> </fontconfig> Index: test/run-test.sh ==================================================================RCS file: /cvs/fontconfig/fontconfig/test/run-test.sh,v retrieving revision 1.3 diff -u -p -r1.3 run-test.sh --- test/run-test.sh 27 Oct 2003 10:44:13 -0000 1.3 +++ test/run-test.sh 28 Apr 2006 08:08:19 -0000 @@ -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 -- keith.packard@intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://lists.freedesktop.org/archives/fontconfig/attachments/20060428/5b5af386/attachment-0001.pgp
Behdad Esfahbod
2006-Apr-28 02:04 UTC
[Fontconfig] Sigh. What to do about per-user fonts...
On Fri, 28 Apr 2006, Keith Packard wrote:> diff -u -p -r1.3 run-test.sh > --- test/run-test.sh 27 Oct 2003 10:44:13 -0000 1.3 > +++ test/run-test.sh 28 Apr 2006 08:08:19 -0000 > @@ -3,6 +3,7 @@ TESTDIR=${srcdir-`pwd`} > > FONTDIR=`pwd`/fonts > CACHEFILE=`pwd`/fonts.cache > +CACHEDIR=`pwd`/cache.dir...> -rm -rf $FONTDIR $CACHEFILE $FONTCONFIG_FILE out > +rm -rf $FONTDIR $CACHEFILE $CACHEDIR $FONTCONFIG_FILE outI will put double quotes around all these variables, or it will make somebody mad when they ''make test'' fontconfig in a path containing spaces. --behdad http://behdad.org/ "Commandment Three says Do Not Kill, Amendment Two says Blood Will Spill" -- Dan Bern, "New American Language"
Keith Packard wrote:> On Thu, 2006-04-27 at 18:27 -0700, Patrick Lam wrote: > >> Right. That works best when you don''t stick cache files in ~/.fonts >> directly, of course. > > Here''s just the cache dir piece of the patch, without the magic > avoid-the-rescan stuff added. > > It''s a huge patch because it rewrites all of the cache file lookup code. > Note that this *also* removes the collision avoidence code, which was > busted. It should still identify collisions and fail to save the cache > file in that case, which should be fairly harmless (just dumping stuff > in the per-user cache). Note that MD5 is a strong hash, so this > ''shouldn''t happen''.I noticed one problem which occurs when you run fc-cache as root and have HOME set to a user directory. I''ll have more details (hopefully a fix) when I next have free time on Friday or something. Right now I''m preparing lecture notes... pat
On Wed, 2006-05-03 at 23:09 -0400, Patrick Lam wrote:> I noticed one problem which occurs when you run fc-cache as root and > have HOME set to a user directory. I''ll have more details (hopefully a > fix) when I next have free time on Friday or something. Right now I''m > preparing lecture notes...I''m not quite sure what to do about that; one option is to strip all ~ relative path names when getuid() != geteuid() from the font path, cache path and other configurable names. I was thinking that we already bailed on writing out cache files in this case though. In which case, the only issue is with sudo. One possible fix here is to use getpwuid (getuid()) instead of getenv ("HOME"). -- keith.packard@intel.com -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part Url : http://lists.freedesktop.org/archives/fontconfig/attachments/20060504/90db61f5/attachment.pgp
Keith Packard wrote:> On Wed, 2006-05-03 at 23:09 -0400, Patrick Lam wrote: > >> I noticed one problem which occurs when you run fc-cache as root and >> have HOME set to a user directory. I''ll have more details (hopefully a >> fix) when I next have free time on Friday or something. Right now I''m >> preparing lecture notes... > > I''m not quite sure what to do about that; one option is to strip all ~ > relative path names when getuid() != geteuid() from the font path, cache > path and other configurable names. > > I was thinking that we already bailed on writing out cache files in this > case though. In which case, the only issue is with sudo. One possible > fix here is to use getpwuid (getuid()) instead of getenv ("HOME").We don''t write global cache files in the getuid() != geteuid() case, but we do write local cache files. So getpwuid(getuid()) seems like it should work. I''ve looked at the patch and it seems generally correct to me. Two questions: 1. Why did you move the #include "fcint.h" to the end of the include-block in fccfg.c? We fixed some problems on Windows by putting it consistently at the beginning of the include block. There''s a bug about that somewhere. 2. Do we still need to do the check for mis-named cache files in DirCacheUnlink? It seems like it wouldn''t be a bad idea to unconditionally blow away anything that''s in the way of what we''re trying to unlink. The patch also appears to work on my system, too, for what that''s worth. pat
Frederic Crozat
2006-May-10 01:23 UTC
[Fontconfig] Sigh. What to do about per-user fonts...
Le lundi 08 mai 2006 ? 13:38 -0400, Patrick Lam a ?crit :> Keith Packard wrote: > > On Wed, 2006-05-03 at 23:09 -0400, Patrick Lam wrote: > > > >> I noticed one problem which occurs when you run fc-cache as root and > >> have HOME set to a user directory. I''ll have more details (hopefully a > >> fix) when I next have free time on Friday or something. Right now I''m > >> preparing lecture notes... > > > > I''m not quite sure what to do about that; one option is to strip all ~ > > relative path names when getuid() != geteuid() from the font path, cache > > path and other configurable names. > > > > I was thinking that we already bailed on writing out cache files in this > > case though. In which case, the only issue is with sudo. One possible > > fix here is to use getpwuid (getuid()) instead of getenv ("HOME"). > > We don''t write global cache files in the getuid() != geteuid() case, but > we do write local cache files. So getpwuid(getuid()) seems like it > should work.Just a side note : The getpwuid(getuid()) would be way much better than getenv("HOME"), which used to be in older version of fontconfig and caused crashes when HOME was not set (we had that problem at installation time with old Mandriva Linux releases. -- Frederic Crozat <fcrozat@mandriva.com> Mandriva