]> git.wh0rd.org - fontconfig.git/blobdiff - src/fccache.c
Fix flipped return value on unlink. (Reported by Mike Fabian)
[fontconfig.git] / src / fccache.c
index 16ac30b74b043995b3d6113f06122f0ae5e14e95..7ccb5295013f3a946146d0af273406faca06855b 100644 (file)
@@ -38,7 +38,7 @@ static off_t
 FcCacheSkipToArch (int fd, const char * arch);
 
 static FcBool 
-FcCacheMoveDown (int fd, off_t start);
+FcCacheCopyOld (int fd, int fd_orig, off_t start);
 
 static void *
 FcDirCacheProduce (FcFontSet *set, FcCache * metadata);
@@ -46,7 +46,7 @@ FcDirCacheProduce (FcFontSet *set, FcCache * metadata);
 static FcBool
 FcDirCacheConsume (int fd, FcFontSet *set);
 
-static FcBool
+FcBool
 FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir);
 
 static int
@@ -291,7 +291,7 @@ FcBool
 FcGlobalCacheSave (FcGlobalCache    *cache,
                   const FcChar8    *cache_file)
 {
-    int                        fd;
+    int                        fd, fd_orig;
     FcGlobalCacheDir   *dir;
     FcAtomic           *atomic;
     off_t              current_arch_start = 0, truncate_to;
@@ -308,7 +308,8 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
     
     atomic = FcAtomicCreate (cache_file);
     if (!atomic)
-       goto bail0;
+       return FcFalse;
+
     if (!FcAtomicLock (atomic))
        goto bail1;
     fd = open ((char *) FcAtomicNewFile(atomic), O_RDWR | O_CREAT, 
@@ -316,21 +317,31 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
     if (fd == -1)
        goto bail2;
 
+    fd_orig = open ((char *) FcAtomicOrigFile(atomic), O_RDONLY);
+
     current_arch_machine_name = FcCacheMachineSignature ();
-    current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
+    if (fd_orig == -1)
+        current_arch_start = 0;
+    else
+        current_arch_start = FcCacheSkipToArch (fd_orig, 
+                                                current_arch_machine_name);
+
     if (current_arch_start < 0)
-       current_arch_start = FcCacheNextOffset (lseek(fd, 0, SEEK_END));
+       current_arch_start = FcCacheNextOffset (lseek(fd_orig, 0, SEEK_END));
 
-    if (!FcCacheMoveDown(fd, current_arch_start))
-       goto bail2;
+    if (!FcCacheCopyOld(fd, fd_orig, current_arch_start))
+       goto bail3;
+
+    close (fd_orig);
+    fd_orig = -1;
 
     current_arch_start = lseek(fd, 0, SEEK_CUR);
     if (ftruncate (fd, current_arch_start) == -1)
-       goto bail2;
+       goto bail3;
 
     header = malloc (10 + strlen (current_arch_machine_name));
     if (!header)
-       goto bail1;
+       goto bail3;
 
     truncate_to = current_arch_start + strlen(current_arch_machine_name) + 11;
     for (dir = cache->dirs; dir; dir = dir->next)
@@ -345,7 +356,7 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
     sprintf (header, "%8x ", (int)truncate_to);
     strcat (header, current_arch_machine_name);
     if (!FcCacheWriteString (fd, header))
-       goto bail1;
+       goto bail4;
 
     for (dir = cache->dirs; dir; dir = dir->next)
     {
@@ -361,10 +372,10 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
     FcCacheWriteString (fd, "");
 
     if (close (fd) == -1)
-       goto bail3;
+       goto bail25;
     
     if (!FcAtomicReplaceOrig (atomic))
-       goto bail3;
+       goto bail25;
     
     FcAtomicUnlock (atomic);
     FcAtomicDestroy (atomic);
@@ -372,13 +383,19 @@ FcGlobalCacheSave (FcGlobalCache    *cache,
     cache->updated = FcFalse;
     return FcTrue;
 
-bail3:
+ bail4:
+    free (header);
+ bail3:
+    if (fd_orig != -1)
+        close (fd_orig);
+
+    close (fd);
+ bail25:
     FcAtomicDeleteNew (atomic);
-bail2:
+ bail2:
     FcAtomicUnlock (atomic);
-bail1:
+ bail1:
     FcAtomicDestroy (atomic);
-bail0:
     return FcFalse;
 }
 
@@ -438,16 +455,34 @@ FcCacheSkipToArch (int fd, const char * arch)
  * down to cover it), and leaves the file pointer at the end of the
  * file. */
 static FcBool 
-FcCacheMoveDown (int fd, off_t start)
+FcCacheCopyOld (int fd, int fd_orig, off_t start)
 {
     char * buf = malloc (8192);
     char candidate_arch_machine_name[MACHINE_SIGNATURE_SIZE + 9];
     long bs;
     int c, bytes_skipped;
+    off_t loc;
 
     if (!buf)
        return FcFalse;
 
+    loc = 0;
+    lseek (fd, 0, SEEK_SET); lseek (fd_orig, 0, SEEK_SET);
+    do
+    {
+        int b = 8192;
+        if (loc + b > start)
+            b = start - loc;
+
+       if ((c = read (fd_orig, buf, b)) <= 0)
+           break;
+       if (write (fd, buf, c) < 0)
+           goto bail;
+
+        loc += c;
+    }
+    while (c > 0);
+
     lseek (fd, start, SEEK_SET);
     if (FcCacheReadString (fd, candidate_arch_machine_name, 
                           sizeof (candidate_arch_machine_name)) == 0)
@@ -482,6 +517,7 @@ FcCacheMoveDown (int fd, off_t start)
     return FcFalse;
 }
 
+/* Does not check that the cache has the appropriate arch section. */
 FcBool
 FcDirCacheValid (const FcChar8 *dir)
 {
@@ -498,6 +534,7 @@ FcDirCacheValid (const FcChar8 *dir)
         FcStrFree (cache_file);
         return FcFalse;
     }
+
     FcStrFree (cache_file);
     /*
      * If the directory has been modified more recently than
@@ -508,6 +545,45 @@ FcDirCacheValid (const FcChar8 *dir)
     return FcTrue;
 }
 
+/* Assumes that the cache file in 'dir' exists.
+ * Checks that the cache has the appropriate arch section. */
+FcBool
+FcDirCacheHasCurrentArch (const FcChar8 *dir)
+{
+    FcChar8     *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+    int        fd;
+    off_t      current_arch_start;
+    char       *current_arch_machine_name;
+
+    current_arch_machine_name = FcCacheMachineSignature();
+    fd = open ((char *)cache_file, O_RDONLY);
+    if (fd == -1)
+        return FcFalse;
+
+    current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
+    close (fd);
+
+    if (current_arch_start < 0)
+        return FcFalse;
+    
+    return FcTrue;
+}
+
+FcBool
+FcDirCacheUnlink (const FcChar8 *dir)
+{
+    FcChar8     *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+
+    if (unlink ((char *)cache_file) != 0)
+    {
+       FcStrFree (cache_file);
+        return FcFalse;
+    }
+
+    FcStrFree (cache_file);
+    return FcTrue;
+}
+
 static int
 FcCacheReadDirs (FcConfig * config, FcGlobalCache * cache, 
                 FcStrList *list, FcFontSet * set)
@@ -616,7 +692,7 @@ FcCacheRead (FcConfig *config, FcGlobalCache * cache)
 }
 
 /* read serialized state from the cache file */
-static FcBool
+FcBool
 FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir)
 {
     char *cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
@@ -732,12 +808,13 @@ FcBool
 FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
 {
     FcChar8         *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
-    int fd, i, dirs_count;
-    FcCache metadata;
-    off_t current_arch_start = 0, truncate_to;
+    int            fd, fd_orig, i, dirs_count;
+    FcAtomic       *atomic;
+    FcCache        metadata;
+    off_t          current_arch_start = 0, truncate_to;
 
-    char current_arch_machine_name, * header;
-    void current_dir_block;
+    char            *current_arch_machine_name, * header;
+    void           *current_dir_block;
 
     if (!cache_file)
         goto bail;
@@ -745,26 +822,43 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
     current_dir_block = FcDirCacheProduce (set, &metadata);
 
     if (metadata.count && !current_dir_block)
-       goto bail;
+       goto bail0;
 
     if (FcDebug () & FC_DBG_CACHE)
         printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
 
-    fd = open((char *)cache_file, O_RDWR | O_CREAT, 0666);
-    if (fd == -1)
+    atomic = FcAtomicCreate (cache_file);
+    if (!atomic)
         goto bail0;
 
+    if (!FcAtomicLock (atomic))
+        goto bail1;
+
+    fd_orig = open((char *)FcAtomicOrigFile (atomic), O_RDONLY, 0666);
+
+    fd = open((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT, 0666);
+    if (fd == -1)
+        goto bail2;
+
     current_arch_machine_name = FcCacheMachineSignature ();
-    current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name);
+    current_arch_start = 0;
+
+    if (fd_orig != -1)
+        current_arch_start = 
+            FcCacheSkipToArch(fd_orig, current_arch_machine_name);
+
     if (current_arch_start < 0)
-       current_arch_start = FcCacheNextOffset (lseek(fd, 0, SEEK_END));
+       current_arch_start = FcCacheNextOffset (lseek(fd_orig, 0, SEEK_END));
 
-    if (!FcCacheMoveDown(fd, current_arch_start))
-       goto bail0;
+    if (fd_orig != -1 && !FcCacheCopyOld(fd, fd_orig, current_arch_start))
+       goto bail3;
+
+    if (fd_orig != -1)
+        close (fd_orig);
 
     current_arch_start = lseek(fd, 0, SEEK_CUR);
     if (ftruncate (fd, current_arch_start) == -1)
-       goto bail0;
+       goto bail3;
 
     /* allocate space for subdir names in this block */
     dirs_count = 0;
@@ -776,11 +870,11 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
     truncate_to = FcCacheNextOffset (FcCacheNextOffset (current_arch_start + sizeof (FcCache) + dirs_count) + metadata.count) - current_arch_start;
     header = malloc (10 + strlen (current_arch_machine_name));
     if (!header)
-       goto bail0;
+       goto bail3;
     sprintf (header, "%8x ", (int)truncate_to);
     strcat (header, current_arch_machine_name);
     if (!FcCacheWriteString (fd, header))
-       goto bail1;
+       goto bail4;
 
     for (i = 0; i < dirs->size; i++)
         FcCacheWriteString (fd, (char *)dirs->strs[i]);
@@ -796,18 +890,29 @@ FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
 
     /* this actually serves to pad out the cache file, if needed */
     if (ftruncate (fd, current_arch_start + truncate_to) == -1)
-       goto bail1;
+       goto bail4;
 
     close(fd);
+    if (!FcAtomicReplaceOrig(atomic))
+        goto bail4;
+    FcAtomicUnlock (atomic);
+    FcAtomicDestroy (atomic);
     return FcTrue;
 
- bail1:
+ bail4:
     free (header);
+ bail3:
+    close (fd);
+ bail2:
+    FcAtomicUnlock (atomic);
+ bail1:
+    FcAtomicDestroy (atomic);
  bail0:
-    free (current_dir_block);
- bail:
     unlink ((char *)cache_file);
     free (cache_file);
+    if (current_dir_block)
+        free (current_dir_block);
+ bail:
     return FcFalse;
 }
 
@@ -822,31 +927,31 @@ FcCacheMachineSignature ()
             "%4x %4x %4x %4x %4x %4x %4x %4x %4x %4x %4x %4x "
             "%4x %4x %4x %4x %4x %4x %4x\n", 
             m[0], m[1], m[2], m[3],
-            sizeof (char),
-            sizeof (char *),
-            sizeof (int),
-            sizeof (FcPattern),
-            sizeof (FcPatternEltPtr),
-            sizeof (struct _FcPatternElt *),
-            sizeof (FcPatternElt),
-            sizeof (FcObjectPtr),
-            sizeof (FcValueListPtr),
-            sizeof (FcValue),
-            sizeof (FcValueBinding),
-            sizeof (struct _FcValueList *),
-            sizeof (FcCharSet),
-            sizeof (FcCharLeaf **),
-            sizeof (FcChar16 *),
-            sizeof (FcChar16),
-            sizeof (FcCharLeaf),
-            sizeof (FcChar32),
-            sizeof (FcCache));
+            (unsigned int)sizeof (char),
+            (unsigned int)sizeof (char *),
+            (unsigned int)sizeof (int),
+            (unsigned int)sizeof (FcPattern),
+            (unsigned int)sizeof (FcPatternEltPtr),
+            (unsigned int)sizeof (struct _FcPatternElt *),
+            (unsigned int)sizeof (FcPatternElt),
+            (unsigned int)sizeof (FcObjectPtr),
+            (unsigned int)sizeof (FcValueListPtr),
+            (unsigned int)sizeof (FcValue),
+            (unsigned int)sizeof (FcValueBinding),
+            (unsigned int)sizeof (struct _FcValueList *),
+            (unsigned int)sizeof (FcCharSet),
+            (unsigned int)sizeof (FcCharLeaf **),
+            (unsigned int)sizeof (FcChar16 *),
+            (unsigned int)sizeof (FcChar16),
+            (unsigned int)sizeof (FcCharLeaf),
+            (unsigned int)sizeof (FcChar32),
+            (unsigned int)sizeof (FcCache));
 
     return buf;
 }
 
 static int banks_ptr = 0, banks_alloc = 0;
