]> git.wh0rd.org - fontconfig.git/blobdiff - src/fccache.c
Add self to AUTHORS list.
[fontconfig.git] / src / fccache.c
index 5643d3aa6694c9a97a0283d48db4c8cdb9c3f36f..50dc4d1558569125a7846732890b6dc164d9d0f7 100644 (file)
@@ -43,7 +43,7 @@ static char *
 FcDirCacheHashName (char * cache_file, int collisions);
 
 static off_t
-FcCacheSkipToArch (int fd, const char * arch, FcBool global);
+FcCacheSkipToArch (int fd, const char * arch);
 
 static FcBool 
 FcCacheCopyOld (int fd, int fd_orig, off_t start);
@@ -219,9 +219,13 @@ FcGlobalCacheLoad (FcGlobalCache    *cache,
 
     cache->updated = FcFalse;
 
+    FcCacheReadString (cache->fd, name_buf, sizeof (name_buf));
+    if (strcmp (name_buf, FC_GLOBAL_MAGIC_COOKIE) != 0)
+       return;
+
     current_arch_machine_name = FcCacheMachineSignature ();
     current_arch_start = FcCacheSkipToArch(cache->fd, 
-                                          current_arch_machine_name, FcTrue);
+                                          current_arch_machine_name);
     if (current_arch_start < 0)
         goto bail_and_destroy;
 
