]> git.wh0rd.org - fontconfig.git/blobdiff - fc-cache/fc-cache.c
Change RCS tag
[fontconfig.git] / fc-cache / fc-cache.c
index 2bb012d2025174fdbcbd4760dec821dcfa501d79..be8b962596cbdadb20a7a8d85a4447ade22b11b6 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $XFree86: $
+ * $RCSId: xc/lib/fontconfig/fc-cache/fc-cache.c,v 1.8tsi Exp $
  *
- * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2002 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 
 #include <fontconfig/fontconfig.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #else
+#ifdef linux
+#define HAVE_GETOPT_LONG 1
+#endif
 #define HAVE_GETOPT 1
 #endif
 
+#ifndef HAVE_GETOPT
+#define HAVE_GETOPT 0
+#endif
+#ifndef HAVE_GETOPT_LONG
+#define HAVE_GETOPT_LONG 0
+#endif
+
 #if HAVE_GETOPT_LONG
+#undef  _GNU_SOURCE
 #define _GNU_SOURCE
 #include <getopt.h>
 const struct option longopts[] = {
+    {"force", 0, 0, 'f'},
+    {"system-only", 0, 0, 's'},
     {"version", 0, 0, 'V'},
     {"verbose", 0, 0, 'v'},
     {"help", 0, 0, '?'},
@@ -50,41 +67,173 @@ extern int optind, opterr, optopt;
 static void
 usage (char *program)
 {
-    fprintf (stderr, "usage: %s [-vV?] [--verbose] [--version] [--help] [dirs]\n",
+    fprintf (stderr, "usage: %s [-fvV?] [--force] [--verbose] [--version] [--help] [dirs]\n",
             program);
     fprintf (stderr, "Build font information caches in [dirs]\n"
             "(all directories in font configuration by default).\n");
     fprintf (stderr, "\n");
+    fprintf (stderr, "  -f, --force          scan directories with apparently valid caches\n");
+    fprintf (stderr, "  -s, --system-only    scan system-wide directories only\n");
     fprintf (stderr, "  -v, --verbose        display status information while busy\n");
     fprintf (stderr, "  -V, --version        display font config version and exit\n");
     fprintf (stderr, "  -?, --help           display this help and exit\n");
     exit (1);
 }
 
-int
-main (int argc, char **argv)
+static int
+nsubdirs (FcStrSet *set)
+{
+    FcStrList  *list;
+    int                n = 0;
+
+    list = FcStrListCreate (set);
+    if (!list)
+       return 0;
+    while (FcStrListNext (list))
+       n++;
+    FcStrListDone (list);
+    return n;
+}
+
+static int
+scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool verbose)
 {
     int                ret = 0;
+    FcChar8    *dir;
     FcFontSet  *set;
-    FcChar8    **dirs;
-    int                verbose = 0;
+    FcStrSet   *subdirs;
+    FcStrList  *sublist;
+    struct stat        statb;
+    
+    /*
+     * Now scan all of the directories into separate databases
+     * and write out the results
+     */
+    while ((dir = FcStrListNext (list)))
+    {
+       if (verbose)
+       {
+           printf ("%s: \"%s\": ", program, dir);
+           fflush (stdout);
+       }
+       set = FcFontSetCreate ();
+       if (!set)
+       {
+           fprintf (stderr, "Can't create font set\n");
+           ret++;
+           continue;
+       }
+       subdirs = FcStrSetCreate ();
+       if (!subdirs)
+       {
+           fprintf (stderr, "Can't create directory set\n");
+           ret++;
+           continue;
+       }
+       
+       if (access ((char *) dir, W_OK) < 0)
+       {
+           switch (errno) {
+           case ENOENT:
+           case ENOTDIR:
+               if (verbose)
+                   printf ("skipping, no such directory\n");
+               break;
+           case EACCES:
+           case EROFS:
+               if (verbose)
+                   printf ("skipping, no write access\n");
+               break;
+           default:
+               fprintf (stderr, "\"%s\": ", dir);
+               perror ("");
+               ret++;
+           }
+           continue;
+       }
+       if (stat ((char *) dir, &statb) == -1)
+       {
+           fprintf (stderr, "\"%s\": ", dir);
+           perror ("");
+           ret++;
+           continue;
+       }
+       if (!S_ISDIR (statb.st_mode))
+       {
+           fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
+           continue;
+       }
+       if (!FcDirScan (set, subdirs, 0, FcConfigGetBlanks (config), dir, force))
+       {
+           fprintf (stderr, "\"%s\": error scanning\n", dir);
+           ret++;
+           continue;
+       }
+       if (!force && FcDirCacheValid (dir))
+       {
+           if (verbose)
+               printf ("skipping, %d fonts, %d dirs\n",
+                       set->nfont, nsubdirs(subdirs));
+       }
+       else
+       {
+           if (verbose)
+               printf ("caching, %d fonts, %d dirs\n", 
+                       set->nfont, nsubdirs (subdirs));
+           if (!FcDirSave (set, subdirs, dir))
+           {
+               fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
+               ret++;
+           }
+       }
+       FcFontSetDestroy (set);
+       sublist = FcStrListCreate (subdirs);
+       if (!sublist)
+       {
+           fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
+           ret++;
+           continue;
+       }
+       ret += scanDirs (sublist, config, program, force, verbose);
+       FcStrSetDestroy (subdirs);
+    }
+    FcStrListDone (list);
+    return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+    FcStrSet   *dirs;
+    FcStrList  *list;
+    FcBool     verbose = FcFalse;
+    FcBool     force = FcFalse;
+    FcBool     systemOnly = FcFalse;
+    FcConfig   *config;
     int                i;
+    int                ret;
 #if HAVE_GETOPT_LONG || HAVE_GETOPT
     int                c;
 
 #if HAVE_GETOPT_LONG
-    while ((c = getopt_long (argc, argv, "Vv?", longopts, NULL)) != -1)
+    while ((c = getopt_long (argc, argv, "fVv?", longopts, NULL)) != -1)
 #else
-    while ((c = getopt (argc, argv, "Vv?")) != -1)
+    while ((c = getopt (argc, argv, "fVv?")) != -1)
 #endif
     {
        switch (c) {
+       case 'f':
+           force = FcTrue;
+           break;
+       case 's':
+           systemOnly = FcTrue;
+           break;
        case 'V':
            fprintf (stderr, "fontconfig version %d.%d.%d\n", 
                     FC_MAJOR, FC_MINOR, FC_REVISION);
            exit (0);
        case 'v':
-           verbose = 1;
+           verbose = FcTrue;
            break;
        default:
            usage (argv[0]);
@@ -95,51 +244,38 @@ main (int argc, char **argv)
     i = 1;
 #endif
 
-    if (!FcInitConfig ())
+    if (systemOnly)
+       FcConfigEnableHome (FcFalse);
+    config = FcInitLoadConfig ();
+    if (!config)
     {
-       fprintf (stderr, "Can't init font config library\n");
+       fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
        return 1;
     }
     if (argv[i])
-       dirs = (FcChar8 **) (argv+i);
-    else
-       dirs = FcConfigGetDirs (0);
-    /*
-     * Now scan all of the directories into separate databases
-     * and write out the results
-     */
-    while (dirs && *dirs)
     {
-       if (verbose)
-           printf ("%s: Scanning directory \"%s\"\n", argv[0], *dirs);
-       set = FcFontSetCreate ();
-       if (!set)
+       dirs = FcStrSetCreate ();
+       if (!dirs)
        {
-           fprintf (stderr, "Out of memory in \"%s\"\n", *dirs);
-           ret++;
+           fprintf (stderr, "%s: Can't create list of directories\n",
+                    argv[0]);
+           return 1;
        }
-       else
+       while (argv[i])
        {
-           if (!FcDirScan (set, 0, FcConfigGetBlanks (0), *dirs, FcTrue))
+           if (!FcStrSetAdd (dirs, (FcChar8 *) argv[i]))
            {
-               fprintf (stderr, "Can't scan directory \"%s\"\n", *dirs);
-               ret++;
+               fprintf (stderr, "%s: Can't add directory\n", argv[0]);
+               return 1;
            }
-           else
-           {
-               if (verbose)
-                   printf ("%s: Saving %d font names for \"%s\"\n", 
-                           argv[0], set->nfont, *dirs);
-               if (!FcDirSave (set, *dirs))
-               {
-                   fprintf (stderr, "Can't save cache in \"%s\"\n", *dirs);
-                   ret++;
-               }
-           }
-           FcFontSetDestroy (set);
+           i++;
        }
-       ++dirs;
+       list = FcStrListCreate (dirs);
+       FcStrSetDestroy (dirs);
     }
+    else
+       list = FcConfigGetConfigDirs (config);
+    ret = scanDirs (list, config, argv[0], force, verbose);
     if (verbose)
        printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded");
     return ret;