X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffccache.c;h=c24b06184a120a6571cee4e749473fc81e47fe34;hb=e37d10fa74217a6102003882d49ac323f28db678;hp=e4b04fcae7622c47196710d88160d6269431ca4b;hpb=23816bf9acbd6cc5dd942daaba3cc084ea70d99d;p=fontconfig.git diff --git a/src/fccache.c b/src/fccache.c index e4b04fc..c24b061 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); } @@ -213,6 +211,17 @@ struct _FcCacheSkip { static FcCacheSkip *fcCacheChains[FC_CACHE_MAX_LEVEL]; static int fcCacheMaxLevel; +#if HAVE_RANDOM +# define FcRandom() random() +#else +# if HAVE_LRAND48 +# define FcRandom() lrand48() +# else +# if HAVE_RAND +# define FcRandom() rand() +# endif +# endif +#endif /* * Generate a random level number, distributed * so that each level is 1/4 as likely as the one before @@ -223,7 +232,7 @@ static int random_level (void) { /* tricky bit -- each bit is '1' 75% of the time */ - long int bits = random () | random (); + long int bits = FcRandom () | FcRandom (); int level = 0; while (++level < FC_CACHE_MAX_LEVEL) @@ -275,9 +284,18 @@ FcCacheInsert (FcCache *cache, struct stat *cache_stat) s->cache = cache; s->size = cache->size; s->ref = 1; - s->cache_dev = cache_stat->st_dev; - s->cache_ino = cache_stat->st_ino; - s->cache_mtime = cache_stat->st_mtime; + if (cache_stat) + { + s->cache_dev = cache_stat->st_dev; + s->cache_ino = cache_stat->st_ino; + s->cache_mtime = cache_stat->st_mtime; + } + else + { + s->cache_dev = 0; + s->cache_ino = 0; + s->cache_mtime = 0; + } /* * Insert into all fcCacheChains @@ -404,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; @@ -419,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) { @@ -434,7 +470,8 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat) PAGE_READONLY, 0, 0, NULL); if (hFileMap != NULL) { - cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, size); + cache = MapViewOfFile (hFileMap, FILE_MAP_READ, 0, 0, + fd_stat->st_size); CloseHandle (hFileMap); } } @@ -456,6 +493,7 @@ 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 || + !FcCacheTimeValid (cache, dir_stat) || !FcCacheInsert (cache, fd_stat)) { if (allocated) @@ -494,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; @@ -521,11 +559,14 @@ FcDirCacheLoadFile (const FcChar8 *cache_file, struct stat *file_stat) { int fd; FcCache *cache; + struct stat my_file_stat; + if (!file_stat) + file_stat = &my_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; } @@ -535,7 +576,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; @@ -548,6 +589,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; } @@ -575,7 +618,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; @@ -623,6 +666,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 @@ -658,6 +702,8 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, FcStrSet *dirs) FcSerializeDestroy (serialize); + FcCacheInsert (cache, NULL); + return cache; bail2: @@ -667,6 +713,11 @@ bail1: return NULL; } + +#ifdef _WIN32 +#define mkdir(path,mode) _mkdir(path) +#endif + static FcBool FcMakeDirectory (const FcChar8 *dir) { @@ -679,7 +730,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); @@ -712,7 +763,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; @@ -798,16 +849,17 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config) * Hokey little macro trick to permit the definitions of C functions * with the same name as CPP macros */ -#define args(x...) (x) +#define args1(x) (x) +#define args2(x,y) (x,y) const FcChar8 * -FcCacheDir args(const FcCache *c) +FcCacheDir args1(const FcCache *c) { return FcCacheDir (c); } FcFontSet * -FcCacheCopySet args(const FcCache *c) +FcCacheCopySet args1(const FcCache *c) { FcFontSet *old = FcCacheSet (c); FcFontSet *new = FcFontSetCreate (); @@ -816,28 +868,33 @@ FcCacheCopySet args(const FcCache *c) if (!new) return NULL; for (i = 0; i < old->nfont; i++) - if (!FcFontSetAdd (new, FcFontSetFont (old, i))) + { + FcPattern *font = FcFontSetFont (old, i); + + FcPatternReference (font); + if (!FcFontSetAdd (new, font)) { FcFontSetDestroy (new); return NULL; } + } return new; } const FcChar8 * -FcCacheSubdir args(const FcCache *c, int i) +FcCacheSubdir args2(const FcCache *c, int i) { return FcCacheSubdir (c, i); } int -FcCacheNumSubdir args(const FcCache *c) +FcCacheNumSubdir args1(const FcCache *c) { return c->dirs_count; } int -FcCacheNumFont args(const FcCache *c) +FcCacheNumFont args1(const FcCache *c) { return FcCacheSet(c)->nfont; } @@ -896,7 +953,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;