fcdir.c revision b09479dc
1/* 2 * fontconfig/src/fcdir.c 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 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. 15 * 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. 23 */ 24 25#include "fcint.h" 26#include <dirent.h> 27 28FcBool 29FcFileIsDir (const FcChar8 *file) 30{ 31 struct stat statb; 32 33 if (FcStat (file, &statb) != 0) 34 return FcFalse; 35 return S_ISDIR(statb.st_mode); 36} 37 38FcBool 39FcFileIsLink (const FcChar8 *file) 40{ 41#if HAVE_LSTAT 42 struct stat statb; 43 44 if (lstat ((const char *)file, &statb) != 0) 45 return FcFalse; 46 return S_ISLNK (statb.st_mode); 47#else 48 return FcFalse; 49#endif 50} 51 52FcBool 53FcFileIsFile (const FcChar8 *file) 54{ 55 struct stat statb; 56 57 if (FcStat (file, &statb) != 0) 58 return FcFalse; 59 return S_ISREG (statb.st_mode); 60} 61 62static FcBool 63FcFileScanFontConfig (FcFontSet *set, 64 FcBlanks *blanks, 65 const FcChar8 *file, 66 FcConfig *config) 67{ 68 FcPattern *font; 69 FcBool ret = FcTrue; 70 int id; 71 int count = 0; 72 73 id = 0; 74 do 75 { 76 font = 0; 77 /* 78 * Nothing in the cache, scan the file 79 */ 80 if (FcDebug () & FC_DBG_SCAN) 81 { 82 printf ("\tScanning file %s...", file); 83 fflush (stdout); 84 } 85 font = FcFreeTypeQuery (file, id, blanks, &count); 86 if (FcDebug () & FC_DBG_SCAN) 87 printf ("done\n"); 88 89 /* 90 * Edit pattern with user-defined rules 91 */ 92 if (font && config && !FcConfigSubstitute (config, font, FcMatchScan)) 93 { 94 FcPatternDestroy (font); 95 font = NULL; 96 ret = FcFalse; 97 } 98 99 /* 100 * Add the font 101 */ 102 if (font) 103 { 104 if (FcDebug() & FC_DBG_SCANV) 105 { 106 printf ("Final font pattern:\n"); 107 FcPatternPrint (font); 108 } 109 if (!FcFontSetAdd (set, font)) 110 { 111 FcPatternDestroy (font); 112 font = NULL; 113 ret = FcFalse; 114 } 115 } 116 else if (font) 117 FcPatternDestroy (font); 118 id++; 119 } while (font && ret && id < count); 120 return ret; 121} 122 123FcBool 124FcFileScanConfig (FcFontSet *set, 125 FcStrSet *dirs, 126 FcBlanks *blanks, 127 const FcChar8 *file, 128 FcConfig *config) 129{ 130 if (FcFileIsDir (file)) 131 return FcStrSetAdd (dirs, file); 132 else 133 { 134 if (set) 135 return FcFileScanFontConfig (set, blanks, file, config); 136 else 137 return FcTrue; 138 } 139} 140 141FcBool 142FcFileScan (FcFontSet *set, 143 FcStrSet *dirs, 144 FcFileCache *cache FC_UNUSED, 145 FcBlanks *blanks, 146 const FcChar8 *file, 147 FcBool force FC_UNUSED) 148{ 149 return FcFileScanConfig (set, dirs, blanks, file, FcConfigGetCurrent ()); 150} 151 152/* 153 * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage 154 */ 155static int 156cmpstringp(const void *p1, const void *p2) 157{ 158 return strcmp(* (char **) p1, * (char **) p2); 159} 160 161FcBool 162FcDirScanConfig (FcFontSet *set, 163 FcStrSet *dirs, 164 FcBlanks *blanks, 165 const FcChar8 *dir, 166 FcBool force, /* XXX unused */ 167 FcConfig *config) 168{ 169 DIR *d; 170 struct dirent *e; 171 FcStrSet *files; 172 FcChar8 *file; 173 FcChar8 *base; 174 FcBool ret = FcTrue; 175 int i; 176 177 if (!force) 178 return FcFalse; 179 180 if (!set && !dirs) 181 return FcTrue; 182 183 if (!blanks) 184 blanks = FcConfigGetBlanks (config); 185 186 /* freed below */ 187 file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1); 188 if (!file) { 189 ret = FcFalse; 190 goto bail; 191 } 192 193 strcpy ((char *) file, (char *) dir); 194 strcat ((char *) file, "/"); 195 base = file + strlen ((char *) file); 196 197 if (FcDebug () & FC_DBG_SCAN) 198 printf ("\tScanning dir %s\n", dir); 199 200 d = opendir ((char *) dir); 201 if (!d) 202 { 203 /* Don't complain about missing directories */ 204 if (errno != ENOENT) 205 ret = FcFalse; 206 goto bail; 207 } 208 209 files = FcStrSetCreate (); 210 if (!files) 211 { 212 ret = FcFalse; 213 goto bail1; 214 } 215 while ((e = readdir (d))) 216 { 217 if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN) 218 { 219 strcpy ((char *) base, (char *) e->d_name); 220 if (!FcStrSetAdd (files, file)) { 221 ret = FcFalse; 222 goto bail2; 223 } 224 } 225 } 226 227 /* 228 * Sort files to make things prettier 229 */ 230 qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp); 231 232 /* 233 * Scan file files to build font patterns 234 */ 235 for (i = 0; i < files->num; i++) 236 FcFileScanConfig (set, dirs, blanks, files->strs[i], config); 237 238bail2: 239 FcStrSetDestroy (files); 240bail1: 241 closedir (d); 242bail: 243 if (file) 244 free (file); 245 246 return ret; 247} 248 249FcBool 250FcDirScan (FcFontSet *set, 251 FcStrSet *dirs, 252 FcFileCache *cache, /* XXX unused */ 253 FcBlanks *blanks, 254 const FcChar8 *dir, 255 FcBool force /* XXX unused */) 256{ 257 if (cache || !force) 258 return FcFalse; 259 260 return FcDirScanConfig (set, dirs, blanks, dir, force, FcConfigGetCurrent ()); 261} 262 263/* 264 * Scan the specified directory and construct a cache of its contents 265 */ 266FcCache * 267FcDirCacheScan (const FcChar8 *dir, FcConfig *config) 268{ 269 FcStrSet *dirs; 270 FcFontSet *set; 271 FcCache *cache = NULL; 272 struct stat dir_stat; 273 274 if (FcDebug () & FC_DBG_FONTSET) 275 printf ("cache scan dir %s\n", dir); 276 277 if (FcStatChecksum (dir, &dir_stat) < 0) 278 goto bail; 279 280 set = FcFontSetCreate(); 281 if (!set) 282 goto bail; 283 284 dirs = FcStrSetCreate (); 285 if (!dirs) 286 goto bail1; 287 288 /* 289 * Scan the dir 290 */ 291 if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config)) 292 goto bail2; 293 294 /* 295 * Build the cache object 296 */ 297 cache = FcDirCacheBuild (set, dir, &dir_stat, dirs); 298 if (!cache) 299 goto bail2; 300 301 /* 302 * Write out the cache file, ignoring any troubles 303 */ 304 FcDirCacheWrite (cache, config); 305 306 bail2: 307 FcStrSetDestroy (dirs); 308 bail1: 309 FcFontSetDestroy (set); 310 bail: 311 return cache; 312} 313 314FcCache * 315FcDirCacheRescan (const FcChar8 *dir, FcConfig *config) 316{ 317 FcCache *cache = FcDirCacheLoad (dir, config, NULL); 318 FcCache *new = NULL; 319 struct stat dir_stat; 320 FcStrSet *dirs; 321 322 if (!cache) 323 return NULL; 324 if (FcStatChecksum (dir, &dir_stat) < 0) 325 goto bail; 326 dirs = FcStrSetCreate (); 327 if (!dirs) 328 goto bail; 329 330 /* 331 * Scan the dir 332 */ 333 if (!FcDirScanConfig (NULL, dirs, NULL, dir, FcTrue, config)) 334 goto bail1; 335 /* 336 * Rebuild the cache object 337 */ 338 new = FcDirCacheRebuild (cache, &dir_stat, dirs); 339 if (!new) 340 goto bail1; 341 FcDirCacheUnload (cache); 342 /* 343 * Write out the cache file, ignoring any troubles 344 */ 345 FcDirCacheWrite (new, config); 346 347bail1: 348 FcStrSetDestroy (dirs); 349bail: 350 return new; 351} 352 353/* 354 * Read (or construct) the cache for a directory 355 */ 356FcCache * 357FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config) 358{ 359 FcCache *cache = NULL; 360 361 /* Try to use existing cache file */ 362 if (!force) 363 cache = FcDirCacheLoad (dir, config, NULL); 364 365 /* Not using existing cache file, construct new cache */ 366 if (!cache) 367 cache = FcDirCacheScan (dir, config); 368 369 return cache; 370} 371 372FcBool 373FcDirSave (FcFontSet *set FC_UNUSED, FcStrSet * dirs FC_UNUSED, const FcChar8 *dir FC_UNUSED) 374{ 375 return FcFalse; /* XXX deprecated */ 376} 377#define __fcdir__ 378#include "fcaliastail.h" 379#undef __fcdir__ 380