Make missing font directory messages only displayed when verbose
[platform/upstream/fontconfig.git] / fc-cache / fc-cache.c
1 /*
2  * $XFree86: xc/lib/fontconfig/fc-cache/fc-cache.c,v 1.7 2002/08/11 15:09:33 keithp Exp $
3  *
4  * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Keith Packard not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission.  Keith Packard makes no
13  * representations about the suitability of this software for any purpose.  It
14  * is provided "as is" without express or implied warranty.
15  *
16  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24
25 #include <fontconfig/fontconfig.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #else
34 #ifdef linux
35 #define HAVE_GETOPT_LONG 1
36 #endif
37 #define HAVE_GETOPT 1
38 #endif
39
40 #ifndef HAVE_GETOPT
41 #define HAVE_GETOPT 0
42 #endif
43 #ifndef HAVE_GETOPT_LONG
44 #define HAVE_GETOPT_LONG 0
45 #endif
46
47 #if HAVE_GETOPT_LONG
48 #undef  _GNU_SOURCE
49 #define _GNU_SOURCE
50 #include <getopt.h>
51 const struct option longopts[] = {
52     {"force", 0, 0, 'f'},
53     {"version", 0, 0, 'V'},
54     {"verbose", 0, 0, 'v'},
55     {"help", 0, 0, '?'},
56     {NULL,0,0,0},
57 };
58 #else
59 #if HAVE_GETOPT
60 extern char *optarg;
61 extern int optind, opterr, optopt;
62 #endif
63 #endif
64
65 static void
66 usage (char *program)
67 {
68     fprintf (stderr, "usage: %s [-fvV?] [--force] [--verbose] [--version] [--help] [dirs]\n",
69              program);
70     fprintf (stderr, "Build font information caches in [dirs]\n"
71              "(all directories in font configuration by default).\n");
72     fprintf (stderr, "\n");
73     fprintf (stderr, "  -f, --force          scan directories with apparently valid caches\n");
74     fprintf (stderr, "  -v, --verbose        display status information while busy\n");
75     fprintf (stderr, "  -V, --version        display font config version and exit\n");
76     fprintf (stderr, "  -?, --help           display this help and exit\n");
77     exit (1);
78 }
79
80 static int
81 nsubdirs (FcStrSet *set)
82 {
83     FcStrList   *list;
84     int         n = 0;
85
86     list = FcStrListCreate (set);
87     if (!list)
88         return 0;
89     while (FcStrListNext (list))
90         n++;
91     FcStrListDone (list);
92     return n;
93 }
94
95 static int
96 scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool verbose)
97 {
98     int         ret = 0;
99     FcChar8     *dir;
100     FcFontSet   *set;
101     FcStrSet    *subdirs;
102     FcStrList   *sublist;
103     struct stat statb;
104     
105     /*
106      * Now scan all of the directories into separate databases
107      * and write out the results
108      */
109     while ((dir = FcStrListNext (list)))
110     {
111         if (verbose)
112         {
113             printf ("%s: \"%s\": ", program, dir);
114             fflush (stdout);
115         }
116         set = FcFontSetCreate ();
117         if (!set)
118         {
119             fprintf (stderr, "Can't create font set\n");
120             ret++;
121             continue;
122         }
123         subdirs = FcStrSetCreate ();
124         if (!subdirs)
125         {
126             fprintf (stderr, "Can't create directory set\n");
127             ret++;
128             continue;
129         }
130         
131         if (stat ((char *) dir, &statb) == -1)
132         {
133             if (errno == ENOENT || errno == ENOTDIR)
134             {
135                 if (verbose)
136                     printf ("no such directory, skipping\n");
137             }
138             else
139             {
140                 fprintf (stderr, "\"%s\": ", dir);
141                 perror ("");
142                 ret++;
143             }
144             continue;
145         }
146         if (!S_ISDIR (statb.st_mode))
147         {
148             fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
149             continue;
150         }
151         if (!FcDirScan (set, subdirs, 0, FcConfigGetBlanks (config), dir, force))
152         {
153             fprintf (stderr, "\"%s\": error scanning\n", dir);
154             ret++;
155             continue;
156         }
157         if (!force && FcDirCacheValid (dir))
158         {
159             if (verbose)
160                 printf ("skipping, %d fonts, %d dirs\n",
161                         set->nfont, nsubdirs(subdirs));
162         }
163         else
164         {
165             if (verbose)
166                 printf ("caching, %d fonts, %d dirs\n", 
167                         set->nfont, nsubdirs (subdirs));
168             if (!FcDirSave (set, subdirs, dir))
169             {
170                 fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
171                 ret++;
172             }
173         }
174         FcFontSetDestroy (set);
175         sublist = FcStrListCreate (subdirs);
176         if (!sublist)
177         {
178             fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
179             ret++;
180             continue;
181         }
182         ret += scanDirs (sublist, config, program, force, verbose);
183         FcStrSetDestroy (subdirs);
184     }
185     FcStrListDone (list);
186     return ret;
187 }
188
189 int
190 main (int argc, char **argv)
191 {
192     FcStrSet    *dirs;
193     FcStrList   *list;
194     FcBool      verbose = FcFalse;
195     FcBool      force = FcFalse;
196     FcConfig    *config;
197     int         i;
198     int         ret;
199 #if HAVE_GETOPT_LONG || HAVE_GETOPT
200     int         c;
201
202 #if HAVE_GETOPT_LONG
203     while ((c = getopt_long (argc, argv, "fVv?", longopts, NULL)) != -1)
204 #else
205     while ((c = getopt (argc, argv, "fVv?")) != -1)
206 #endif
207     {
208         switch (c) {
209         case 'f':
210             force = FcTrue;
211             break;
212         case 'V':
213             fprintf (stderr, "fontconfig version %d.%d.%d\n", 
214                      FC_MAJOR, FC_MINOR, FC_REVISION);
215             exit (0);
216         case 'v':
217             verbose = FcTrue;
218             break;
219         default:
220             usage (argv[0]);
221         }
222     }
223     i = optind;
224 #else
225     i = 1;
226 #endif
227
228     config = FcInitLoadConfig ();
229     if (!config)
230     {
231         fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
232         return 1;
233     }
234     if (argv[i])
235     {
236         dirs = FcStrSetCreate ();
237         if (!dirs)
238         {
239             fprintf (stderr, "%s: Can't create list of directories\n",
240                      argv[0]);
241             return 1;
242         }
243         while (argv[i])
244         {
245             if (!FcStrSetAdd (dirs, (FcChar8 *) argv[i]))
246             {
247                 fprintf (stderr, "%s: Can't add directory\n", argv[0]);
248                 return 1;
249             }
250             i++;
251         }
252         list = FcStrListCreate (dirs);
253         FcStrSetDestroy (dirs);
254     }
255     else
256         list = FcConfigGetConfigDirs (config);
257     ret = scanDirs (list, config, argv[0], force, verbose);
258     if (verbose)
259         printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded");
260     return ret;
261 }