diff --git a/src/fccache.c b/src/fccache.c index 5173e0b..085bd72 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -545,6 +545,26 @@ FcCacheTimeValid (FcCache *cache, struct stat *dir_stat) return cache->checksum == (int) dir_stat->st_mtime; } +static FcBool +FcCacheDirsValid (FcCache *cache) +{ + FcStrSet *dirs = FcStrSetCreate (); + FcBool ret = FcFalse; + + if (!dirs) + goto bail; + if (!FcDirScanOnly (dirs, FcCacheDir (cache))) + goto bail1; + ret = cache->dirs_count == dirs->num; + if (FcDebug () & FC_DBG_CACHE) + printf ("%s: cache: %d, fs: %d\n", FcCacheDir (cache), cache->dirs_count, dirs->num); + +bail1: + FcStrSetDestroy (dirs); +bail: + return ret; +} + /* * Map a cache file into memory */ @@ -559,7 +579,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat) cache = FcCacheFindByStat (fd_stat); if (cache) { - if (FcCacheTimeValid (cache, dir_stat)) + if (FcCacheTimeValid (cache, dir_stat) && + FcCacheDirsValid (cache)) return cache; FcDirCacheUnload (cache); cache = NULL; @@ -611,6 +632,7 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat) cache->version < FC_CACHE_CONTENT_VERSION || cache->size != (intptr_t) fd_stat->st_size || !FcCacheTimeValid (cache, dir_stat) || + !FcCacheDirsValid (cache) || !FcCacheInsert (cache, fd_stat)) { if (allocated) diff --git a/src/fcdir.c b/src/fcdir.c index 3bcd0b8..d11bf42 100644 --- a/src/fcdir.c +++ b/src/fcdir.c @@ -164,7 +164,8 @@ FcDirScanConfig (FcFontSet *set, FcBlanks *blanks, const FcChar8 *dir, FcBool force, /* XXX unused */ - FcConfig *config) + FcConfig *config, + FcBool scanOnly) { DIR *d; struct dirent *e; @@ -180,7 +181,7 @@ FcDirScanConfig (FcFontSet *set, if (!set && !dirs) return FcTrue; - if (!blanks) + if (!blanks && !scanOnly) blanks = FcConfigGetBlanks (config); /* freed below */ @@ -233,7 +234,17 @@ FcDirScanConfig (FcFontSet *set, * Scan file files to build font patterns */ for (i = 0; i < files->num; i++) - FcFileScanConfig (set, dirs, blanks, files->strs[i], config); + { + if (scanOnly) + { + if (FcFileIsDir (files->strs[i])) + FcStrSetAdd (dirs, files->strs[i]); + } + else + { + FcFileScanConfig (set, dirs, blanks, files->strs[i], config); + } + } bail2: FcStrSetDestroy (files); @@ -257,7 +268,14 @@ FcDirScan (FcFontSet *set, if (cache || !force) return FcFalse; - return FcDirScanConfig (set, dirs, blanks, dir, force, FcConfigGetCurrent ()); + return FcDirScanConfig (set, dirs, blanks, dir, force, FcConfigGetCurrent (), FcFalse); +} + +FcBool +FcDirScanOnly (FcStrSet *dirs, + const FcChar8 *dir) +{ + return FcDirScanConfig (NULL, dirs, NULL, dir, FcTrue, NULL, FcTrue); } /* @@ -266,7 +284,7 @@ FcDirScan (FcFontSet *set, FcCache * FcDirCacheScan (const FcChar8 *dir, FcConfig *config) { - FcStrSet *dirs; + FcStrSet *dirs, *dirs2; FcFontSet *set; FcCache *cache = NULL; struct stat dir_stat; @@ -274,6 +292,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config) if (FcDebug () & FC_DBG_FONTSET) printf ("cache scan dir %s\n", dir); +retry: if (FcStatChecksum (dir, &dir_stat) < 0) goto bail; @@ -285,24 +304,41 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config) if (!dirs) goto bail1; + dirs2 = FcStrSetCreate (); + if (!dirs2) + goto bail2; + /* * Scan the dir */ - if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config)) - goto bail2; + if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config, FcFalse)) + goto bail3; /* * Build the cache object */ cache = FcDirCacheBuild (set, dir, &dir_stat, dirs); if (!cache) - goto bail2; + goto bail3; + if (!FcDirScanOnly (dirs2, dir)) + goto bail3; + fprintf(stderr, "FcDirCacheScan: %s: before: %d, after: %d\n", dir, dirs->num, dirs2->num); + if (dirs2->num != dirs->num) + { + fprintf(stderr, "FcDirCacheScan: directory entries updated: retrying the scan: %s\n", dir); + FcStrSetDestroy (dirs); + FcStrSetDestroy (dirs2); + FcFontSetDestroy (set); + goto retry; + } /* * Write out the cache file, ignoring any troubles */ FcDirCacheWrite (cache, config); + bail3: + FcStrSetDestroy (dirs2); bail2: FcStrSetDestroy (dirs); bail1: @@ -317,33 +353,49 @@ FcDirCacheRescan (const FcChar8 *dir, FcConfig *config) FcCache *cache = FcDirCacheLoad (dir, config, NULL); FcCache *new = NULL; struct stat dir_stat; - FcStrSet *dirs; + FcStrSet *dirs, *dirs2; if (!cache) return NULL; +retry: if (FcStatChecksum (dir, &dir_stat) < 0) goto bail; dirs = FcStrSetCreate (); if (!dirs) goto bail; + dirs2 = FcStrSetCreate (); + if (!dirs2) + goto bail1; /* * Scan the dir */ - if (!FcDirScanConfig (NULL, dirs, NULL, dir, FcTrue, config)) - goto bail1; + if (!FcDirScanConfig (NULL, dirs, NULL, dir, FcTrue, config, FcFalse)) + goto bail2; /* * Rebuild the cache object */ new = FcDirCacheRebuild (cache, &dir_stat, dirs); if (!new) - goto bail1; + goto bail2; FcDirCacheUnload (cache); + + if (!FcDirScanOnly (dirs2, dir)) + goto bail2; + if (dirs2->num != dirs->num) + { + fprintf(stderr, "FcDirCacheRescan: directory entries updated: retrying the scan: %s\n", dir); + FcStrSetDestroy (dirs); + FcStrSetDestroy (dirs2); + goto retry; + } /* * Write out the cache file, ignoring any troubles */ FcDirCacheWrite (new, config); +bail2: + FcStrSetDestroy (dirs2); bail1: FcStrSetDestroy (dirs); bail: diff --git a/src/fcint.h b/src/fcint.h index 3d41b0c..a1b147f 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -849,7 +849,12 @@ FcDirScanConfig (FcFontSet *set, FcBlanks *blanks, const FcChar8 *dir, FcBool force, - FcConfig *config); + FcConfig *config, + FcBool scanOnly); + +FcPrivate FcBool +FcDirScanOnly (FcStrSet *dirs, + const FcChar8 *dir); /* fcfont.c */ FcPrivate int