]> git.wh0rd.org Git - fontconfig.git/blob - fc-cache/fc-cache.c
Have fc-cache skip directories without write access
[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 }