]> git.wh0rd.org - fontconfig.git/blobdiff - src/fccache.c
Merge with HEAD and finish the GCC 4 cleanups (no more warnings!)
[fontconfig.git] / src / fccache.c
index 6b6b8e36c54614b7aca380ffc1d748a1ca60cad8..1f530652f348a0d204d61c95458bdd3cbbf6d641 100644 (file)
@@ -2,6 +2,7 @@
  * $RCSId: xc/lib/fontconfig/src/fccache.c,v 1.12 2002/08/22 07:36:44 keithp Exp $
  *
  * Copyright © 2000 Keith Packard
+ * Copyright © 2005 Patrick Lam
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -46,7 +47,7 @@ static FcBool
 FcDirCacheConsume (int fd, FcFontSet *set);
 
 static FcBool
-FcDirCacheRead (FcFontSet * set, const FcChar8 *dir);
+FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir);
 
 static int
 FcCacheNextOffset(off_t w);
@@ -59,8 +60,8 @@ FcCacheHaveBank (int bank);
 
 #define FC_DBG_CACHE_REF    1024
 
-static FcChar8 *
-FcCacheReadString (int fd, FcChar8 *dest, int len)
+static char *
+FcCacheReadString (int fd, char *dest, int len)
 {
     FcChar8    c;
     FcBool     escape;
@@ -68,7 +69,7 @@ FcCacheReadString (int fd, FcChar8 *dest, int len)
     int                i;
 
     if (len == 0)
-       return FcFalse;
+       return 0;
     
     size = len;
     i = 0;
@@ -100,7 +101,7 @@ FcCacheReadString (int fd, FcChar8 *dest, int len)
 }
 
 static FcBool
