]> git.wh0rd.org - fontconfig.git/blob - fc-cache/fc-cache.c
78418d786c4cc0844f86ba1c3f41da1e9fc8a7be
[fontconfig.git] / fc-cache / fc-cache.c
1 /*
2 * $XFree86: xc/lib/fontconfig/fc-cache/fc-cache.c,v 1.8tsi 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 <stdlib.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #else
35 #ifdef linux
36 #define HAVE_GETOPT_LONG 1
37 #endif
38 #define HAVE_GETOPT 1
39 #endif
40
41 #ifndef HAVE_GETOPT
42 #define HAVE_GETOPT 0
43 #endif
44 #ifndef HAVE_GETOPT_LONG
45 #define HAVE_GETOPT_LONG 0
46 #endif
47
48 #if HAVE_GETOPT_LONG
49 #undef _GNU_SOURCE
50 #define _GNU_SOURCE
51 #include <getopt.h>
52 const struct option longopts[] = {
53 {"force", 0, 0, 'f'},
54 {"system-only", 0, 0, 's'},
55 {"version", 0, 0, 'V'},
56 {"verbose", 0, 0, 'v'},
57 {"help", 0, 0, '?'},
58 {NULL,0,0,0},
59 };
60 #else
61 #if HAVE_GETOPT
62 extern char *optarg;
63 extern int optind, opterr, optopt;
64 #endif
65 #endif
66
67 static void
68 usage (char *program)
69 {
70 fprintf (stderr, "usage: %s [-fvV?] [--force] [--verbose] [--version] [--help] [dirs]\n",
71 program);
72 fprintf (stderr, "Build font information caches in [dirs]\n"
73 "(all directories in font configuration by default).\n");
74 fprintf (stderr, "\n");
75 fprintf (stderr, " -f, --force scan directories with apparently valid caches\n");
76 fprintf (stderr, " -s, --system-only scan system-wide directories only\n");
77 fprintf (stderr, " -v, --verbose display status information while busy\n");
78 fprintf (stderr, " -V, --version display font config version and exit\n");
79 fprintf (stderr, " -?, --help display this help and exit\n");
80 exit (1);
81 }
82
83 static int
84 nsubdirs (FcStrSet *set)
85 {
86 FcStrList *list;
87 int n = 0;
88
89 list = FcStrListCreate (set);
90 if (!list)
91 return 0;
92 while (FcStrListNext (list))
93 n++;
94 FcStrListDone (list);
95 return n;
96 }
97
98 static int
99 scanDirs (FcStrList *list, FcConfig *config, char *program, FcBool force, FcBool verbose)
100 {
101 int ret = 0;
102 FcChar8 *dir;
103 FcFontSet *set;
104 FcStrSet *subdirs;
105 FcStrList *sublist;
106 struct stat statb;
107
108 /*
109 * Now scan all of the directories into separate databases
110 * and write out the results
111 */
112 while ((dir = FcStrListNext (list)))
113 {
114 if (verbose)
115 {
116 printf ("%s: \"%s\": ", program, dir);
117 fflush (stdout);
118 }
119 set = FcFontSetCreate ();
120 if (!set)
121 {
122 fprintf (stderr, "Can't create font set\n");
123 ret++;
124 continue;
125 }
126 subdirs = FcStrSetCreate ();
127 if (!subdirs)
128 {
129 fprintf (stderr, "Can't create directory set\n");
130 ret++;
131 continue;
132 }
133
134 if (access ((char *) dir, W_OK) < 0)
135 {
136 switch (errno) {
137 case ENOENT:
138 case ENOTDIR:
139 if (verbose)
140 printf ("skipping, no such directory\n");
141 break;
142 case EACCES:
143 case EROFS:
144 if (verbose)
145 printf ("skipping, no write access\n");
146 break;
147 default:
148 fprintf (stderr, "\"%s\": ", dir);
149 perror ("");
150 ret++;
151 }
152 continue;
153 }
154 if (stat ((char *) dir, &statb) == -1)
155 {
156 fprintf (stderr, "\"%s\": ", dir);
157 perror ("");
158 ret++;
159 continue;
160 }
161 if (!S_ISDIR (statb.st_mode))
162 {
163 fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
164 continue;
165 }
166 if (!FcDirScan (set, subdirs, 0, FcConfigGetBlanks (config), dir, force))
167 {
168 fprintf (stderr, "\"%s\": error scanning\n", dir);
169 ret++;
170 continue;
171 }
172 if (!force && FcDirCacheValid (dir))
173 {
174 if (verbose)
175 printf ("skipping, %d fonts, %d dirs\n",
176 set->nfont, nsubdirs(subdirs));
177 }
178 else
179 {
180 if (verbose)
181 printf ("caching, %d fonts, %d dirs\n",
182 set->nfont, nsubdirs (subdirs));
183 if (!FcDirSave (set, subdirs, dir))
184 {
185 fprintf (stderr, "Can't save cache in \"%s\"\n", dir);
186 ret++;
187 }
188 }
189 FcFontSetDestroy (set);
190 sublist = FcStrListCreate (subdirs);
191 if (!sublist)
192 {
193 fprintf (stderr, "Can't create subdir list in \"%s\"\n", dir);
194 ret++;
195 continue;
196 }
197 ret += scanDirs (sublist, config, program, force, verbose);
198 FcStrSetDestroy (subdirs);
199 }
200 FcStrListDone (list);
201 return ret;
202 }
203
204 int
205 main (int argc, char **argv)
206 {
207 FcStrSet *dirs;
208 FcStrList *list;
209 FcBool verbose = FcFalse;
210 FcBool force = FcFalse;
211 FcBool systemOnly = FcFalse;
212 FcConfig *config;
213 int i;
214 int ret;
215 #if HAVE_GETOPT_LONG || HAVE_GETOPT
216 int c;
217
218 #if HAVE_GETOPT_LONG
219 while ((c = getopt_long (argc, argv, "fVv?", longopts, NULL)) != -1)
220 #else
221 while ((c = getopt (argc, argv, "fVv?")) != -1)
222 #endif
223 {
224 switch (c) {
225 case 'f':
226 force = FcTrue;
227 break;
228 case 's':
229 systemOnly = FcTrue;
230 break;
231 case 'V':
232 fprintf (stderr, "fontconfig version %d.%d.%d\n",
233 FC_MAJOR, FC_MINOR, FC_REVISION);
234 exit (0);
235 case 'v':
236 verbose = FcTrue;
237 break;
238 default:
239 usage (argv[0]);
240 }
241 }
242 i = optind;
243 #else
244 i = 1;
245 #endif
246
247 if (systemOnly)
248 FcConfigEnableHome (FcFalse);
249 config = FcInitLoadConfig ();
250 if (!config)
251 {
252 fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
253 return 1;
254 }
255 if (argv[i])
256 {
257 dirs = FcStrSetCreate ();
258 if (!dirs)
259 {
260 fprintf (stderr, "%s: Can't create list of directories\n",
261 argv[0]);
262 return 1;
263 }
264 while (argv[i])
265 {
266 if (!FcStrSetAdd (dirs, (FcChar8 *) argv[i]))
267 {
268 fprintf (stderr, "%s: Can't add directory\n", argv[0]);
269 return 1;
270 }
271 i++;
272 }
273 list = FcStrListCreate (dirs);
274 FcStrSetDestroy (dirs);
275 }
276 else
277 list = FcConfigGetConfigDirs (config);
278 ret = scanDirs (list, config, argv[0], force, verbose);
279 if (verbose)
280 printf ("%s: %s\n", argv[0], ret ? "failed" : "succeeded");
281 return ret;
282 }