]> git.wh0rd.org - fontconfig.git/blobdiff - fc-cat/fc-cat.c
With no args, fc-cat now dumps all directories.
[fontconfig.git] / fc-cat / fc-cat.c
index f088e4585a9220ff2003f190f02014b0b8e4fe11..6074f1d92f1fe81670fa15e877979dccb82fb1fc 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <fontconfig/fontconfig.h>
-#include <../src/fccache.c>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <libgen.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #else
 #define HAVE_GETOPT 1
 #endif
 
+#include "../src/fccache.c"
+#include "../fc-arch/fcarch.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
 #ifndef HAVE_GETOPT
 #define HAVE_GETOPT 0
 #endif
@@ -53,6 +53,8 @@
 #include <getopt.h>
 const struct option longopts[] = {
     {"version", 0, 0, 'V'},
+    {"verbose", 0, 0, 'v'},
+    {"recurse", 0, 0, 'r'},
     {"help", 0, 0, '?'},
     {NULL,0,0,0},
 };
@@ -78,9 +80,6 @@ extern int optind, opterr, optopt;
 #define PUTC(c,f) putc(c,f)
 #endif
 
-FcBool
-FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *cache_file);
-
 static FcBool
 FcCacheWriteChars (FILE *f, const FcChar8 *chars)
 {
@@ -149,13 +148,15 @@ static void
 usage (char *program)
 {
 #if HAVE_GETOPT_LONG
-    fprintf (stderr, "usage: %s [-V?] [--version] [--help] <fonts.cache-2>\n",
-            program);
+    fprintf (stderr, "usage: %s [-V?] [--version] [--help] {*-%s.cache-2|directory}...\n",
+            program, FC_ARCHITECTURE);
 #else
-    fprintf (stderr, "usage: %s [-fsvV?] <fonts.cache-2>\n",
-            program);
+    fprintf (stderr, "usage: %s [-fsvV?] {*-%s.cache-2|directory}...\n",
+            program, FC_ARCHITECTURE);
 #endif
-    fprintf (stderr, "Reads font information caches in <fonts.cache-2>\n");
+    fprintf (stderr, "Reads font information cache from:\n"); 
+    fprintf (stderr, " 1) specified fontconfig cache file\n");
+    fprintf (stderr, " 2) related to a particular font directory\n");
     fprintf (stderr, "\n");
 #if HAVE_GETOPT_LONG
     fprintf (stderr, "  -V, --version        display font config version and exit\n");
@@ -167,104 +168,22 @@ usage (char *program)
     exit (1);
 }
 
-static FcBool 
-FcCacheGlobalFileReadAndPrint (FcFontSet * set, FcStrSet *dirs, char * dir, char *cache_file)
+static int
+FcCacheFileOpen (char *cache_file, off_t *size)
 {
-    char               name_buf[8192];
     int fd;
-    char * current_arch_machine_name;
-    char candidate_arch_machine_name[9+MACHINE_SIGNATURE_SIZE];
-    off_t current_arch_start = 0;
-
-    if (!cache_file)
-       goto bail;
-
-    current_arch_machine_name = FcCacheMachineSignature();
-    fd = open(cache_file, O_RDONLY);
-    if (fd == -1)
-       goto bail;
+    struct stat file_stat;
 
-    current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name,
-                                          FcTrue);
-    if (current_arch_start < 0)
-       goto bail1;
+    fd = open(cache_file, O_RDONLY | O_BINARY);
+    if (fd < 0)
+        return -1;
 
-    lseek (fd, current_arch_start, SEEK_SET);
-    if (FcCacheReadString (fd, candidate_arch_machine_name, 
-                          sizeof (candidate_arch_machine_name)) == 0)
-       goto bail1;
-
-    while (1) 
-    {
-       FcCacheReadString (fd, name_buf, sizeof (name_buf));
-       if (!strlen(name_buf))
-           break;
-       printf ("fc-cat: printing global cache contents for dir %s\n", 
-               name_buf);
-
-       if (!FcDirCacheConsume (fd, dir, set))
-           goto bail1;
-
-       FcCachePrintSet (set, dirs, name_buf);
-
-       FcFontSetDestroy (set);
-       set = FcFontSetCreate();
+    if (fstat (fd, &file_stat) < 0) {
+       close (fd); 
+       return -1;
     }
-
- bail1:
-    close (fd);
- bail:
-    return FcFalse;
-}
-
-/* read serialized state from the cache file */
-static FcBool
-FcCacheFileRead (FcFontSet * set, FcStrSet *dirs, char * dir, char *cache_file)
-{
-    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];
-    char name_buf[8192];
-
-    if (!cache_file)
-        goto bail;
-
-    current_arch_machine_name = FcCacheMachineSignature();
-    fd = open(cache_file, O_RDONLY);
-    if (fd == -1)
-        goto bail;
-
-    FcCacheReadString (fd, name_buf, sizeof (name_buf));
-    if (!strlen (name_buf))
-       goto bail;
-    printf ("fc-cat: printing directory cache contents for dir %s\n", 
-           name_buf);
-
-    current_arch_start = FcCacheSkipToArch(fd, current_arch_machine_name,
-                                          FcFalse);
-    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 (strlen(FcCacheReadString (fd, subdirName, sizeof (subdirName))) > 0)
-        FcStrSetAdd (dirs, (FcChar8 *)subdirName);
-
-    if (!FcDirCacheConsume (fd, dir, set))
-       goto bail1;
-       
-    close(fd);
-    return FcTrue;
-
- bail1:
-    close (fd);
- bail:
-    return FcFalse;
+    *size = file_stat.st_size;
+    return fd;
 }
 
 /*
@@ -275,16 +194,15 @@ static const FcChar8 *
 FcFileBaseName (const char *cache, const FcChar8 *file)
 {
     const FcChar8   *cache_slash;
+    int                    cache_len = strlen (cache);
 
-    cache_slash = FcStrLastSlash ((const FcChar8 *)cache);
-    if (cache_slash && !strncmp ((const char *) cache, (const char *) file,
-                                (cache_slash + 1) - (const FcChar8 *)cache))
-       return file + ((cache_slash + 1) - (const FcChar8 *)cache);
+    if (!strncmp (cache, file, cache_len) && file[cache_len] == '/')
+       return file + cache_len + 1;
     return file;
 }
 
 FcBool
-FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *cache_file)
+FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *base_name, FcBool verbose)
 {
     FcPattern      *font;
     FcChar8        *name, *dir;
@@ -292,6 +210,7 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *cache_file)
     int                    ret;
     int                    n;
     int                    id;
+    int                    ndir = 0;
     FcStrList      *list;
 
     list = FcStrListCreate (dirs);
@@ -300,7 +219,7 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *cache_file)
     
     while ((dir = FcStrListNext (list)))
     {
-       base = FcFileBaseName (cache_file, dir);
+       base = FcFileBaseName (base_name, dir);
        if (!FcCacheWriteStringOld (stdout, base))
            goto bail3;
        if (PUTC (' ', stdout) == EOF)
@@ -313,18 +232,20 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *cache_file)
            goto bail3;
        if (PUTC ('\n', stdout) == EOF)
            goto bail3;
+       ndir++;
     }
     
     for (n = 0; n < set->nfont; n++)
     {
-       font = set->fonts[n];
+       FcPattern   **fonts = FcFontSetFonts (set);
+       FcPattern   *encoded_font = fonts[n];
+       FcPattern   *font = FcEncodedOffsetToPtr (set, encoded_font, FcPattern);
+
        if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
            goto bail3;
-       base = FcFileBaseName (cache_file, file);
+       base = FcFileBaseName (base_name, file);
        if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
            goto bail3;
-       if (FcDebug () & FC_DBG_CACHEV)
-           printf (" write file \"%s\"\n", base);
        if (!FcCacheWriteStringOld (stdout, base))
            goto bail3;
        if (PUTC (' ', stdout) == EOF)
@@ -343,6 +264,8 @@ FcCachePrintSet (FcFontSet *set, FcStrSet *dirs, char *cache_file)
        if (PUTC ('\n', stdout) == EOF)
            goto bail3;
     }
+    if (verbose && !set->nfont && !ndir)
+       printf ("<empty>\n");
     
     FcStrListDone (list);
 
@@ -354,19 +277,50 @@ bail2:
     return FcFalse;
 }
 
+FcCache *
+FcCacheFileMap (const FcChar8 *file)
+{
+    FcCache *cache;
+    int            fd;
+    struct stat file_stat;
+
+    fd = open (file, O_RDONLY | O_BINARY);
+    if (fd < 0)
+       return NULL;
+    if (fstat (fd, &file_stat) < 0) {
+       close (fd);
+       return NULL;
+    }
+    if (!FcDirCacheLoad (fd, file_stat.st_size, &cache)) {
+       close (fd);
+       return NULL;
+    }
+    close (fd);
+    return cache;
+}
+
 int
 main (int argc, char **argv)
 {
     int                i;
+    int                ret = 0;
+    FcFontSet  *fs;
+    FcStrSet    *dirs;
+    FcStrSet   *args = NULL;
+    FcStrList  *arglist;
+    FcCache    *cache;
+    FcConfig   *config;
+    FcChar8    *arg;
+    int                verbose = 0;
+    int                recurse = 0;
+    FcBool     first = FcTrue;
 #if HAVE_GETOPT_LONG || HAVE_GETOPT
     int                c;
-    FcFontSet  *fs = FcFontSetCreate();
-    FcStrSet    *dirs = FcStrSetCreate();
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "fsVv?", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "Vvr?", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "fsVv?")) != -1)
+    while ((c = getopt (argc, argv, "Vvr?")) != -1)
 #endif
     {
        switch (c) {
@@ -374,6 +328,12 @@ main (int argc, char **argv)
            fprintf (stderr, "fontconfig version %d.%d.%d\n", 
                     FC_MAJOR, FC_MINOR, FC_REVISION);
            exit (0);
+       case 'v':
+           verbose++;
+           break;
+       case 'r':
+           recurse++;
+           break;
        default:
            usage (argv[0]);
        }
@@ -383,22 +343,104 @@ main (int argc, char **argv)
     i = 1;
 #endif
 
-    if (i >= argc)
-        usage (argv[0]);
-
-    if (FcCacheFileRead (fs, dirs, dirname (strdup(argv[i])), argv[i]))
-       FcCachePrintSet (fs, dirs, argv[i]);
+    config = FcInitLoadConfig ();
+    if (!config)
+    {
+       fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
+       return 1;
+    }
+    FcConfigSetCurrent (config);
+    
+    args = FcStrSetCreate ();
+    if (!args)
+    {
+       fprintf (stderr, "%s: malloc failure\n", argv[0]);
+       return 1;
+    }
+    if (i < argc)
+    {
+       for (; i < argc; i++)
+       {
+           if (!FcStrSetAdd (args, argv[i]))
+           {
+               fprintf (stderr, "%s: malloc failure\n", argv[0]);
+               return 1;
+           }
+       }
+       arglist = FcStrListCreate (args);
+       if (!arglist)
+       {
+           fprintf (stderr, "%s: malloc failure\n", argv[0]);
+           return 1;
+       }
+    }
     else
     {
-        FcStrSetDestroy (dirs);
-        dirs = FcStrSetCreate ();
-        if (FcCacheGlobalFileReadAndPrint (fs, dirs, dirname (strdup (argv[i])),
-                                           argv[i]))
-            ;
+       recurse++;
+       arglist = FcConfigGetFontDirs (config);
+       while ((arg = FcStrListNext (arglist)))
+           if (!FcStrSetAdd (args, arg))
+           {
+               fprintf (stderr, "%s: malloc failure\n", argv[0]);
+               return 1;
+           }
+       FcStrListDone (arglist);
     }
+    arglist = FcStrListCreate (args);
+    if (!arglist)
+    {
+       fprintf (stderr, "%s: malloc failure\n", argv[0]);
+       return 1;
+    }
+
+    while ((arg = FcStrListNext (arglist)))
+    {
+       int         j;
+       off_t       size;
+       intptr_t    *cache_dirs;
+       FcChar8     *cache_file = NULL;
+       
+       if (FcFileIsDir (arg))
+           cache = FcDirCacheMap (arg, config, &cache_file);
+       else
+           cache = FcCacheFileMap (arg);
+       if (!cache)
+       {
+           perror ((char *) arg);
+           ret++;
+           continue;
+       }
+       
+       dirs = FcStrSetCreate ();
+       fs = FcCacheSet (cache);
+       cache_dirs = FcCacheDirs (cache);
+       for (j = 0; j < cache->dirs_count; j++) 
+       {
+           FcStrSetAdd (dirs, FcOffsetToPtr (cache_dirs,
+                                             cache_dirs[j],
+                                             FcChar8));
+           if (recurse)
+               FcStrSetAdd (args, FcOffsetToPtr (cache_dirs,
+                                             cache_dirs[j],
+                                             FcChar8));
+       }
 
-    FcStrSetDestroy (dirs);
-    FcFontSetDestroy (fs);
+       if (verbose)
+       {
+           if (!first)
+               printf ("\n");
+           printf ("Directory: %s\nCache: %s\n--------\n",
+                   FcCacheDir(cache), cache_file ? cache_file : arg);
+           first = FcFalse;
+       }
+        FcCachePrintSet (fs, dirs, FcCacheDir (cache), verbose);
+
+       FcStrSetDestroy (dirs);
+
+       FcDirCacheUnmap (cache);
+       if (cache_file)
+           FcStrFree (cache_file);
+    }
 
     return 0;
 }