diff --git a/src/fccache.c b/src/fccache.c index 0976201..4acde22 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -338,7 +338,7 @@ FcDirCacheOpenFile (const FcChar8 *cache_file, struct stat *file_stat) static FcBool FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat, - struct stat *dir_stat, void *closure), + struct stat *dir_stat, struct timeval *cache_mtime, void *closure), void *closure, FcChar8 **cache_file_ret) { int fd = -1; @@ -348,6 +348,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, struct stat file_stat, dir_stat; FcBool ret = FcFalse; const FcChar8 *sysroot = FcConfigGetSysRoot (config); + struct timeval latest_mtime = (struct timeval){ 0 }; if (sysroot) d = FcStrBuildFilename (sysroot, dir, NULL); @@ -383,15 +384,18 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, #endif fd = FcDirCacheOpenFile (cache_hashed, &file_stat); if (fd >= 0) { - ret = (*callback) (config, fd, &file_stat, &dir_stat, closure); + ret = (*callback) (config, fd, &file_stat, &dir_stat, &latest_mtime, closure); close (fd); if (ret) { if (cache_file_ret) + { + if (*cache_file_ret) + FcStrFree (*cache_file_ret); *cache_file_ret = cache_hashed; + } else FcStrFree (cache_hashed); - break; } } #ifndef _WIN32 @@ -414,7 +418,8 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir, } } #endif - FcStrFree (cache_hashed); + else + FcStrFree (cache_hashed); } FcStrListDone (list); @@ -998,12 +1003,31 @@ FcDirCacheUnload (FcCache *cache) } static FcBool -FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure) +FcDirCacheMapHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure) { FcCache *cache = FcDirCacheMapFd (config, fd, fd_stat, dir_stat); + struct timeval cache_mtime; if (!cache) return FcFalse; + cache_mtime.tv_sec = fd_stat->st_mtime; +#ifdef HAVE_STRUCT_STAT_ST_MTIM + cache_mtime.tv_usec = fd_stat->st_mtim.tv_nsec / 1000; +#else + cache_mtime.tv_usec = 0; +#endif + if (timercmp (latest_cache_mtime, &cache_mtime, <)) + { + if (*((FcCache **) closure)) + FcDirCacheUnload (*((FcCache **) closure)); + } + else + { + FcDirCacheUnload (cache); + return FcFalse; + } + latest_cache_mtime->tv_sec = cache_mtime.tv_sec; + latest_cache_mtime->tv_usec = cache_mtime.tv_usec; *((FcCache **) closure) = cache; return FcTrue; } @@ -1093,7 +1117,7 @@ FcDirChecksumNano (struct stat *statb) * the magic number and the size field */ static FcBool -FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, void *closure FC_UNUSED) +FcDirCacheValidateHelper (FcConfig *config, int fd, struct stat *fd_stat, struct stat *dir_stat, struct timeval *latest_cache_mtime, void *closure FC_UNUSED) { FcBool ret = FcTrue; FcCache c; diff --git a/test/run-test.sh b/test/run-test.sh index 4e5968b..8ad09e3 100644 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -340,6 +340,72 @@ fi rm -rf $MyPWD/sysroot +dotest "read newer caches when multiple places are allowed to store" +prep +cp $FONT1 $FONT2 $FONTDIR +if [ -n ${SOURCE_DATE_EPOCH:-} ] && [ ${#SOURCE_DATE_EPOCH} -gt 0 ]; then + touch -m -t "`date -d \"@${SOURCE_DATE_EPOCH}\" +%y%m%d%H%M.%S`" $FONTDIR +fi +MYCACHEBASEDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX` +MYCACHEDIR=$MYCACHEBASEDIR/cache.dir +MYOWNCACHEDIR=$MYCACHEBASEDIR/owncache.dir +MYCONFIG=`mktemp /tmp/fontconfig.XXXXXXXX` + +mkdir -p $MYCACHEDIR +mkdir -p $MYOWNCACHEDIR + +sed "s!@FONTDIR@!$FONTDIR! +s!@REMAPDIR@!! +s!@CACHEDIR@!$MYCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf + +FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE $FONTDIR + +sleep 1 +cat<$MYCONFIG + + + $FONTDIR/4x6.pcf + 8 + + +EOF +sed "s!@FONTDIR@!$FONTDIR! +s!@REMAPDIR@!$MYCONFIG! +s!@CACHEDIR@!$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf + +if [ -n ${SOURCE_DATE_EPOCH:-} ]; then + old_epoch=${SOURCE_DATE_EPOCH} + SOURCE_DATE_EPOCH=`expr $SOURCE_DATE_EPOCH + 1` +fi +FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCCACHE -f $FONTDIR +if [ -n ${SOURCE_DATE_EPOCH:-} ]; then + SOURCE_DATE_EPOCH=${old_epoch} +fi + +sed "s!@FONTDIR@!$FONTDIR! +s!@REMAPDIR@!$MYCONFIG! +s!@CACHEDIR@!$MYCACHEDIR$MYOWNCACHEDIR!" < $TESTDIR/fonts.conf.in > my-fonts.conf + +FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort > my-out +echo "=" >> my-out +FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out +echo "=" >> my-out +FONTCONFIG_FILE=$MyPWD/my-fonts.conf $FCLIST - family pixelsize | sort >> my-out +tr -d '\015' my-out.tmp; mv my-out.tmp my-out +sed -e 's/pixelsize=6/pixelsize=8/g' $BUILDTESTDIR/$EXPECTED > my-out.expected + +if cmp my-out my-out.expected > /dev/null ; then : ; else + echo "*** Test failed: $TEST" + echo "*** output is in 'my-out', expected output in 'my-out.expected'" + echo "Actual Result" + cat my-out + echo "Expected Result" + cat my-out.expected + exit 1 +fi + +rm -rf $MYCACHEBASEDIR $MYCONFIG my-fonts.conf my-out my-out.expected + fi # if [ "x$EXEEXT" = "x" ] rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out