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