#define _GNU_SOURCE
#include <getopt.h>
const struct option longopts[] = {
+ {"convert", 0, 0, 'c'},
{"force", 0, 0, 'f'},
{"really-force", 0, 0, 'r'},
{"root", 1, 0, 'R'},
#if HAVE_GETOPT_LONG || HAVE_GETOPT
int c;
+FcBool convert = FcFalse;
+
#if HAVE_GETOPT_LONG
- while ((c = getopt_long (argc, argv, "frR:sVvh", longopts, NULL)) != -1)
+ while ((c = getopt_long (argc, argv, "cfrR:sVvh", longopts, NULL)) != -1)
#else
- while ((c = getopt (argc, argv, "frR:sVvh")) != -1)
+ while ((c = getopt (argc, argv, "cfrR:sVvh")) != -1)
#endif
{
switch (c) {
+ case 'c':
+ convert = FcTrue;
+ break;
case 'r':
really_force = FcTrue;
/* fall through */
i = 1;
#endif
+ if (convert)
+ {
+ const FcChar8 *src_cache, *dst_cache, *src_type, *dst_type;
+
+ src_cache = (const FcChar8 *) argv[i++];
+ src_type = (const FcChar8 *) argv[i++];
+ dst_cache = (const FcChar8 *) argv[i++];
+ dst_type = (const FcChar8 *) argv[i++];
+
+ FcDirCacheConvert (src_cache, src_type, dst_cache, dst_type);
+
+ return 0;
+ }
+
if (systemOnly)
FcConfigEnableHome (FcFalse);
config = FcInitLoadConfig ();
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);
+
+ return FcFalse;
+}
+
/*
* Hokey little macro trick to permit the definitions of C functions
* with the same name as CPP macros