From 8ba2b3c59b2cd0bf24b6045f5c6babdf49b4b30d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 8 Nov 2011 11:47:27 -0500 Subject: [PATCH] fc-cache: convert --- fc-cache/fc-cache.c | 24 ++++++++- src/fccache.c | 116 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 2 deletions(-) diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c index 59a24bb..9bac25d 100644 --- a/fc-cache/fc-cache.c +++ b/fc-cache/fc-cache.c @@ -67,6 +67,7 @@ #define _GNU_SOURCE #include const struct option longopts[] = { + {"convert", 0, 0, 'c'}, {"force", 0, 0, 'f'}, {"really-force", 0, 0, 'r'}, {"root", 1, 0, 'R'}, @@ -386,13 +387,18 @@ main (int argc, char **argv) #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 */ @@ -423,6 +429,20 @@ main (int argc, char **argv) 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 (); diff --git a/src/fccache.c b/src/fccache.c index e9f57f4..350b805 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -1009,6 +1009,122 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config) 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 -- 2.39.2