- return ret;
-}
-
-FcFontSet *
-FcCacheRead (FcConfig *config, FcGlobalCache * cache)
-{
- FcFontSet *s = FcFontSetCreate();
- FcStrSet *processed_dirs;
-
- if (!s)
- return 0;
-
- processed_dirs = FcStrSetCreate();
- if (!processed_dirs)
- goto bail;
-
- if (FcCacheReadDirs (config, cache, FcConfigGetConfigDirs (config), s, processed_dirs))
- goto bail1;
-
- FcStrSetDestroy (processed_dirs);
- return s;
-
- bail1:
- FcStrSetDestroy (processed_dirs);
- bail:
- FcFontSetDestroy (s);
- 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 (char * cache_file, 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 *)cache_file, strlen (cache_file));
-
- 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. */
-static int
-FcDirCacheOpen (const FcChar8 *dir)
-{
- FcBool found;
- int fd = -1, collisions = 0;
- char *cache_file, *cache_hashed;
- char name_buf[FC_MAX_FILE_LEN];
- struct stat dir_stat;
-
- if (stat ((char *)dir, &dir_stat) == -1)
- return -1;
-
- cache_file = (char *)FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
- if (!cache_file)
- return -1;
-
- found = FcFalse;
- do
- {
- struct stat c;
- FcChar8 *name_buf_dir;
-
- if (fd >= 0)
- close (fd);
-
- cache_hashed = FcDirCacheHashName (cache_file, collisions++);
- if (!cache_hashed)
- {
- FcStrFree ((FcChar8 *)cache_file);
- return -1;
- }
-
- fd = open(cache_hashed, O_RDONLY | O_BINARY);
- FcStrFree ((FcChar8 *)cache_hashed);
-
- if (fd == -1)
- break;
- if (!FcCacheReadString (fd, name_buf, sizeof (name_buf)) ||
- !strlen(name_buf))
- break;
-
- name_buf_dir = FcStrDirname ((FcChar8 *)name_buf);
- if (stat ((char *)name_buf_dir, &c) == -1)
- {
- FcStrFree (name_buf_dir);
- continue;
- }
- FcStrFree (name_buf_dir);
- found = (c.st_ino == dir_stat.st_ino) && (c.st_dev == dir_stat.st_dev);
- } while (!found);
-
- if (!found || fd < 0)
- {
- if (fd >= 0)
- close (fd);
- fd = open(cache_file, O_RDONLY | O_BINARY);
- }
-
- FcStrFree ((FcChar8 *)cache_file);
- return fd;
-}
-
-/* read serialized state from the cache file */
-FcBool
-FcDirCacheRead (FcFontSet * set, FcStrSet * dirs, const FcChar8 *dir, FcConfig *config)
-{
- 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];
-
- fd = FcDirCacheOpen (dir);
- if (fd < 0)
- goto bail;
-
- current_arch_machine_name = FcCacheMachineSignature();
- current_arch_start = FcCacheSkipToArch(fd,
- current_arch_machine_name);
- if (current_arch_start < 0)
- goto bail1;
-
- lseek (fd, current_arch_start, SEEK_SET);
- if (FcCacheReadString (fd, candidate_arch_machine_name,
- sizeof (candidate_arch_machine_name)) == 0)
- goto bail1;
-
- while (FcCacheReadString (fd, subdirName, sizeof (subdirName)) && strlen (subdirName) > 0)
- FcStrSetAdd (dirs, (FcChar8 *)subdirName);
-
- if (!FcDirCacheConsume (fd, (const char *)dir, set, config))
- goto bail1;
-
- close(fd);
- return FcTrue;
-
- bail1:
- close (fd);
- bail:
- return FcFalse;
-}
-
-static FcBool
-FcDirCacheConsume (int fd, const char * dir, FcFontSet *set, FcConfig *config)
-{
- FcCache metadata;
- void * current_dir_block;
- off_t pos;
-
- if (read(fd, &metadata, sizeof(FcCache)) != sizeof(FcCache))
- return FcFalse;
- if (metadata.magic != FC_CACHE_MAGIC)
- return FcFalse;
-
- if (!metadata.count)
- {
- pos = FcCacheNextOffset (lseek(fd, 0, SEEK_CUR));
- lseek (fd, pos, SEEK_SET);
- if (config)
- FcConfigAddFontDir (config, (FcChar8 *)dir);
- return FcTrue;
- }
-
- 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;
-
- FcCacheAddBankDir (metadata.bank, dir);
- if (config)
- FcConfigAddFontDir (config, (FcChar8 *)dir);
-
- if (!FcFontSetUnserialize (&metadata, set, current_dir_block))
- return FcFalse;
-
- return FcTrue;
-}
-
-static void *
-FcDirCacheProduce (FcFontSet *set, FcCache *metadata)
-{
- void * current_dir_block, * final_dir_block;
- static unsigned int rand_state = 0;
- int bank, needed_bytes_no_align;
-
- if (!rand_state)
- rand_state = time(0L);
- bank = rand_r(&rand_state);
-
- while (FcCacheHaveBank(bank))
- bank = rand_r(&rand_state);
-
- memset (metadata, 0, sizeof(FcCache));
- FcFontSetNewBank();
- needed_bytes_no_align = FcFontSetNeededBytes (set);
- metadata->count = needed_bytes_no_align +
- FcFontSetNeededBytesAlign ();
- metadata->magic = FC_CACHE_MAGIC;
- metadata->bank = bank;
-
- if (!needed_bytes_no_align) /* not a failure, no fonts to write */
- {
- /* no, you don't really need to write any bytes at all. */
- metadata->count = 0;
- return 0;
- }
-
- current_dir_block = malloc (metadata->count);
- if (!current_dir_block)
- goto bail;
- /* shut up valgrind */
- memset (current_dir_block, 0, metadata->count);
- final_dir_block = FcFontSetDistributeBytes (metadata, current_dir_block);
-
- if ((void *)((char *)current_dir_block+metadata->count) < final_dir_block)
- goto bail;
-
- if (!FcFontSetSerialize (bank, set))
- goto bail;
-
- return current_dir_block;
-
- bail:
- free (current_dir_block);
- return 0;
-}
-
-/* write serialized state to the cache file */
-FcBool
-FcDirCacheWrite (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
-{
- char *cache_file;
- char *cache_hashed;
- int fd, fd_orig, i, dirs_count;
- FcAtomic *atomic;
- FcCache metadata;
- off_t current_arch_start = 0, truncate_to;
- char name_buf[FC_MAX_FILE_LEN];
- int collisions;
-
- char *current_arch_machine_name, * header;
- void *current_dir_block = 0;
-
- dir = FcConfigNormalizeFontDir (FcConfigGetCurrent(), dir);
- if (!dir)