Read latest cache in paths

Right now fontconfig uses a cache found first in a path and
cachedirs are the order of the system-wide path and then the user path.
this is due to avoid writing caches into the user path when running as root.

However, changing caches by certain config only, e.g. using <match target="scan">
may not take effect by this behavior, because it may be stored into the user path.

Thus, needing to find the latest cache out from paths.

Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/182
This commit is contained in:
Akira TAGOH 2019-10-28 17:11:38 +09:00
parent cd51cb241a
commit c9862b6ea7
2 changed files with 96 additions and 6 deletions

View File

@ -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;

View File

@ -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<<EOF>$MYCONFIG
<fontconfig>
<match target="scan">
<test name="file"><string>$FONTDIR/4x6.pcf</string></test>
<edit name="pixelsize"><int>8</int></edit>
</match>
</fontconfig>
EOF
sed "s!@FONTDIR@!$FONTDIR!
s!@REMAPDIR@!<include ignore_missing=\"yes\">$MYCONFIG</include>!
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@!<include ignore_missing=\"yes\">$MYCONFIG</include>!
s!@CACHEDIR@!$MYCACHEDIR</cachedir><cachedir>$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 >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