-FcCacheWriteString (int fd, const FcChar8 *chars)
+FcCacheWriteString (int fd, const char *chars)
 {
     if (write (fd, chars, strlen(chars)+1) != strlen(chars)+1)
        return FcFalse;
@@ -147,14 +148,20 @@ FcGlobalCacheDestroy (FcGlobalCache *cache)
 
 void
 FcGlobalCacheLoad (FcGlobalCache    *cache,
+                   FcStrSet        *staleDirs,
                   const FcChar8    *cache_file)
 {
-    FcChar8            name_buf[8192];
+    char               name_buf[8192];
     FcGlobalCacheDir   *d, *next;
     char               * current_arch_machine_name;
     char               candidate_arch_machine_name[MACHINE_SIGNATURE_SIZE + 9];
     off_t              current_arch_start;
 
+    struct stat        cache_stat, dir_stat;
+
+    if (stat ((char *) cache_file, &cache_stat) < 0)
+        return;
+
     cache->fd = open ((char *) cache_file, O_RDONLY);
     if (cache->fd == -1)
        return;
@@ -168,16 +175,30 @@ FcGlobalCacheLoad (FcGlobalCache    *cache,
         goto bail0;
 
     lseek (cache->fd, current_arch_start, SEEK_SET);
-    if (FcCacheReadString (cache->fd, candidate_arch_machine_name, 
-                          sizeof (candidate_arch_machine_name)) == 0)
+    FcCacheReadString (cache->fd, candidate_arch_machine_name, 
+                       sizeof (candidate_arch_machine_name));
+    if (strlen(candidate_arch_machine_name) == 0)
        goto bail0;
 
     while (1) 
     {
+       off_t targ;
+
        FcCacheReadString (cache->fd, name_buf, sizeof (name_buf));
        if (!strlen(name_buf))
            break;
 
+        if (stat ((char *) name_buf, &dir_stat) < 0 || 
+            dir_stat.st_mtime > cache_stat.st_mtime)
+        {
+            FcCache md;
+
+            FcStrSetAdd (staleDirs, FcStrCopy ((FcChar8 *)name_buf));
+            read (cache->fd, &md, sizeof (FcCache));
+            lseek (cache->fd, FcCacheNextOffset (lseek(cache->fd, 0, SEEK_CUR)) + md.count, SEEK_SET);
+            continue;
+        }
+
        d = malloc (sizeof (FcGlobalCacheDir));
        if (!d)
            goto bail1;
@@ -185,11 +206,14 @@ FcGlobalCacheLoad (FcGlobalCache    *cache,
        d->next = cache->dirs;
        cache->dirs = d;
 
-       d->name = FcStrCopy (name_buf);
+       d->name = (char *)FcStrCopy ((FcChar8 *)name_buf);
        d->ent = 0;
        d->offset = lseek (cache->fd, 0, SEEK_CUR);
-       read (cache->fd, &d->metadata, sizeof (FcCache));
-       lseek (cache->fd, d->metadata.count, SEEK_CUR);
+       if (read (cache->fd, &d->metadata, sizeof (FcCache)) != sizeof (FcCache))
+           goto bail1;
+       targ = FcCacheNextOffset (lseek(cache->fd, 0, SEEK_CUR)) + d->metadata.count;
+       if (lseek (cache->fd, targ, SEEK_SET) != targ)
+           goto bail1;
     }
     return;
 
@@ -201,37 +225,38 @@ FcGlobalCacheLoad (FcGlobalCache    *cache,
     }
     cache->dirs = 0;
  bail0:
-    free (current_arch_machine_name);
     close (cache->fd);
     cache->fd = -1;
     return;
 }
 
 FcBool
-FcGlobalCacheReadDir (FcFontSet *set, FcStrSet *dirs, FcGlobalCache * cache, const FcChar8 *dir, FcConfig *config)
+FcGlobalCacheReadDir (FcFontSet *set, FcStrSet *dirs, FcGlobalCache * cache, const char *dir, FcConfig *config)
 {
     FcGlobalCacheDir *d;
+    FcBool ret = FcFalse;
 
     if (cache->fd == -1)
        return FcFalse;
 
     for (d = cache->dirs; d; d = d->next)
     {
-       if (strcmp (d->name, dir) == 0)
+       if (strncmp (d->name, dir, strlen(dir)) == 0)
        {
            lseek (cache->fd, d->offset, SEEK_SET);
            if (!FcDirCacheConsume (cache->fd, set))
                return FcFalse;
-           return FcTrue;
+            if (strcmp (d->name, dir) == 0)
+               ret = FcTrue;
        }
     }
 
-    return FcFalse;
+    return ret;
 }
 
 FcBool
 FcGlobalCacheUpdate (FcGlobalCache  *cache,
-                    const FcChar8  *name,
+                    const char     *name,
                     FcFontSet      *set)
 {
     FcGlobalCacheDir * d;
@@ -256,7 +281,7 @@ FcGlobalCacheUpdate (FcGlobalCache  *cache,
 
     cache->updated = FcTrue;
 
-    d->name = FcStrCopy (name);
+    d->name = (char *)FcStrCopy ((FcChar8 *)name);
     d->ent = FcDirCacheProduce (set, &d->metadata);
     d->offset = 0;
     return FcTrue;
@@ -303,7 +328,11 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
     if (ftruncate (fd, current_arch_start) == -1)
        goto bail2;
 
-    truncate_to = current_arch_start;
+    header = malloc (10 + strlen (current_arch_machine_name));
+    if (!header)
+       goto bail1;
+
+    truncate_to = current_arch_start + strlen(current_arch_machine_name) + 11;
     for (dir = cache->dirs; dir; dir = dir->next)
     {
        truncate_to += strlen(dir->name) + 1;
@@ -312,9 +341,7 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
        truncate_to += dir->metadata.count;
     }
     truncate_to -= current_arch_start;
-    header = malloc (10 + strlen (current_arch_machine_name));
-    if (!header)
-       goto bail1;
+
     sprintf (header, "%8x ", (int)truncate_to);
     strcat (header, current_arch_machine_name);
     if (!FcCacheWriteString (fd, header))
@@ -326,7 +353,7 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
         {
             FcCacheWriteString (fd, dir->name);
             write (fd, &dir->metadata, sizeof(FcCache));
-            lseek (fd, FcCacheNextOffset (lseek(fd, 0, SEEK_END)), SEEK_SET);
+            lseek (fd, FcCacheNextOffset (lseek(fd, 0, SEEK_CUR)), SEEK_SET);
             write (fd, dir->ent, dir->metadata.count);
             free (dir->ent);
         }
@@ -383,13 +410,19 @@ FcCacheSkipToArch (int fd, const char * arch)
     {
        long bs;
 
-       lseek (fd, current_arch_start, SEEK_SET);
+       if (lseek (fd, current_arch_start, SEEK_SET) != current_arch_start)
+            return -1;
+
        if (FcCacheReadString (fd, candidate_arch_machine_name_count, 
                                sizeof (candidate_arch_machine_name_count)) == 0)
             return -1;
        if (!strlen(candidate_arch_machine_name_count))
            return -1;
        bs = strtol(candidate_arch_machine_name_count, &candidate_arch, 16);
+
+       if (!bs || bs < strlen (candidate_arch_machine_name_count))
+           return -1;
+
        candidate_arch++; /* skip leading space */
 
        if (strcmp (candidate_arch, arch)==0)
@@ -478,8 +511,6 @@ static int
 FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache, 
                 FcStrList *list, FcFontSet * set)
 {
-    DIR                        *d;
-    struct dirent      *e;
     int                        ret = 0;
     FcChar8            *dir;
     FcChar8            *file, *base;
@@ -488,8 +519,7 @@ FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache,
     struct stat                statb;
 
     /*
-     * Now scan all of the directories into separate databases
-     * and write out the results
+     * Read in the results from 'list'.
      */
     while ((dir = FcStrListNext (list)))
     {
@@ -543,27 +573,11 @@ FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache,
            free (file);
            continue;
        }
-       d = opendir ((char *) dir);
-       if (!d)
-       {
-           FcStrSetDestroy (subdirs);
-           free (file);
-           continue;
-       }
-       while ((e = readdir (d)))
-       {
-           if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
-           {
-               strcpy ((char *) base, (char *) e->d_name);
-               if (FcFileIsDir (file) && !FcStrSetAdd (subdirs, file))
-                   ret++;
-           }
-       }
-       closedir (d);
-       if (!FcDirCacheValid (dir) || !FcDirCacheRead (set, dir))
+       if (!FcDirCacheValid (dir) || !FcDirCacheRead (set, subdirs, dir))
        {
            if (FcDebug () & FC_DBG_FONTSET)
-               printf ("scan dir %s\n", dir);
+               printf ("cache scan dir %s\n", dir);
+
            FcDirScanConfig (set, subdirs, cache, 
                             config->blanks, dir, FcFalse, config);
        }
@@ -602,13 +616,14 @@ FcCacheRead (FcConfig *config, FcGlobalCache * cache)
 
 /* read serialized state from the cache file */
 static FcBool
-FcDirCacheRead (FcFontSet * set, const FcChar8 *dir)
+FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir)
 {
-    FcChar8         *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+    char *cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
     int fd;
     char * current_arch_machine_name;
     char candidate_arch_machine_name[9+MACHINE_SIGNATURE_SIZE];
     off_t current_arch_start = 0;
+    char subdirName[FC_MAX_FILE_LEN + 1 + 12 + 1];
 
     if (!cache_file)
         goto bail;
@@ -626,7 +641,10 @@ FcDirCacheRead (FcFontSet * set, const FcChar8 *dir)
     if (FcCacheReadString (fd, candidate_arch_machine_name, 
                           sizeof (candidate_arch_machine_name)) == 0)
        goto bail1;
-    
+
+    while (strlen(FcCacheReadString (fd, subdirName, sizeof (subdirName))) > 0)
+        FcStrSetAdd (dirs, (FcChar8 *)subdirName);
+
     if (!FcDirCacheConsume (fd, set))
        goto bail1;
        
@@ -635,7 +653,7 @@ FcDirCacheRead (FcFontSet * set, const FcChar8 *dir)
     return FcTrue;
 
  bail1:
-    close(fd);
+    close (fd);
  bail:
     free (cache_file);
     return FcFalse;
@@ -671,7 +689,7 @@ static void *
 FcDirCacheProduce (FcFontSet *set, FcCache *metadata)
 {
     void * current_dir_block, * final_dir_block;
-    static int rand_state = 0;
+    static unsigned int rand_state = 0;
     int bank;
 
     if (!rand_state) 
@@ -710,12 +728,13 @@ FcDirCacheProduce (FcFontSet *set, FcCache *metadata)
 
 /* write serialized state to the cache file */
 FcBool
-FcDirCacheWrite (FcFontSet *set, const FcChar8 *dir)
+FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
 {
     FcChar8         *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
-    int fd;
+    int fd, i;
     FcCache metadata;
     off_t current_arch_start = 0, truncate_to;
+
     char * current_arch_machine_name, * header;
     void * current_dir_block;
 
@@ -726,7 +745,7 @@ FcDirCacheWrite (FcFontSet *set, const FcChar8 *dir)
 
     if (!metadata.count)
     {
-       unlink (cache_file);
+       unlink ((char *)cache_file);
        free (cache_file);
        return FcTrue;
     }
@@ -737,7 +756,7 @@ FcDirCacheWrite (FcFontSet *set, const FcChar8 *dir)
     if (FcDebug () & FC_DBG_CACHE)
         printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
 
-    fd = open(cache_file, O_RDWR | O_CREAT, 0666);
+    fd = open((char *)cache_file, O_RDWR | O_CREAT, 0666);
     if (fd == -1)
         goto bail0;
 
@@ -747,22 +766,26 @@ FcDirCacheWrite (FcFontSet *set, const FcChar8 *dir)
        current_arch_start = FcCacheNextOffset (lseek(fd, 0, SEEK_END));
 
     if (!FcCacheMoveDown(fd, current_arch_start))
-       goto bail2;
+       goto bail0;
 
     current_arch_start = lseek(fd, 0, SEEK_CUR);
     if (ftruncate (fd, current_arch_start) == -1)
-       goto bail2;
+       goto bail0;
 
     /* now write the address of the next offset */
     truncate_to = FcCacheNextOffset (FcCacheNextOffset (current_arch_start + sizeof (FcCache)) + metadata.count) - current_arch_start;
     header = malloc (10 + strlen (current_arch_machine_name));
     if (!header)
-       goto bail1;
+       goto bail0;
     sprintf (header, "%8x ", (int)truncate_to);
     strcat (header, current_arch_machine_name);
     if (!FcCacheWriteString (fd, header))
        goto bail1;
 
+    for (i = 0; i < dirs->size; i++)
+        FcCacheWriteString (fd, (char *)dirs->strs[i]);
+    FcCacheWriteString (fd, "");
+
     write (fd, &metadata, sizeof(FcCache));
     lseek (fd, FcCacheNextOffset (lseek(fd, 0, SEEK_END)), SEEK_SET);
     write (fd, current_dir_block, metadata.count);
@@ -775,14 +798,12 @@ FcDirCacheWrite (FcFontSet *set, const FcChar8 *dir)
     close(fd);
     return FcTrue;
 
- bail2:
-    free (header);
  bail1:
-    free (current_arch_machine_name);
+    free (header);
  bail0:
     free (current_dir_block);
  bail:
-    unlink (cache_file);
+    unlink ((char *)cache_file);
     free (cache_file);
     return FcFalse;
 }