2 * fontconfig/src/fcdir.c
4 * Copyright © 2000 Keith Packard
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 the author(s) not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. The authors make no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) 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.
32 FcFileIsDir (const FcChar8 *file)
36 if (FcStat (file, &statb) != 0)
38 return S_ISDIR(statb.st_mode);
42 FcFileIsLink (const FcChar8 *file)
47 if (lstat ((const char *)file, &statb) != 0)
49 return S_ISLNK (statb.st_mode);
56 FcFileIsFile (const FcChar8 *file)
60 if (FcStat (file, &statb) != 0)
62 return S_ISREG (statb.st_mode);
66 FcFileScanFontConfig (FcFontSet *set,
72 int old_nfont = set->nfont;
73 const FcChar8 *sysroot = FcConfigGetSysRoot (config);
75 if (FcDebug () & FC_DBG_SCAN)
77 printf ("\tScanning file %s...", file);
81 if (!FcFreeTypeQueryAll (file, -1, NULL, NULL, set))
84 if (FcDebug () & FC_DBG_SCAN)
87 for (i = old_nfont; i < set->nfont; i++)
89 FcPattern *font = set->fonts[i];
92 * Get rid of sysroot here so that targeting scan rule may contains FC_FILE pattern
93 * and they should usually expect without sysroot.
97 size_t len = strlen ((const char *)sysroot);
100 if (FcPatternObjectGetString (font, FC_FILE_OBJECT, 0, &f) == FcResultMatch &&
101 strncmp ((const char *)f, (const char *)sysroot, len) == 0)
103 FcChar8 *s = FcStrdup (f);
104 FcPatternObjectDel (font, FC_FILE_OBJECT);
107 else if (s[len+1] == '/')
109 FcPatternObjectAddString (font, FC_FILE_OBJECT, &s[len]);
115 * Edit pattern with user-defined rules
117 if (config && !FcConfigSubstitute (config, font, FcMatchScan))
120 if (FcDebug() & FC_DBG_SCANV)
122 printf ("Final font pattern:\n");
123 FcPatternPrint (font);
131 FcFileScanConfig (FcFontSet *set,
136 if (FcFileIsDir (file))
138 const FcChar8 *sysroot = FcConfigGetSysRoot (config);
139 const FcChar8 *d = file;
144 len = strlen ((const char *)sysroot);
145 if (strncmp ((const char *)file, (const char *)sysroot, len) == 0)
147 if (file[len] != '/')
149 else if (file[len+1] == '/')
154 return FcStrSetAdd (dirs, d);
159 return FcFileScanFontConfig (set, file, config);
166 FcFileScan (FcFontSet *set,
168 FcFileCache *cache FC_UNUSED,
169 FcBlanks *blanks FC_UNUSED,
171 FcBool force FC_UNUSED)
176 config = FcConfigReference (NULL);
179 ret = FcFileScanConfig (set, dirs, file, config);
180 FcConfigDestroy (config);
186 * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
189 cmpstringp(const void *p1, const void *p2)
191 return strcmp(* (char **) p1, * (char **) p2);
195 FcDirScanConfig (FcFontSet *set,
198 FcBool force, /* XXX unused */
204 FcChar8 *file_prefix, *s_dir = NULL;
206 const FcChar8 *sysroot = FcConfigGetSysRoot (config);
217 file_prefix = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
222 strcpy ((char *) file_prefix, (char *) dir);
223 strcat ((char *) file_prefix, FC_DIR_SEPARATOR_S);
224 base = file_prefix + strlen ((char *) file_prefix);
227 s_dir = FcStrBuildFilename (sysroot, dir, NULL);
229 s_dir = FcStrdup (dir);
235 if (FcDebug () & FC_DBG_SCAN)
236 printf ("\tScanning dir %s\n", s_dir);
238 d = opendir ((char *) s_dir);
241 /* Don't complain about missing directories */
247 files = FcStrSetCreateEx (FCSS_ALLOW_DUPLICATES | FCSS_GROW_BY_64);
253 while ((e = readdir (d)))
255 if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
257 strcpy ((char *) base, (char *) e->d_name);
258 if (!FcStrSetAdd (files, file_prefix)) {
266 * Sort files to make things prettier
268 qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp);
271 * Scan file files to build font patterns
273 for (i = 0; i < files->num; i++)
274 FcFileScanConfig (set, dirs, files->strs[i], config);
277 FcStrSetDestroy (files);
290 FcDirScan (FcFontSet *set,
292 FcFileCache *cache FC_UNUSED,
293 FcBlanks *blanks FC_UNUSED,
295 FcBool force FC_UNUSED)
303 config = FcConfigReference (NULL);
306 ret = FcDirScanConfig (set, dirs, dir, force, config);
307 FcConfigDestroy (config);
313 * Scan the specified directory and construct a cache of its contents
316 FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
320 FcCache *cache = NULL;
321 struct stat dir_stat;
322 const FcChar8 *sysroot = FcConfigGetSysRoot (config);
329 d = FcStrBuildFilename (sysroot, dir, NULL);
333 if (FcDebug () & FC_DBG_FONTSET)
334 printf ("cache scan dir %s\n", d);
336 if (FcStatChecksum (d, &dir_stat) < 0)
339 set = FcFontSetCreate();
343 dirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
348 fd = FcDirCacheLock (dir, config);
353 /* Do not pass sysroot here. FcDirScanConfig() do take care of it */
354 if (!FcDirScanConfig (set, dirs, dir, FcTrue, config))
358 * Build the cache object
360 cache = FcDirCacheBuild (set, dir, &dir_stat, dirs);
365 * Write out the cache file, ignoring any troubles
367 FcDirCacheWrite (cache, config);
371 FcDirCacheUnlock (fd);
373 FcStrSetDestroy (dirs);
375 FcFontSetDestroy (set);
383 FcDirCacheRescan (const FcChar8 *dir, FcConfig *config)
387 struct stat dir_stat;
389 const FcChar8 *sysroot;
395 config = FcConfigReference (config);
398 sysroot = FcConfigGetSysRoot (config);
399 cache = FcDirCacheLoad (dir, config, NULL);
404 d = FcStrBuildFilename (sysroot, dir, NULL);
407 if (FcStatChecksum (d, &dir_stat) < 0)
409 dirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
414 fd = FcDirCacheLock (dir, config);
419 /* Do not pass sysroot here. FcDirScanConfig() do take care of it */
420 if (!FcDirScanConfig (NULL, dirs, dir, FcTrue, config))
423 * Rebuild the cache object
425 new = FcDirCacheRebuild (cache, &dir_stat, dirs);
428 FcDirCacheUnload (cache);
430 * Write out the cache file, ignoring any troubles
432 FcDirCacheWrite (new, config);
436 FcDirCacheUnlock (fd);
438 FcStrSetDestroy (dirs);
442 FcConfigDestroy (config);
448 * Read (or construct) the cache for a directory
451 FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config)
453 FcCache *cache = NULL;
455 config = FcConfigReference (config);
456 /* Try to use existing cache file */
458 cache = FcDirCacheLoad (dir, config, NULL);
460 /* Not using existing cache file, construct new cache */
462 cache = FcDirCacheScan (dir, config);
463 FcConfigDestroy (config);
469 FcDirSave (FcFontSet *set FC_UNUSED, FcStrSet * dirs FC_UNUSED, const FcChar8 *dir FC_UNUSED)
471 return FcFalse; /* XXX deprecated */
474 #include "fcaliastail.h"