+ bail0:
+ if (free_test_dir)
+ FcStrFree (full_test_dir);
+ return FcFalse;
+}
+
+static void
+align_fd (int fd, off_t *pos, int align)
+{
+ int adj = *pos & (align - 1);
+ if (adj)
+ {
+ lseek (fd, adj, SEEK_CUR);
+ *pos += adj;
+ }
+}
+
+static uint64_t
+_conv_num (int src_fd, int dst_fd, off_t *src_pos, off_t *dst_pos,
+ FcBool src_be, FcBool dst_be, int src_psize, int dst_psize,
+ int src_read, int dst_write)
+{
+ unsigned char src[8], dst[8], *s, *d;
+ int i, src_step, dst_step;
+ uint64_t ret;
+
+ align_fd (src_fd, src_pos, src_read);
+ read (src_fd, src, src_read);
+ *src_pos += src_read;
+
+ if (src_be)
+ s = &src[src_read - 1], src_step = -1;
+ else
+ s = src, src_step = 1;
+ if (dst_be)
+ d = &dst[dst_write - 1], dst_step = -1;
+ else
+ d = dst, dst_step = 1;
+
+ ret = 0;
+ for (i = 0; i < src_read; ++i)
+ {
+ ret |= ((uint64_t) *s) << (8 * i);
+ *d = *s;
+ s += src_step;
+ d += dst_step;
+ }
+ for (; i < dst_write; ++i)
+ {
+ *d = 0;
+ d += dst_step;
+ }
+
+ align_fd (dst_fd, dst_pos, dst_write);
+ write (dst_fd, dst, dst_write);
+ *dst_pos += dst_write;
+
+ return ret;
+}
+#define conv_num(r, w) _conv_num (src_fd, dst_fd, &src_pos, &dst_pos, src_be, dst_be, src_psize, dst_psize, r, w)
+#define conv_ptr() conv_num (src_psize, dst_psize)
+#define conv_int() conv_num (4, 4)
+
+FcBool
+FcDirCacheConvert (const FcChar8 *src_cache, const FcChar8 *src_type,
+ const FcChar8 *dst_cache, const FcChar8 *dst_type)
+{
+ /* See fcarch.h for the spec used here */
+ FcCache c;
+ FcBool src_be;
+ FcBool dst_be;
+ int src_psize;
+ int dst_psize;
+ int src_dalign;
+ int dst_dalign;
+ int src_fd;
+ int dst_fd;
+ off_t src_pos;
+ off_t dst_pos;
+ struct stat src_st;
+
+ src_be = !strncmp ((const char *) src_type, "be", 2);
+ dst_be = !strncmp ((const char *) dst_type, "be", 2);
+
+ src_psize = !strncmp ((const char *) src_type + 2, "32", 2) ? 4 : 8;
+ dst_psize = !strncmp ((const char *) dst_type + 2, "32", 2) ? 4 : 8;
+
+ if (src_psize == 4)
+ src_dalign = !strncmp ((const char *) src_type + 4, "d4", 2) ? 4 : 8;
+ else
+ src_dalign = src_psize;
+
+ if (dst_psize == 4)
+ dst_dalign = !strncmp ((const char *) dst_type + 4, "d4", 2) ? 4 : 8;
+ else
+ dst_dalign = dst_psize;
+
+ src_fd = open ((const char *) src_cache, O_RDONLY);
+ if (src_fd == -1)
+ return FcFalse;
+ dst_fd = open ((const char *) dst_cache, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ if (dst_fd == -1)
+ {
+ close (src_fd);
+ return FcFalse;
+ }
+ src_pos = dst_pos = 0;
+
+ /* Process FcCache at start of file */
+ c.magic = conv_int ();
+ c.version = conv_int ();
+ c.size = conv_ptr ();
+ c.dir = conv_ptr ();
+ c.dirs = conv_ptr ();
+ c.dirs_count = conv_int ();
+ c.set = conv_ptr ();
+ c.mtime = conv_int ();
+ align_fd (dst_fd, &dst_pos, dst_psize);
+