X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffccache.c;h=c43609ccdd735f734fb2341cfbca813a8549dbbe;hb=238489030a64fa883f8f9fc3d73247b7f7257899;hp=3185059c4f229246d5bb38652606f6417e7205a9;hpb=c9c6875014661d4326100bae0464279d76bd657f;p=fontconfig.git diff --git a/src/fccache.c b/src/fccache.c index 3185059..c43609c 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -47,7 +47,7 @@ struct MD5Context { }; static void MD5Init(struct MD5Context *ctx); -static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len); +static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len); static void MD5Final(unsigned char digest[16], struct MD5Context *ctx); static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]); @@ -67,7 +67,7 @@ FcDirCacheBasename (const FcChar8 * dir, FcChar8 cache_base[CACHEBASE_LEN]) struct MD5Context ctx; MD5Init (&ctx); - MD5Update (&ctx, (unsigned char *)dir, strlen ((char *) dir)); + MD5Update (&ctx, (const unsigned char *)dir, strlen ((const char *) dir)); MD5Final (hash, &ctx); @@ -104,6 +104,7 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config) if (!cache_hashed) break; (void) unlink ((char *) cache_hashed); + FcStrFree (cache_hashed); } FcStrListDone (list); /* return FcFalse if something went wrong */ @@ -135,7 +136,8 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat) */ static FcBool FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, - FcBool (*callback) (int fd, struct stat *stat, void *closure), + FcBool (*callback) (int fd, struct stat *fd_stat, + struct stat *dir_stat, void *closure), void *closure, FcChar8 **cache_file_ret) { int fd = -1; @@ -161,20 +163,16 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, break; fd = FcDirCacheOpenFile (cache_hashed, &file_stat); if (fd >= 0) { - if (dir_stat.st_mtime <= file_stat.st_mtime) + ret = (*callback) (fd, &file_stat, &dir_stat, closure); + close (fd); + if (ret) { - ret = (*callback) (fd, &file_stat, closure); - if (ret) - { - if (cache_file_ret) - *cache_file_ret = cache_hashed; - else - FcStrFree (cache_hashed); - close (fd); - break; - } + if (cache_file_ret) + *cache_file_ret = cache_hashed; + else + FcStrFree (cache_hashed); + break; } - close (fd); } FcStrFree (cache_hashed); } @@ -424,11 +422,28 @@ FcCacheFini (void) assert (fcCacheMaxLevel == 0); } +static FcBool +FcCacheTimeValid (FcCache *cache, struct stat *dir_stat) +{ + struct stat dir_static; + + if (!dir_stat) + { + if (stat ((const char *) FcCacheDir (cache), &dir_static) < 0) + return FcFalse; + dir_stat = &dir_static; + } + if (FcDebug () & FC_DBG_CACHE) + printf ("FcCacheTimeValid dir \"%s\" cache time %d dir time %d\n", + FcCacheDir (cache), cache->mtime, (int) dir_stat->st_mtime); + return cache->mtime == (int) dir_stat->st_mtime; +} + /* * Map a cache file into memory */ static FcCache * -FcDirCacheMapFd (int fd, struct stat *fd_stat) +FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat) { FcCache *cache; FcBool allocated = FcFalse; @@ -439,7 +454,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat) if (cache) return cache; /* - * For small cache files, just read them into memory + * Lage cache files are mmap'ed, smaller cache files are read. This + * balances the system cost of mmap against per-process memory usage. */ if (fd_stat->st_size >= FC_CACHE_MIN_MMAP) { @@ -477,7 +493,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat) if (cache->magic != FC_CACHE_MAGIC_MMAP || cache->version < FC_CACHE_CONTENT_VERSION || cache->size != fd_stat->st_size || - !FcCacheInsert (cache, fd_stat)) + !FcCacheInsert (cache, fd_stat) || + !FcCacheTimeValid (cache, dir_stat)) { if (allocated) free (cache); @@ -515,9 +532,9 @@ FcDirCacheUnload (FcCache *cache) } static FcBool -FcDirCacheMapHelper (int fd, struct stat *fd_stat, void *closure) +FcDirCacheMapHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure) { - FcCache *cache = FcDirCacheMapFd (fd, fd_stat); + FcCache *cache = FcDirCacheMapFd (fd, fd_stat, dir_stat); if (!cache) return FcFalse; @@ -546,7 +563,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) fd = FcDirCacheOpenFile (cache_file, file_stat); if (fd < 0) return NULL; - cache = FcDirCacheMapFd (fd, file_stat); + cache = FcDirCacheMapFd (fd, file_stat, NULL); close (fd); return cache; } @@ -556,7 +573,7 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) * the magic number and the size field */ static FcBool -FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure) +FcDirCacheValidateHelper (int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure) { FcBool ret = FcTrue; FcCache c; @@ -569,6 +586,8 @@ FcDirCacheValidateHelper (int fd, struct stat *fd_stat, void *closure) ret = FcFalse; else if (fd_stat->st_size != c.size) ret = FcFalse; + else if (c.mtime != (int) dir_stat->st_mtime) + ret = FcFalse; return ret; } @@ -596,7 +615,7 @@ FcDirCacheValid (const FcChar8 *dir) * Build a cache structure from the given contents */ FcCache * -FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs) +FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcStrSet *dirs) { FcSerialize *serialize = FcSerializeCreate (); FcCache *cache; @@ -644,6 +663,7 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs) cache->magic = FC_CACHE_MAGIC_ALLOC; cache->version = FC_CACHE_CONTENT_VERSION; cache->size = serialize->size; + cache->mtime = (int) dir_stat->st_mtime; /* * Serialize directory name @@ -707,7 +727,7 @@ FcMakeDirectory (const FcChar8 *dir) parent = FcStrDirname (dir); if (!parent) return FcFalse; - if (access ((char *) parent, W_OK|X_OK) == 0) + if (access ((char *) parent, F_OK) == 0) ret = mkdir ((char *) dir, 0777) == 0; else if (access ((char *) parent, F_OK) == -1) ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0777) == 0); @@ -740,7 +760,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config) if (!list) return FcFalse; while ((test_dir = FcStrListNext (list))) { - if (access ((char *) test_dir, W_OK|X_OK) == 0) + if (access ((char *) test_dir, W_OK) == 0) { cache_dir = test_dir; break; @@ -930,7 +950,7 @@ static void MD5Init(struct MD5Context *ctx) * Update context to reflect the concatenation of another buffer full * of bytes. */ -static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len) +static void MD5Update(struct MD5Context *ctx, const unsigned char *buf, unsigned len) { FcChar32 t;