]> git.wh0rd.org Git - fontconfig.git/commitdiff
Store font directory mtime in cache file.
authorKeith Packard <keithp@koto.keithp.com>
Thu, 18 Oct 2007 11:13:51 +0000 (04:13 -0700)
committerKeith Packard <keithp@koto.keithp.com>
Thu, 18 Oct 2007 11:13:51 +0000 (04:13 -0700)
Instead of relying on mtime ordering between a directory and its associated
cache file, write the directory mtime into the cache file itself. This makes
cache file checks more reliable across file systems.

This change is made in a way that old programs can use new cache files, but
new programs will need new cache files.

fc-arch/fcarch.tmpl.h
src/fccache.c
src/fcdir.c
src/fcint.h

index 0843a64e432ac15db65cb412026b35be90912371..96dccb4aa3184e78352f2b694ee220d5754cda7e 100644 (file)
 @@@ use something reasonable and don't include any spaces
 @@@
 @@@ name    endian   char     char*    int      intptr_t Pattern  EltPtr   Elt *    Elt      ObjPtr   VLPtr    Value    Binding  VL *     CharSet  Leaf**   Char16 * Char16   Leaf     Char32   Cache
-x86        78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-x86-64     78563412_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000030
-ppc        12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-ppc64      12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000030
-m68k       12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-mipsel     78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_0000001c
-sparc64     12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000030
+x86        78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+x86-64     78563412_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000038
+ppc        12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+ppc64      12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000038
+m68k       12345678_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_0000000c_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+mipsel     78563412_00000001_00000004_00000004_00000004_00000010_00000004_00000004_00000008_00000004_00000004_00000010_00000004_00000004_00000010_00000004_00000004_00000002_00000020_00000004_00000020
+sparc64     12345678_00000001_00000008_00000004_00000008_00000018_00000008_00000008_00000010_00000004_00000008_00000010_00000004_00000008_00000018_00000008_00000008_00000002_00000020_00000004_00000038
index 9e8819cbdc2d111d833353e329e18d635e74e31e..42c70821748819cd7dbcdd932aed2c1884d24907 100644 (file)
@@ -47,7 +47,7 @@ struct MD5Context {
 };
 
 static void MD5Init(struct MD5Context *ctx);
-static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len);
+static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len);
 static void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
 static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]);
 
@@ -67,7 +67,7 @@ FcDirCacheBasename (const FcChar8 * dir, FcChar8 cache_base[CACHEBASE_LEN])
     struct MD5Context  ctx;
 
     MD5Init (&ctx);
-    MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir));
+    MD5Update (&ctx, (const unsigned char *)dir, strlen ((const char *) dir));
 
     MD5Final (hash, &ctx);
 
@@ -136,7 +136,8 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat)
  */
 static FcBool
 FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, 
-                  FcBool (*callback) (int fd, struct stat *stat, void *closure),
+                  FcBool (*callback) (int fd, struct stat *fd_stat,
+                                      struct stat *dir_stat, void *closure),
                   void *closure, FcChar8 **cache_file_ret)
 {
     int                fd = -1;
@@ -162,20 +163,16 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
            break;
         fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
         if (fd >= 0) {
-           if (dir_stat.st_mtime <= file_stat.st_mtime)
+           ret = (*callback) (fd, &file_stat, &dir_stat, closure);
+           close (fd);
+           if (ret)
            {
-               ret = (*callback) (fd, &file_stat, closure);
-               if (ret)
-               {
-                   if (cache_file_ret)
-                       *cache_file_ret = cache_hashed;
-                   else
-                       FcStrFree (cache_hashed);
-                   close (fd);
-                   break;
-               }
+               if (cache_file_ret)
+                   *cache_file_ret = cache_hashed;
+               else
+                   FcStrFree (cache_hashed);
+               break;
            }
-           close (fd);
        }
        FcStrFree (cache_hashed);
     }
@@ -425,11 +422,28 @@ FcCacheFini (void)
     assert (fcCacheMaxLevel == 0);
 }
 
+static FcBool
+FcCacheTimeValid (FcCache *cache, struct stat *dir_stat)
+{
+    struct stat        dir_static;
+
+    if (!dir_stat)
+    {
+       if (stat ((const char *) FcCacheDir (cache), &dir_static) < 0)
+           return FcFalse;
+       dir_stat = &dir_static;
+    }
+    if (FcDebug () & FC_DBG_CACHE)
+       printf ("FcCacheTimeValid dir \"%s\" cache time %d dir time %d\n",
+               FcCacheDir (cache), cache->mtime, (int) dir_stat->st_mtime);
+    return cache->mtime == (int) dir_stat->st_mtime;
+}
+
 /*
  * Map a cache file into memory
  */
 static FcCache *