-static int * bankId = 0;
+static int * bankId = 0, * bankIdx = 0;
 
 static FcBool
 FcCacheHaveBank (int bank)
@@ -866,28 +971,37 @@ FcCacheHaveBank (int bank)
 int
 FcCacheBankToIndex (int bank)
 {
-    static int lastBank = FC_BANK_DYNAMIC, lastIndex = -1;
-    int i;
-    int * b;
-
-    if (bank == lastBank)
-       return lastIndex;
+    int i, j;
 
     for (i = 0; i < banks_ptr; i++)
-       if (bankId[i] == bank)
-           return i;
+       if (bankId[bankIdx[i]] == bank)
+       {
+           int t = bankIdx[i];
+
+           for (j = i; j > 0; j--)
+               bankIdx[j] = bankIdx[j-1];
+           bankIdx[0] = t;
+           return t;
+       }
 
     if (banks_ptr >= banks_alloc)
     {
+       int * b, * bidx;
        b = realloc (bankId, (banks_alloc + 4) * sizeof(int));
        if (!b)
            return -1;
-
        bankId = b;
+
+       bidx = realloc (bankIdx, (banks_alloc + 4) * sizeof(int));
+       if (!bidx)
+           return -1;
+       bankIdx = bidx;
+
        banks_alloc += 4;
     }
 
     i = banks_ptr++;
     bankId[i] = bank;
+    bankIdx[i] = i;
     return i;
 }