]> git.wh0rd.org - fontconfig.git/blob - src/fcdir.c
Eliminate ./ and ../ elements from font directory names when scanning.
[fontconfig.git] / src / fcdir.c
1 /*
2 * $RCSId: xc/lib/fontconfig/src/fcdir.c,v 1.9 2002/08/31 22:17:32 keithp Exp $
3 *
4 * Copyright © 2000 Keith Packard
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 "fcint.h"
26 #include <dirent.h>
27
28 FcBool
29 FcFileIsDir (const FcChar8 *file)
30 {
31 struct stat statb;
32
33 if (stat ((const char *) file, &statb) != 0)
34 return FcFalse;
35 return S_ISDIR(statb.st_mode);
36 }
37
38 static FcBool
39 FcFileScanFontConfig (FcFontSet *set,
40 FcBlanks *blanks,
41 const FcChar8 *file,
42 FcConfig *config)
43 {
44 FcPattern *font;
45 FcBool ret = FcTrue;
46 int id;
47 int count = 0;
48
49 id = 0;
50 do
51 {
52 font = 0;
53 /*
54 * Nothing in the cache, scan the file
55 */
56 if (FcDebug () & FC_DBG_SCAN)
57 {
58 printf ("\tScanning file %s...", file);
59 fflush (stdout);
60 }
61 font = FcFreeTypeQuery (file, id, blanks, &count);
62 if (FcDebug () & FC_DBG_SCAN)
63 printf ("done\n");
64 /*
65 * Add the font
66 */
67 if (font && (!config || FcConfigAcceptFont (config, font)))
68 {
69 if (!FcFontSetAdd (set, font))
70 {
71 FcPatternDestroy (font);
72 font = 0;
73 ret = FcFalse;
74 }
75 }
76 else if (font)
77 FcPatternDestroy (font);
78 id++;
79 } while (font && ret && id < count);
80 return ret;
81 }
82
83 FcBool
84 FcFileScanConfig (FcFontSet *set,
85 FcStrSet *dirs,
86 FcBlanks *blanks,
87 const FcChar8 *file,
88 FcBool force,
89 FcConfig *config)
90 {
91 if (config && !FcConfigAcceptFilename (config, file))
92 return FcTrue;
93
94 if (FcFileIsDir (file))
95 return FcStrSetAdd (dirs, file);
96 else
97 return FcFileScanFontConfig (set, blanks, file, config);
98 }
99
100 FcBool
101 FcFileScan (FcFontSet *set,
102 FcStrSet *dirs,
103 FcFileCache *cache, /* XXX unused */
104 FcBlanks *blanks,
105 const FcChar8 *file,
106 FcBool force)
107 {
108 return FcFileScanConfig (set, dirs, blanks, file, force, 0);
109 }
110
111 /*
112 * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
113 */
114
115 static int
116 cmpstringp(const void *p1, const void *p2)
117 {
118 return strcmp(* (char **) p1, * (char **) p2);
119 }
120
121 /*
122 * Scan 'dir', adding font files to 'set' and
123 * subdirectories to 'dirs'
124 */
125
126 FcBool
127 FcDirScanConfig (FcFontSet *set,
128 FcStrSet *dirs,
129 FcBlanks *blanks,
130 const FcChar8 *dir,
131 FcBool force,
132 FcConfig *config)
133 {
134 DIR *d;
135 FcChar8 *canon_dir;
136 struct dirent *e;
137 FcStrSet *dirlist, *filelist;
138 FcChar8 *file;
139 FcChar8 *base;
140 FcBool ret = FcTrue;
141 FcFontSet *tmpSet;
142 int i;
143
144 canon_dir = FcStrCanonFilename (dir);
145 if (!canon_dir) canon_dir = (FcChar8 *) dir;
146 printf ("dir %s canon %s\n", dir, canon_dir);
147
148 if (config && !FcConfigAcceptFilename (config, canon_dir)) {
149 ret = FcTrue;
150 goto bail;
151 }
152
153 if (!force)
154 {
155 if (FcDirCacheRead (set, dirs, canon_dir, config)) {
156 ret = FcTrue;
157 goto bail;
158 }
159 }
160
161 if (FcDebug () & FC_DBG_FONTSET)
162 printf ("cache scan dir %s\n", canon_dir);
163
164 /* freed below */
165 file = (FcChar8 *) malloc (strlen ((char *) canon_dir) + 1 + FC_MAX_FILE_LEN + 1);
166 if (!file) {
167 ret = FcFalse;
168 goto bail;
169 }
170
171 strcpy ((char *) file, (char *) canon_dir);
172 strcat ((char *) file, "/");
173 base = file + strlen ((char *) file);
174
175 if (FcDebug () & FC_DBG_SCAN)
176 printf ("\tScanning dir %s\n", canon_dir);
177
178 d = opendir ((char *) canon_dir);
179 if (!d)
180 {
181 /* Don't complain about missing directories */
182 if (errno == ENOENT)
183 ret = FcTrue;
184 else
185 ret = FcFalse;
186 goto bail_1;
187 }
188
189 tmpSet = FcFontSetCreate();
190 if (!tmpSet)
191 {
192 ret = FcFalse;
193 goto bail0;
194 }
195
196 dirlist = FcStrSetCreate ();
197 if (!dirlist)
198 {
199 ret = FcFalse;
200 goto bail1;
201 }
202 filelist = FcStrSetCreate ();
203 if (!filelist)
204 {
205 ret = FcFalse;
206 goto bail2;
207 }
208 while ((e = readdir (d)))
209 {
210 if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
211 {
212 strcpy ((char *) base, (char *) e->d_name);
213 if (FcFileIsDir (file)) {
214 if (!FcStrSetAdd (dirlist, file)) {
215 ret = FcFalse;
216 goto bail3;
217 }
218 } else {
219 if (!FcStrSetAdd (filelist, file)) {
220 ret = FcFalse;
221 goto bail3;
222 }
223 }
224 }
225 }
226 /*
227 * Sort files and dirs to make things prettier
228 */
229 qsort(dirlist->strs, dirlist->num, sizeof(FcChar8 *), cmpstringp);
230 qsort(filelist->strs, filelist->num, sizeof(FcChar8 *), cmpstringp);
231
232 for (i = 0; i < filelist->num; i++)
233 FcFileScanFontConfig (tmpSet, blanks, filelist->strs[i], config);
234
235 /*
236 * Now that the directory has been scanned,
237 * write out the cache file
238 */
239 FcDirCacheWrite (tmpSet, dirlist, canon_dir, config);
240
241 /*
242 * Add the discovered fonts to our internal non-cache list
243 */
244 for (i = 0; i < tmpSet->nfont; i++)
245 FcFontSetAdd (set, tmpSet->fonts[i]);
246
247 /*
248 * the patterns in tmpset now belong to set; don't free them
249 */
250 tmpSet->nfont = 0;
251
252 /*
253 * Add the discovered directories to the list to be scanned
254 */
255 for (i = 0; i < dirlist->num; i++)
256 if (!FcStrSetAdd (dirs, dirlist->strs[i])) {
257 ret = FcFalse;
258 goto bail3;
259 }
260
261 bail3:
262 FcStrSetDestroy (filelist);
263 bail2:
264 FcStrSetDestroy (dirlist);
265 bail1:
266 FcFontSetDestroy (tmpSet);
267
268 bail0:
269 closedir (d);
270
271 bail_1:
272 free (file);
273 bail:
274 if (canon_dir != dir) free (canon_dir);
275 return ret;
276 }
277
278 FcBool
279 FcDirScan (FcFontSet *set,
280 FcStrSet *dirs,
281 FcFileCache *cache, /* XXX unused */
282 FcBlanks *blanks,
283 const FcChar8 *dir,
284 FcBool force)
285 {
286 return FcDirScanConfig (set, dirs, blanks, dir, force, 0);
287 }
288
289 FcBool
290 FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
291 {
292 return FcDirCacheWrite (set, dirs, dir, FcConfigGetCurrent ());
293 }