-FcDirCacheMapFd (int fd, struct stat *fd_stat)
+FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat)
 {
     FcCache    *cache;
     FcBool     allocated = FcFalse;
@@ -478,7 +492,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat)
     if (cache->magic != FC_CACHE_MAGIC_MMAP || 
        cache->version < FC_CACHE_CONTENT_VERSION ||
        cache->size != fd_stat->st_size ||
-       !FcCacheInsert (cache, fd_stat))
+       !FcCacheInsert (cache, fd_stat) ||
+       !FcCacheTimeValid (cache, dir_stat))
     {
        if (allocated)
            free (cache);
@@ -516,9 +531,9 @@ FcDirCacheUnload (FcCache *cache)
 }
 
 static FcBool
-FcDirCacheMapHelper (int fd, struct stat *fd_stat, void *closure)
+FcDirCacheMapHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
 {
-    FcCache *cache = FcDirCacheMapFd (fd, fd_stat);
+    FcCache *cache = FcDirCacheMapFd (fd, fd_stat, dir_stat);
 
     if (!cache)
        return FcFalse;
@@ -547,7 +562,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
     fd = FcDirCacheOpenFile (cache_file, file_stat);
     if (fd < 0)
        return NULL;
-    cache = FcDirCacheMapFd (fd, file_stat);
+    cache = FcDirCacheMapFd (fd, file_stat, NULL);
     close (fd);
     return cache;
 }
@@ -557,7 +572,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat)
  * the magic number and the size field
  */
 static FcBool
-FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure)
+FcDirCacheValidateHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure)
 {
     FcBool  ret = FcTrue;
     FcCache    c;
@@ -570,6 +585,8 @@ FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure)
        ret = FcFalse;
     else if (fd_stat->st_size != c.size)
        ret = FcFalse;
+    else if (c.mtime != (int) dir_stat->st_mtime)
+       ret = FcFalse;
     return ret;
 }
 
@@ -597,7 +614,7 @@ FcDirCacheValid (const FcChar8 *dir)
  * Build a cache structure from the given contents
  */
 FcCache *
-FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs)
 {
     FcSerialize        *serialize = FcSerializeCreate ();
     FcCache *cache;
@@ -645,6 +662,7 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs)
     cache->magic = FC_CACHE_MAGIC_ALLOC;
     cache->version = FC_CACHE_CONTENT_VERSION;
     cache->size = serialize->size;
+    cache->mtime = (int) dir_stat->st_mtime;
 
     /*
      * Serialize directory name
@@ -931,7 +949,7 @@ static void MD5Init(struct MD5Context *ctx)
  * Update context to reflect the concatenation of another buffer full
  * of bytes.
  */
-static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len)
+static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len)
 {
     FcChar32 t;
 
index e9e9d197c57a444801680afe5ce1c93213fe8707..48755deb244cb708d7133126c92e3cd5da93964f 100644 (file)
@@ -146,6 +146,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     int                        i;
     FcBlanks           *blanks = FcConfigGetBlanks (config);
     FcCache            *cache = NULL;
+    struct stat                dir_stat;
 
     if (FcDebug () & FC_DBG_FONTSET)
        printf ("cache scan dir %s\n", dir);
@@ -174,6 +175,11 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
            ret = FcFalse;
        goto bail_1;
     }
+    if (stat ((char *) dir, &dir_stat) < 0)
+    {
+       ret = FcFalse;
+       goto bail_1;
+    }
 
     set = FcFontSetCreate();
     if (!set) 
@@ -218,7 +224,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
     /*
      * Build the cache object
      */
-    cache = FcDirCacheBuild (set, dir, dirs);
+    cache = FcDirCacheBuild (set, dir, &dir_stat, dirs);
     if (!cache)
        goto bail3;
     
index 4ab4a74906a77fb6087ce73ee56af314018c17d4..73bf875c1f483be5290ce6ab9d53f9043bdd538a 100644 (file)
@@ -322,6 +322,7 @@ struct _FcCache {
     intptr_t   dirs;               /* offset to subdirs */
     int                dirs_count;         /* number of subdir strings */
     intptr_t   set;                /* offset to font set */
+    int                mtime;              /* low bits of directory mtime */
 };
 
 #undef FcCacheDir
@@ -408,7 +409,7 @@ typedef struct _FcCaseFold {
 
 #define FC_CACHE_MAGIC_MMAP        0xFC02FC04
 #define FC_CACHE_MAGIC_ALLOC       0xFC02FC05
-#define FC_CACHE_CONTENT_VERSION    1
+#define FC_CACHE_CONTENT_VERSION    2
 
 struct _FcAtomic {
     FcChar8    *file;          /* original file name */
@@ -503,7 +504,7 @@ FcPrivate FcCache *
 FcDirCacheScan (const FcChar8 *dir, FcConfig *config);
 
 FcPrivate FcCache *
-FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs);
+FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs);
 
 FcPrivate FcBool
 FcDirCacheWrite (FcCache *cache, FcConfig *config);