@@ -325,9 +329,6 @@ FcGlobalCacheUpdate (FcGlobalCache  *cache,
 {
     FcGlobalCacheDir * d;
 
-    if (!set->nfont)
-       return FcTrue;
-
     for (d = cache->dirs; d; d = d->next)
     {
        if (strcmp(d->name, name) == 0)
@@ -388,8 +389,7 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
         current_arch_start = 0;
     else
         current_arch_start = FcCacheSkipToArch (fd_orig, 
-                                                current_arch_machine_name, 
-                                               FcTrue);
+                                                current_arch_machine_name);
 
     if (current_arch_start < 0)
        current_arch_start = FcCacheNextOffset (lseek(fd_orig, 0, SEEK_END));
@@ -418,6 +418,7 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
     }
     truncate_to -= current_arch_start;
 
+    FcCacheWriteString (fd, FC_GLOBAL_MAGIC_COOKIE);
     sprintf (header, "%8x ", (int)truncate_to);
     strcat (header, current_arch_machine_name);
     if (!FcCacheWriteString (fd, header))
@@ -425,7 +426,7 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
 
     for (dir = cache->dirs; dir; dir = dir->next)
     {
-        if (dir->ent)
+        if (dir->name)
         {
             FcCacheWriteString (fd, dir->name);
             write (fd, &dir->metadata, sizeof(FcCache));
@@ -483,15 +484,14 @@ FcCacheNextOffset(off_t w)
 /* return the address of the segment for the provided arch,
  * or -1 if arch not found */
 static off_t
-FcCacheSkipToArch (int fd, const char * arch, FcBool global)
+FcCacheSkipToArch (int fd, const char * arch)
 {
     char candidate_arch_machine_name_count[MACHINE_SIGNATURE_SIZE + 9];
     char * candidate_arch;
     off_t current_arch_start = 0;
 
     lseek (fd, 0, SEEK_SET);
-    if (!global)
-       FcCacheSkipString (fd);
+    FcCacheSkipString (fd);
     current_arch_start = lseek (fd, 0, SEEK_CUR);
 
     /* skip arches that are not the current arch */
@@ -590,6 +590,9 @@ FcCacheCopyOld (int fd, int fd_orig, off_t start)
 }
 
 /* Does not check that the cache has the appropriate arch section. */
+/* Also, this can be fooled if the original location has a stale
+ * 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)
 {
@@ -649,8 +652,7 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir)
        goto bail;
 
     current_arch_machine_name = FcCacheMachineSignature();
-    current_arch_start = FcCacheSkipToArch(fd, 
-                                          current_arch_machine_name, FcFalse);
+    current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
     close (fd);
 
     if (current_arch_start < 0)
@@ -666,18 +668,55 @@ FcDirCacheHasCurrentArch (const FcChar8 *dir)
 FcBool
 FcDirCacheUnlink (const FcChar8 *dir)
 {
-    FcChar8     *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+    char       *cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+    char       *cache_hashed;
+    int                fd, collisions;
     struct stat        cache_stat;
+    char       name_buf[FC_MAX_FILE_LEN];
 
+    /* First remove normal cache file. */
     if (stat ((char *) cache_file, &cache_stat) == 0 &&
        unlink ((char *)cache_file) != 0)
+       goto bail;
+
+    /* Next remove any applicable hashed files. */
+    fd = -1; collisions = 0;
+    do
     {
-       FcStrFree (cache_file);
-        return FcFalse;
+       cache_hashed = FcDirCacheHashName (cache_file, collisions++);
+       if (!cache_hashed)
+           goto bail;
+
+       if (fd > 0)
+           close (fd);
+       fd = open(cache_hashed, O_RDONLY);
+       if (fd == -1)
+       {
+           FcStrFree ((FcChar8 *)cache_file);
+           return FcTrue;
+       }
+
+       FcCacheReadString (fd, name_buf, sizeof (name_buf));
+       if (!strlen(name_buf))
+           goto bail;
+    } while (strcmp (name_buf, cache_file) != 0);
+
+    FcStrFree ((FcChar8 *)cache_file);
+    close (fd);
+
+    if (stat ((char *) cache_hashed, &cache_stat) == 0 &&
+       unlink ((char *)cache_hashed) != 0)
+    {
+       FcStrFree ((FcChar8 *)cache_hashed);
+       goto bail;
     }
 
-    FcStrFree (cache_file);
+    FcStrFree ((FcChar8 *)cache_hashed);
     return FcTrue;
+
+ bail:
+    FcStrFree ((FcChar8 *)cache_file);
+    return FcFalse;
 }
 
 static int
@@ -840,6 +879,10 @@ FcDirCacheOpen (char *cache_file)
     char       *cache_hashed;
     char       name_buf[FC_MAX_FILE_LEN];
 
+    fd = open(cache_file, O_RDONLY);
+    if (fd != -1)
+       return fd;
+
     do
     {
        cache_hashed = FcDirCacheHashName (cache_file, collisions++);
@@ -849,6 +892,8 @@ FcDirCacheOpen (char *cache_file)
        if (fd > 0)
            close (fd);
        fd = open(cache_hashed, O_RDONLY);
+       FcStrFree ((FcChar8 *)cache_hashed);
+
        if (fd == -1)
            return -1;
        FcCacheReadString (fd, name_buf, sizeof (name_buf));
@@ -883,8 +928,7 @@ FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir)
 
     current_arch_machine_name = FcCacheMachineSignature();
     current_arch_start = FcCacheSkipToArch(fd, 
-                                          current_arch_machine_name,
-                                          FcFalse);
+                                          current_arch_machine_name);
     if (current_arch_start < 0)
         goto bail1;
 
@@ -927,6 +971,7 @@ FcDirCacheConsume (int fd, const char * dir, FcFontSet *set)
     pos = FcCacheNextOffset (lseek(fd, 0, SEEK_CUR));
     current_dir_block = mmap (0, metadata.count, 
                              PROT_READ, MAP_SHARED, fd, pos);
+    lseek (fd, pos+metadata.count, SEEK_SET);
     if (current_dir_block == MAP_FAILED)
        return FcFalse;
 
@@ -992,7 +1037,7 @@ FcBool
 FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
 {
     char           *cache_file;
-    char           *cache_hashed;
+    char           *cache_hashed;
     int            fd, fd_orig, i, dirs_count;
     FcAtomic       *atomic;
     FcCache        metadata;
@@ -1045,13 +1090,29 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
        goto bail1;
 
     if (!FcAtomicLock (atomic))
-        goto bail2;
+    {
+       /* Now try rewriting the original version of the file. */
+       FcAtomicDestroy (atomic);
 
-    fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY, 0666);
+       atomic = FcAtomicCreate ((FcChar8 *)cache_file);
+       fd_orig = open (cache_file, O_RDONLY);
+       if (fd_orig == -1)
+           fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY);
+
+       fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT, 0666);
+       if (fd == -1)
+           goto bail2;
+    }
+
+    /* In all cases, try opening the real location of the cache file first. */
+    /* (even if that's not atomic.) */
+    fd_orig = open (cache_file, O_RDONLY);
+    if (fd_orig == -1)
+       fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY);
 
     fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT, 0666);
     if (fd == -1)
-        goto bail3;
+       goto bail3;
 
     FcCacheWriteString (fd, cache_file);
 
@@ -1060,7 +1121,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
 
     if (fd_orig != -1)
         current_arch_start = 
-            FcCacheSkipToArch(fd_orig, current_arch_machine_name, FcFalse);
+            FcCacheSkipToArch(fd_orig, current_arch_machine_name);
 
     if (current_arch_start < 0)
        current_arch_start = FcCacheNextOffset (lseek(fd_orig, 0, SEEK_END));
@@ -1110,6 +1171,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
     close(fd);
     if (!FcAtomicReplaceOrig(atomic))
         goto bail5;
+    FcStrFree ((FcChar8 *)cache_hashed);
     FcAtomicUnlock (atomic);
     FcAtomicDestroy (atomic);
     return FcTrue;
@@ -1123,7 +1185,7 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
  bail2:
     FcAtomicDestroy (atomic);
  bail1:
-    free (cache_hashed);
+    FcStrFree ((FcChar8 *)cache_hashed);
  bail0:
     unlink ((char *)cache_file);
     free (cache_file);