fontconfig: Branch 'master' - 34 commits

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 .gitlab-ci.yml                   |    7 
 conf.d/05-reset-dirs-sample.conf |    9 +
 conf.d/Makefile.am               |    1 
 configure.ac                     |   33 ----
 doc/fccache.fncs                 |    5 
 doc/fontconfig-user.sgml         |   21 ++
 fc-cache/fc-cache.c              |   12 +
 fonts.dtd                        |   17 ++
 src/Makefile.am                  |    3 
 src/fccache.c                    |  291 +++++++++++++-----------------------
 src/fccfg.c                      |  168 ++++++++++++++++----
 src/fcdir.c                      |    1 
 src/fchash.c                     |   20 --
 src/fcint.h                      |   35 ++++
 src/fcstr.c                      |  166 ++++++++++++++++++++
 src/fcxml.c                      |  313 +++++++++++++++++++++++++--------------
 test/Makefile.am                 |    5 
 test/fonts.conf.in               |    1 
 test/run-test-conf.sh            |   12 +
 test/run-test-map.sh             |  107 +++++++++++++
 test/run-test.sh                 |  198 +++++++++++++++---------
 test/test-bz106632.c             |   24 ++
 test/test-conf.c                 |    1 
 test/test-d1f48f11.c             |    2 
 test/test-hash.c                 |  186 -----------------------
 test/test-issue110.c             |    2 
 26 files changed, 971 insertions(+), 669 deletions(-)

New commits:
commit faa11fb642d046e9aecde6d1385b8e6c14ec6055
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Apr 4 12:14:20 2019 +0000

    Update the test case that is looking for uuid based on host

diff --git a/test/run-test.sh b/test/run-test.sh
index 2d820a8..b55efcb 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -249,6 +249,38 @@ if cmp out1 out2 > /dev/null ; then : ; else
 fi
 rm -rf $TESTTMPDIR out1 out2 bind-fonts.conf
 
+dotest "Fallback to uuid"
+prep
+cp $FONT1 $FONTDIR
+touch -d @`stat -c %Y $FONTDIR` $FONTDIR
+$FCCACHE $FONTDIR
+sleep 1
+_cache=`ls -1 --color=no $CACHEDIR/*cache*`
+_mtime=`stat -c %Y $FONTDIR`
+_uuid=`uuidgen`
+_newcache=`echo $_cache | sed "s/\([0-9a-f]*\)\(\-.*\)/$_uuid\2/"`
+mv $_cache $_newcache
+echo $_uuid > $FONTDIR/.uuid
+touch -d @$_mtime $FONTDIR
+(cd $CACHEDIR; ls -1 --color=no *cache*) > out1
+TESTTMPDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
+mkdir -p $TESTTMPDIR/cache.dir
+sed "s!@FONTDIR@!$TESTTMPDIR/fonts!
+s!@REMAPDIR@!<remap-dir as-path="'"'"$FONTDIR"'"'">$TESTTMPDIR/fonts</remap-dir>!
+s!@CACHEDIR@!$TESTTMPDIR/cache.dir!" < $TESTDIR/fonts.conf.in > bind-fonts.conf
+$BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/fc-match/fc-match$EXEEXT -f ""
+(cd $CACHEDIR; ls -1 --color=no *cache*) > out2
+if cmp out1 out2 > /dev/null ; then : ; else
+    echo "*** Test failed: $TEST"
+    echo "cache was created unexpectedly."
+    echo "Before:"
+    cat out1
+    echo "After:"
+    cat out2
+    exit 1
+fi
+rm -rf $TESTTMPDIR out1 out2 bind-fonts.conf
+
 else
     echo "No bubblewrap installed. skipping..."
 fi # if [ x"$BWRAP" != "x" -a "x$EXEEXT" = "x" ]
@@ -276,30 +308,6 @@ fi
 
 rm -rf $MyPWD/sysroot
 
-dotest "Fallback to uuid"
-prep
-cp $FONT1 $FONTDIR
-touch -d @`stat -c %Y $FONTDIR` $FONTDIR
-$FCCACHE $FONTDIR
-_cache=`ls -1 --color=no $CACHEDIR/*cache*`
-_mtime=`stat -c %Y $FONTDIR`
-_uuid=`uuidgen`
-_newcache=`echo $_cache | sed "s/\([0-9a-f]*\)\(\-.*\)/$_uuid\2/"`
-mv $_cache $_newcache
-echo $_uuid > $FONTDIR/.uuid
-touch -d @$_mtime $FONTDIR
-$FCCACHE $FONTDIR
-_cache2=`ls -1 --color=no $CACHEDIR/*cache*`
-if [ "x$_cache2" != "x$_newcache" ]; then
-  echo "*** Test failed: $TEST"
-  echo "Cache wasn't fallen back."
-  echo "Expected result:"
-  echo $_newcache
-  echo "Actual result:"
-  echo $_cache2
-  exit 1
-fi
-
 fi # if [ "x$EXEEXT" = "x" ]
 
 rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out
commit 76e899700bdc0443807f7e0170d3c1aa6da1b84b
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Apr 4 11:57:13 2019 +0000

    No need to remap for uuid based

diff --git a/src/fccache.c b/src/fccache.c
index c954cc4..47f7876 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -150,7 +150,7 @@ static const char bin2hex[] = { '0', '1', '2', '3',
 static FcChar8 *
 FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
 {
-    FcChar8		*new_dir = NULL;
+    FcChar8		*mapped_dir = NULL;
     unsigned char 	hash[16];
     FcChar8		*hex_hash, *key = NULL;
     int			cnt;
@@ -158,11 +158,17 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
     const FcChar8	*salt, *orig_dir = NULL;
 
     salt = FcConfigMapSalt (config, dir);
-    new_dir = FcConfigMapFontPath(config, dir);
-    if (new_dir)
+    /* Obtain a path where "dir" is mapped to.
+     * In case:
+     * <remap-dir as-path="/usr/share/fonts">/run/host/fonts</remap-dir>
+     *
+     * FcConfigMapFontPath (config, "/run/host/fonts") will returns "/usr/share/fonts".
+     */
+    mapped_dir = FcConfigMapFontPath(config, dir);
+    if (mapped_dir)
     {
 	orig_dir = dir;
-	dir = new_dir;
+	dir = mapped_dir;
     }
     if (salt)
     {
@@ -196,11 +202,11 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
     strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
     if (FcDebug() & FC_DBG_CACHE)
     {
-	printf ("cache: %s (dir: %s%s%s%s%s%s)\n", cache_base, orig_dir ? orig_dir : dir, new_dir ? " (mapped to " : "", new_dir ? (char *)new_dir : "", new_dir ? ")" : "", salt ? ", salt: " : "", salt ? (char *)salt : "");
+	printf ("cache: %s (dir: %s%s%s%s%s%s)\n", cache_base, orig_dir ? orig_dir : dir, mapped_dir ? " (mapped to " : "", mapped_dir ? (char *)mapped_dir : "", mapped_dir ? ")" : "", salt ? ", salt: " : "", salt ? (char *)salt : "");
     }
 
-    if (new_dir)
-	FcStrFree(new_dir);
+    if (mapped_dir)
+	FcStrFree(mapped_dir);
 
     return cache_base;
 }
@@ -209,19 +215,13 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
 static FcChar8 *
 FcDirCacheBasenameUUID (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
 {
-    FcChar8 *new_dir = NULL;
     FcChar8 *target, *fuuid;
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
-    const FcChar8 *salt, *orig_dir = NULL;
     int fd;
 
-    salt = FcConfigMapSalt (config, dir);
-    new_dir = FcConfigMapFontPath (config, dir);
-    if (new_dir)
-    {
-	orig_dir = dir;
-	dir = new_dir;
-    }
+    /* We don't need to apply remapping here. because .uuid was created at that very directory
+     * to determine the cache name no matter where it was mapped to.
+     */
     cache_base[0] = 0;
     if (sysroot)
 	target = FcStrBuildFilename (sysroot, dir, NULL);
@@ -244,12 +244,10 @@ FcDirCacheBasenameUUID (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base
 	strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
 	if (FcDebug () & FC_DBG_CACHE)
 	{
-	    printf ("cache fallbacks to: %s (dir: %s%s%s%s%s)\n", cache_base, orig_dir ? orig_dir : dir, new_dir ? " (mapped to " : "", new_dir ? (char *)new_dir : "", new_dir ? ")" : "", salt ? ", salt was ignored" : "");
+	    printf ("cache fallbacks to: %s (dir: %s)\n", cache_base, dir);
 	}
     }
 bail:
-    if (new_dir)
-	FcStrFree (new_dir);
     FcStrFree (fuuid);
     FcStrFree (target);
 
commit 7f61838435ed3e3f8c19c593e9e646d221128df8
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Apr 4 10:59:47 2019 +0000

    Fallback uuid-based name to read a cache if no MD5-based cache available

diff --git a/src/fccache.c b/src/fccache.c
index 8581ae6..c954cc4 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -196,7 +196,7 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
     strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
     if (FcDebug() & FC_DBG_CACHE)
     {
-	printf ("cache: %s (dir: %s%s%s%s, salt: %s)\n", cache_base, orig_dir ? orig_dir : dir, new_dir ? " (mapped to " : "", new_dir ? (char *)new_dir : "", new_dir ? ")" : "", salt);
+	printf ("cache: %s (dir: %s%s%s%s%s%s)\n", cache_base, orig_dir ? orig_dir : dir, new_dir ? " (mapped to " : "", new_dir ? (char *)new_dir : "", new_dir ? ")" : "", salt ? ", salt: " : "", salt ? (char *)salt : "");
     }
 
     if (new_dir)
@@ -205,16 +205,74 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
     return cache_base;
 }
 
+#ifndef _WIN32
+static FcChar8 *
+FcDirCacheBasenameUUID (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
+{
+    FcChar8 *new_dir = NULL;
+    FcChar8 *target, *fuuid;
+    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
+    const FcChar8 *salt, *orig_dir = NULL;
+    int fd;
+
+    salt = FcConfigMapSalt (config, dir);
+    new_dir = FcConfigMapFontPath (config, dir);
+    if (new_dir)
+    {
+	orig_dir = dir;
+	dir = new_dir;
+    }
+    cache_base[0] = 0;
+    if (sysroot)
+	target = FcStrBuildFilename (sysroot, dir, NULL);
+    else
+	target = FcStrdup (dir);
+    fuuid = FcStrBuildFilename (target, ".uuid", NULL);
+    if ((fd = FcOpen ((char *) fuuid, O_RDONLY)) != -1)
+    {
+	char suuid[37];
+	ssize_t len;
+
+	memset (suuid, 0, sizeof (suuid));
+	len = read (fd, suuid, 36);
+	suuid[36] = 0;
+	close (fd);
+	if (len < 0)
+	    goto bail;
+	cache_base[0] = '/';
+	strcpy ((char *)&cache_base[1], suuid);
+	strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
+	if (FcDebug () & FC_DBG_CACHE)
+	{
+	    printf ("cache fallbacks to: %s (dir: %s%s%s%s%s)\n", cache_base, orig_dir ? orig_dir : dir, new_dir ? " (mapped to " : "", new_dir ? (char *)new_dir : "", new_dir ? ")" : "", salt ? ", salt was ignored" : "");
+	}
+    }
+bail:
+    if (new_dir)
+	FcStrFree (new_dir);
+    FcStrFree (fuuid);
+    FcStrFree (target);
+
+    return cache_base;
+}
+#endif
+
 FcBool
 FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
 {
     FcChar8	*cache_hashed = NULL;
     FcChar8	cache_base[CACHEBASE_LEN];
+#ifndef _WIN32
+    FcChar8     uuid_cache_base[CACHEBASE_LEN];
+#endif
     FcStrList	*list;
     FcChar8	*cache_dir;
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
 
     FcDirCacheBasenameMD5 (config, dir, cache_base);
+#ifndef _WIN32
+    FcDirCacheBasenameUUID (config, dir, uuid_cache_base);
+#endif
 
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
@@ -229,10 +287,23 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
         if (!cache_hashed)
 	    break;
 	(void) unlink ((char *) cache_hashed);
-	FcDirCacheDeleteUUID (dir, config);
 	FcStrFree (cache_hashed);
+#ifndef _WIN32
+	if (uuid_cache_base[0] != 0)
+	{
+	    if (sysroot)
+		cache_hashed = FcStrBuildFilename (sysroot, cache_dir, uuid_cache_base, NULL);
+	    else
+		cache_hashed = FcStrBuildFilename (cache_dir, uuid_cache_base, NULL);
+	    if (!cache_hashed)
+		break;
+	    (void) unlink ((char *) cache_hashed);
+	    FcStrFree (cache_hashed);
+	}
+#endif
     }
     FcStrListDone (list);
+    FcDirCacheDeleteUUID (dir, config);
     /* return FcFalse if something went wrong */
     if (cache_dir)
 	return FcFalse;
@@ -300,7 +371,11 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
     while ((cache_dir = FcStrListNext (list)))
     {
         FcChar8	*cache_hashed;
+#ifndef _WIN32
+	FcBool retried = FcFalse;
 
+    retry:
+#endif
 	if (sysroot)
 	    cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL);
 	else
@@ -320,6 +395,18 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
 		break;
 	    }
 	}
+#ifndef _WIN32
+	else if (!retried)
+	{
+	    retried = FcTrue;
+	    FcDirCacheBasenameUUID (config, dir, cache_base);
+	    if (cache_base[0] != 0)
+	    {
+		FcStrFree (cache_hashed);
+		goto retry;
+	    }
+	}
+#endif
     	FcStrFree (cache_hashed);
     }
     FcStrListDone (list);
diff --git a/test/run-test.sh b/test/run-test.sh
index 69a12f6..2d820a8 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -236,7 +236,6 @@ mkdir -p $TESTTMPDIR/cache.dir
 sed "s!@FONTDIR@!$TESTTMPDIR/fonts!
 s!@REMAPDIR@!<remap-dir as-path="'"'"$FONTDIR"'"'">$TESTTMPDIR/fonts</remap-dir>!
 s!@CACHEDIR@!$TESTTMPDIR/cache.dir!" < $TESTDIR/fonts.conf.in > bind-fonts.conf
-cat bind-fonts.conf
 $BWRAP --bind / / --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/fc-cache/fc-cache$EXEEXT $TESTTMPDIR/fonts
 (cd $TESTTMPDIR/cache.dir; ls -1 --color=no *cache*) > out2
 if cmp out1 out2 > /dev/null ; then : ; else
@@ -277,6 +276,30 @@ fi
 
 rm -rf $MyPWD/sysroot
 
+dotest "Fallback to uuid"
+prep
+cp $FONT1 $FONTDIR
+touch -d @`stat -c %Y $FONTDIR` $FONTDIR
+$FCCACHE $FONTDIR
+_cache=`ls -1 --color=no $CACHEDIR/*cache*`
+_mtime=`stat -c %Y $FONTDIR`
+_uuid=`uuidgen`
+_newcache=`echo $_cache | sed "s/\([0-9a-f]*\)\(\-.*\)/$_uuid\2/"`
+mv $_cache $_newcache
+echo $_uuid > $FONTDIR/.uuid
+touch -d @$_mtime $FONTDIR
+$FCCACHE $FONTDIR
+_cache2=`ls -1 --color=no $CACHEDIR/*cache*`
+if [ "x$_cache2" != "x$_newcache" ]; then
+  echo "*** Test failed: $TEST"
+  echo "Cache wasn't fallen back."
+  echo "Expected result:"
+  echo $_newcache
+  echo "Actual result:"
+  echo $_cache2
+  exit 1
 fi
 
+fi # if [ "x$EXEEXT" = "x" ]
+
 rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out
commit 13d2a47d79a4ec4d3bc48aeb89dd9c899468152e
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Apr 4 06:47:34 2019 +0000

    Fix unexpected cache name by double-slash in path

diff --git a/src/fccfg.c b/src/fccfg.c
index f2289f1..e81eeba 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -612,7 +612,7 @@ FcConfigMapFontPath(FcConfig		*config,
 {
     FcStrList	*list;
     FcChar8	*dir;
-    const FcChar8 *map;
+    const FcChar8 *map, *rpath;
     FcChar8     *retval;
 
     list = FcConfigGetFontDirs(config);
@@ -627,15 +627,17 @@ FcConfigMapFontPath(FcConfig		*config,
     map = FcStrTripleSecond(dir);
     if (!map)
 	return 0;
-    retval = FcStrBuildFilename(map, path + strlen((char *) dir), NULL);
+    rpath = path + strlen ((char *) dir);
+    while (*rpath == '/')
+	rpath++;
+    retval = FcStrBuildFilename(map, rpath, NULL);
     if (retval)
     {
 	size_t len = strlen ((const char *) retval);
-	if (retval[len-1] == '/')
-	{
-	    /* trim the last slash */
-	    retval[len-1] = 0;
-	}
+	while (len > 0 && retval[len-1] == '/')
+	    len--;
+	/* trim the last slash */
+	retval[len] = 0;
     }
     return retval;
 }
diff --git a/test/run-test.sh b/test/run-test.sh
index aeb5ecd..69a12f6 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -156,6 +156,10 @@ ls -l $CACHEDIR > out2
 if cmp out1 out2 > /dev/null ; then : ; else
   echo "*** Test failed: $TEST"
   echo "cache was created/updated."
+  echo "Before:"
+  cat out1
+  echo "After:"
+  cat out2
   exit 1
 fi
 if [ x`cat xxx` != "x$TESTTMPDIR/fonts/4x6.pcf" ]; then
@@ -220,7 +224,35 @@ if cmp flist1 flist2 > /dev/null ; then
 fi
 rm -rf $TESTTMPDIR $TESTTMP2DIR out1 out2 xxx flist1 flist2 stat1 stat2 bind-fonts.conf
 
+dotest "Check consistency of MD5 in cache name"
+prep
+mkdir -p $FONTDIR/sub
+cp $FONT1 $FONTDIR/sub
+$FCCACHE $FONTDIR
+sleep 1
+(cd $CACHEDIR; ls -1 --color=no *cache*) > out1
+TESTTMPDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
+mkdir -p $TESTTMPDIR/cache.dir
+sed "s!@FONTDIR@!$TESTTMPDIR/fonts!
+s!@REMAPDIR@!<remap-dir as-path="'"'"$FONTDIR"'"'">$TESTTMPDIR/fonts</remap-dir>!
+s!@CACHEDIR@!$TESTTMPDIR/cache.dir!" < $TESTDIR/fonts.conf.in > bind-fonts.conf
+cat bind-fonts.conf
+$BWRAP --bind / / --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/fc-cache/fc-cache$EXEEXT $TESTTMPDIR/fonts
+(cd $TESTTMPDIR/cache.dir; ls -1 --color=no *cache*) > out2
+if cmp out1 out2 > /dev/null ; then : ; else
+    echo "*** Test failed: $TEST"
+    echo "cache was created unexpectedly."
+    echo "Before:"
+    cat out1
+    echo "After:"
+    cat out2
+    exit 1
 fi
+rm -rf $TESTTMPDIR out1 out2 bind-fonts.conf
+
+else
+    echo "No bubblewrap installed. skipping..."
+fi # if [ x"$BWRAP" != "x" -a "x$EXEEXT" = "x" ]
 
 if [ "x$EXEEXT" = "x" ]; then
 dotest "sysroot option"
commit faec0b51db6ef935929a95b289524abac062be8c
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Apr 4 05:04:17 2019 +0000

    Don't show salt in debugging message if salt is null

diff --git a/src/fccfg.c b/src/fccfg.c
index 9b12744..f2289f1 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -556,11 +556,11 @@ FcConfigAddFontDir (FcConfig	    *config,
     {
 	if (m)
 	{
-	    printf ("%s -> %s (salt: %s)\n", d, m, salt);
+	    printf ("%s -> %s%s%s%s\n", d, m, salt ? " (salt: " : "", salt ? (const char *)salt : "", salt ? ")" : "");
 	}
 	else if (salt)
 	{
-	    printf ("%s (salt: %s)\n", d, salt);
+	    printf ("%s%s%s%s\n", d, salt ? " (salt: " : "", salt ? (const char *)salt : "", salt ? ")" : "");
 	}
     }
     return FcStrSetAddFilenamePairWithSalt (config->fontDirs, d, m, salt);
commit 91114d18c3435e4bffe1812eb03ffe5efa8543d7
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Wed Apr 3 04:48:42 2019 +0000

    Allow overriding salt with new one coming later

diff --git a/src/fcint.h b/src/fcint.h
index 7fad78f..9e1da1e 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -1250,6 +1250,9 @@ FcPrivate void
 FcStrSetSort (FcStrSet * set);
 
 FcPrivate FcBool
+FcStrSetMemberAB (FcStrSet *set, const FcChar8 *a, FcChar8 *b, FcChar8 **ret);
+
+FcPrivate FcBool
 FcStrSetAddTriple (FcStrSet *set, const FcChar8 *a, const FcChar8 *b, const FcChar8 *c);
 
 FcPrivate const FcChar8 *
diff --git a/src/fcstr.c b/src/fcstr.c
index 2d3c510..cdebe98 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -1233,6 +1233,58 @@ FcStrSetMember (FcStrSet *set, const FcChar8 *s)
     return FcFalse;
 }
 
+static int
+fc_strcmp_r (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 **ret)
+{
+    FcChar8 c1, c2;
+
+    if (s1 == s2)
+    {
+	if (ret)
+	    *ret = NULL;
+	return 0;
+    }
+    for (;;)
+    {
+	if (s1)
+	    c1 = *s1++;
+	else
+	    c1 = 0;
+	if (s2)
+	    c2 = *s2++;
+	else
+	    c2 = 0;
+	if (!c1 || c1 != c2)
+	    break;
+    }
+    if (ret)
+	*ret = s1;
+    return (int) c1  - (int) c2;
+}
+
+FcBool
+FcStrSetMemberAB (FcStrSet *set, const FcChar8 *a, FcChar8 *b, FcChar8 **ret)
+{
+    int i;
+    const FcChar8 *s = NULL;
+
+    for (i = 0; i < set->num; i++)
+    {
+	if (!fc_strcmp_r (set->strs[i], a, &s) && s)
+	{
+	    if (!fc_strcmp_r (s, b, NULL))
+	    {
+		if (ret)
+		    *ret = set->strs[i];
+		return FcTrue;
+	    }
+	}
+    }
+    if (ret)
+	*ret = NULL;
+    return FcFalse;
+}
+
 FcBool
 FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
 {
@@ -1313,6 +1365,7 @@ FcStrSetAddFilenamePairWithSalt (FcStrSet *set, const FcChar8 *a, const FcChar8
 {
     FcChar8 *new_a = NULL;
     FcChar8 *new_b = NULL;
+    FcChar8 *rs = NULL;
     FcBool  ret;
 
     if (a)
@@ -1331,6 +1384,11 @@ FcStrSetAddFilenamePairWithSalt (FcStrSet *set, const FcChar8 *a, const FcChar8
 	    return FcFalse;
 	}
     }
+    /* Override maps with new one if exists */
+    if (FcStrSetMemberAB (set, new_a, new_b, &rs))
+    {
+	FcStrSetDel (set, rs);
+    }
     ret = FcStrSetAddTriple (set, new_a, new_b, salt);
     if (new_a)
 	FcStrFree (new_a);
commit 791762d8b7108f692b8643a208825f5ba3aa7a72
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Apr 2 11:03:16 2019 +0000

    fc-cache: Show font directories to generate cache with -v

diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index e0816c9..1866bd7 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -404,6 +404,17 @@ main (int argc, char **argv)
 	return 1;
     }
 
+    if (verbose)
+    {
+	const FcChar8 *dir;
+
+	printf ("Font directories:\n");
+	while ((dir = FcStrListNext (list)))
+	{
+	    printf ("\t%s\n", dir);
+	}
+	FcStrListFirst(list);
+    }
     changed = 0;
     ret = scanDirs (list, config, force, really_force, verbose, error_on_no_fonts, &changed);
     FcStrListDone (list);
commit d1acc73f23205e63be791c9f21eba917d292c541
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Apr 2 10:25:46 2019 +0000

    Oops, Terminate string

diff --git a/src/fccache.c b/src/fccache.c
index 8124e05..8581ae6 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -172,6 +172,7 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
 	key = (FcChar8 *) malloc (dl + sl + 1);
 	memcpy (key, dir, dl);
 	memcpy (key + dl, salt, sl + 1);
+	key[dl + sl] = 0;
 	if (!orig_dir)
 		orig_dir = dir;
 	dir = key;
commit fc9f706ecb71b2625487138e6f7424d8c2cee761
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Apr 2 10:00:17 2019 +0000

    Add some debugging output

diff --git a/src/fccache.c b/src/fccache.c
index 7c3edc5..8124e05 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -150,17 +150,20 @@ static const char bin2hex[] = { '0', '1', '2', '3',
 static FcChar8 *
 FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
 {
-    FcChar8		*new_dir;
+    FcChar8		*new_dir = NULL;
     unsigned char 	hash[16];
     FcChar8		*hex_hash, *key = NULL;
     int			cnt;
     struct MD5Context 	ctx;
-    const FcChar8	*salt;
+    const FcChar8	*salt, *orig_dir = NULL;
 
     salt = FcConfigMapSalt (config, dir);
     new_dir = FcConfigMapFontPath(config, dir);
     if (new_dir)
+    {
+	orig_dir = dir;
 	dir = new_dir;
+    }
     if (salt)
     {
 	size_t dl = strlen ((const char *) dir);
@@ -169,6 +172,8 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
 	key = (FcChar8 *) malloc (dl + sl + 1);
 	memcpy (key, dir, dl);
 	memcpy (key + dl, salt, sl + 1);
+	if (!orig_dir)
+		orig_dir = dir;
 	dir = key;
     }
     MD5Init (&ctx);
@@ -176,8 +181,6 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
 
     MD5Final (hash, &ctx);
 
-    if (new_dir)
-	FcStrFree(new_dir);
     if (key)
 	FcStrFree (key);
 
@@ -190,6 +193,13 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
     }
     hex_hash[2*cnt] = 0;
     strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
+    if (FcDebug() & FC_DBG_CACHE)
+    {
+	printf ("cache: %s (dir: %s%s%s%s, salt: %s)\n", cache_base, orig_dir ? orig_dir : dir, new_dir ? " (mapped to " : "", new_dir ? (char *)new_dir : "", new_dir ? ")" : "", salt);
+    }
+
+    if (new_dir)
+	FcStrFree(new_dir);
 
     return cache_base;
 }
diff --git a/src/fccfg.c b/src/fccfg.c
index 9f42058..9b12744 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -552,12 +552,27 @@ FcConfigAddFontDir (FcConfig	    *config,
 		    const FcChar8   *m,
 		    const FcChar8   *salt)
 {
+    if (FcDebug() & FC_DBG_CACHE)
+    {
+	if (m)
+	{
+	    printf ("%s -> %s (salt: %s)\n", d, m, salt);
+	}
+	else if (salt)
+	{
+	    printf ("%s (salt: %s)\n", d, salt);
+	}
+    }
     return FcStrSetAddFilenamePairWithSalt (config->fontDirs, d, m, salt);
 }
 
 FcBool
 FcConfigResetFontDirs (FcConfig *config)
 {
+    if (FcDebug() & FC_DBG_CACHE)
+    {
+	printf ("Reset font directories!\n");
+    }
     return FcStrSetDeleteAll (config->fontDirs);
 }
 
commit cb1df8cb28d6ae34726cf7c3fd0142847431c7bb
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Apr 2 09:37:49 2019 +0000

    Don't warn if path can't be converted with prefix

diff --git a/src/fcxml.c b/src/fcxml.c
index 54a26da..d154a54 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -2076,6 +2076,11 @@ FcParseRemapDir (FcConfigParse *parse)
 	FcConfigMessage (parse, FcSevereError, "out of memory");
 	return;
     }
+    if (data[0] == 0)
+    {
+	FcConfigMessage (parse, FcSevereWarning, "empty font directory name for remap ignored");
+	return;
+    }
     path = FcConfigGetAttribute (parse, "as-path");
     if (!path)
     {
@@ -2086,7 +2091,9 @@ FcParseRemapDir (FcConfigParse *parse)
     salt = FcConfigGetAttribute (parse, "salt");
     prefix = _get_real_path_from_prefix (parse, data, attr);
     if (!prefix || prefix[0] == 0)
-	FcConfigMessage (parse, FcSevereWarning, "empty font directory name for remap ignored");
+    {
+	/* nop */
+    }
     else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
     {
 	if (!FcConfigAddFontDir (parse->config, prefix, path, salt))
@@ -2257,11 +2264,18 @@ FcParseDir (FcConfigParse *parse)
 	FcConfigMessage (parse, FcSevereError, "out of memory");
 	return;
     }
+    if (data[0] == 0)
+    {
+	FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
+	return;
+    }
     attr = FcConfigGetAttribute (parse, "prefix");
     salt = FcConfigGetAttribute (parse, "salt");
     prefix = _get_real_path_from_prefix (parse, data, attr);
     if (!prefix || prefix[0] == 0)
-	FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
+    {
+	/* nop */
+    }
     else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
     {
 	if (!FcConfigAddFontDir (parse->config, prefix, NULL, salt))
commit 34791c32f19a3abc6a3dd2000d28202b80a882f9
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Mar 26 05:07:34 2019 +0000

    Don't share fonts and cache dir for testing
    
    There seems a race condition on CI. so create an unique directory to avoid colision.

diff --git a/test/run-test.sh b/test/run-test.sh
index 2bda9c2..aeb5ecd 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -28,8 +28,9 @@ esac
 TESTDIR=${srcdir-"$MyPWD"}
 BUILDTESTDIR=${builddir-"$MyPWD"}
 
-FONTDIR="$MyPWD"/fonts
-CACHEDIR="$MyPWD"/cache.dir
+BASEDIR=`mktemp -d --tmpdir fontconfig.XXXXXXXX`
+FONTDIR="$BASEDIR"/fonts
+CACHEDIR="$BASEDIR"/cache.dir
 EXPECTED=${EXPECTED-"out.expected"}
 LOG_COMPILER=${LOG_COMPILER-"$TESTDIR/wrapper-script.sh"}
 
@@ -226,6 +227,7 @@ dotest "sysroot option"
 prep
 mkdir -p $MyPWD/sysroot/$FONTDIR
 mkdir -p $MyPWD/sysroot/$CACHEDIR
+mkdir -p $MyPWD/sysroot/$MyPWD
 cp $FONT1 $MyPWD/sysroot/$FONTDIR
 cp $MyPWD/fonts.conf $MyPWD/sysroot/$MyPWD/fonts.conf
 $FCCACHE -y $MyPWD/sysroot
@@ -245,4 +247,4 @@ rm -rf $MyPWD/sysroot
 
 fi
 
-rm -rf $FONTDIR $CACHEFILE $CACHEDIR $FONTCONFIG_FILE out
+rm -rf $FONTDIR $CACHEFILE $CACHEDIR $BASEDIR $FONTCONFIG_FILE out
commit 0950f248e031865e0abe8dad4c974ea426e159b2
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Mar 25 20:00:15 2019 +0900

    Add more data to artifacts for debugging purpose

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cbb624a..a82cec4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -31,9 +31,11 @@ shared-build:
       - build-*/fontconfig*/_build/sub/*.log
       - build-*/fontconfig*/_build/sub/test/*.log
       - build-*/fontconfig*/_build/sub/test/*.trs
+      - build-*/fontconfig*/_build/sub/test/out*
       - build-*/*.log
       - build-*/test/*.log
       - build-*/test/*.trs
+      - build-*/test/out*
       - prefix-*
 static-build:
   stage: build
@@ -54,6 +56,7 @@ static-build:
       - build-*/*.log
       - build-*/test/*.log
       - build-*/test/*.trs
+      - build-*/test/out*
 mingw-build:
   stage: build
   script:
@@ -74,4 +77,4 @@ mingw-build:
       - build-*/*.log
       - build-*/test/*.log
       - build-*/test/*.trs
-
+      - build-*/test/out*
commit ad3f335ccfeceb8595ae9e30bde901a732b9dd51
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Mar 25 10:58:15 2019 +0000

    Fix make check fail on MinGW again

diff --git a/src/fcxml.c b/src/fcxml.c
index 0ca283e..54a26da 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -1287,7 +1287,7 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
 {
 #ifdef _WIN32
     const FcChar8 *data;
-    FcChar8 buffer[1000];
+    FcChar8 buffer[1000] = { 0 };
 #endif
     FcChar8 *parent = NULL, *retval = NULL;
 
@@ -1321,7 +1321,6 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
 	if (!FcStrIsAbsoluteFilename (path) && path[0] != '~')
 	    FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous path in <%s> element. please add prefix=\"cwd\" if current behavior is desired.", FcElementReverseMap (parse->pstack->element));
     }
-#endif
     if (parent)
     {
 	retval = FcStrBuildFilename (parent, path, NULL);
@@ -1330,7 +1329,7 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
     {
 	retval = FcStrdup (path);
     }
-#ifdef _WIN32
+#else
     if (strcmp ((const char *) path, "CUSTOMFONTDIR") == 0)
     {
 	FcChar8 *p;
@@ -1377,12 +1376,23 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
 	    strcat ((char *) data, "\\");
 	strcat ((char *) data, "fonts");
     }
-    else if (!prefix)
+    else
     {
-	if (!FcStrIsAbsoluteFilename (path) && path[0] != '~')
-	    FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous path in <%s> element. please add prefix=\"cwd\" if current behavior is desired.", FcElementReverseMap (parse->pstack->element));
+	data = path;
+	if (!prefix)
+	{
+	    if (!FcStrIsAbsoluteFilename (path) && path[0] != '~')
+		FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous path in <%s> element. please add prefix=\"cwd\" if current behavior is desired.", FcElementReverseMap (parse->pstack->element));
+	}
+	if (parent)
+	{
+	    retval = FcStrBuildFilename (parent, data, NULL);
+	}
+	else
+	{
+	    retval = FcStrdup (data);
+	}
     }
-    retval = FcStrdup (data);
 #endif
 
     return retval;
commit 8e2c85fe81020b3703e37a127ccc85625350a12d
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Mar 25 17:39:16 2019 +0900

    Use alternative function for realpath on Win32

diff --git a/src/fccfg.c b/src/fccfg.c
index db93118..9f42058 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -87,7 +87,16 @@ FcConfigRealPath(const FcChar8 *path)
     if (!path)
 	return NULL;
 
+#ifndef _WIN32
     resolved_ret = realpath((const char *) path, resolved_name);
+#else
+    if (GetFullPathNameA ((LPCSTR) path, PATH_MAX, resolved_name, NULL) == 0)
+    {
+        fprintf (stderr, "Fontconfig warning: GetFullPathNameA failed.\n");
+        return NULL;
+    }
+    resolved_ret = resolved_name;
+#endif
     if (resolved_ret)
 	path = (FcChar8 *) resolved_ret;
     return FcStrCopyFilename(path);
commit b1bcc0cbb258d3b697147c80c410e8df6843f376
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Mar 25 16:17:33 2019 +0900

    Fix build issues on MinGW

diff --git a/src/fcxml.c b/src/fcxml.c
index 88804d7..0ca283e 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -1338,7 +1338,7 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
 	if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
 	{
 	    FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
-	    goto bail;
+	    return NULL;
 	}
 	/*
 	 * Must use the multi-byte aware function to search
@@ -1357,7 +1357,7 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
 	if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
 	{
 	    FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
-	    goto bail;
+	    return NULL;
 	}
 	p = _mbsrchr (data, '\\');
 	if (p) *p = '\0';
@@ -1371,7 +1371,7 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
 	if (rc == 0 || rc > sizeof (buffer) - 20)
 	{
 	    FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed");
-	    goto bail;
+	    return NULL;
 	}
 	if (data [strlen ((const char *) data) - 1] != '\\')
 	    strcat ((char *) data, "\\");
commit 9177cf2c3814f1f23fe207d4be3876111d272d60
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Mar 25 15:52:02 2019 +0900

    Add back if !OS_WIN32 line

diff --git a/test/Makefile.am b/test/Makefile.am
index ff693e4..fc47a50 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -76,6 +76,7 @@ endif
 check_PROGRAMS += test-bz106618
 test_bz106618_LDADD = $(top_builddir)/src/libfontconfig.la
 
+if !OS_WIN32
 check_PROGRAMS += test-bz106632
 test_bz106632_CFLAGS =					\
 	-I$(top_builddir)				\
commit a39f30738d6688888a6e19d08ddaaf8928d563e1
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Fri Feb 1 06:41:51 2019 +0000

    trivial testcase update

diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh
index f9e0abd..437bafa 100644
--- a/test/run-test-conf.sh
+++ b/test/run-test-conf.sh
@@ -33,5 +33,11 @@ BUILDTESTDIR=${builddir-"$MyPWD"}
 
 RUNNER=../test/test-conf$EXEEXT
 
-$RUNNER $TESTDIR/../conf.d/60-generic.conf $TESTDIR/test-60-generic.json
-$RUNNER $TESTDIR/../conf.d/90-synthetic.conf $TESTDIR/test-90-synthetic.json
+for i in \
+	60-generic.conf \
+	90-synthetic.conf \
+    ; do
+    test_json=$(echo test-$i|sed s'/\.conf/.json/')
+    echo $RUNNER $TESTDIR/../conf.d/$i $TESTDIR/$test_json
+    $RUNNER $TESTDIR/../conf.d/$i $TESTDIR/$test_json
+done
commit 4ff52ffb52dc9eb9b12aee21c4b897206c28d457
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Fri Feb 1 06:41:38 2019 +0000

    Update doc for salt

diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml
index f30b4f0..cfe173f 100644
--- a/doc/fontconfig-user.sgml
+++ b/doc/fontconfig-user.sgml
@@ -310,9 +310,13 @@ following structure:
 This is the top level element for a font configuration and can contain
 <literal>&lt;dir&gt;</literal>, <literal>&lt;cachedir&gt;</literal>, <literal>&lt;include&gt;</literal>, <literal>&lt;match&gt;</literal> and <literal>&lt;alias&gt;</literal> elements in any order.
   </para></refsect2>
-  <refsect2><title><literal>&lt;dir prefix="default"&gt;</literal></title><para>
+  <refsect2><title><literal>&lt;dir prefix="default" salt=""&gt;</literal></title><para>
 This element contains a directory name which will be scanned for font files
-to include in the set of available fonts. If 'prefix' is set to "default" or "cwd", the current working directory will be added as the path prefix prior to the value. If 'prefix' is set to "xdg", the value in the XDG_DATA_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. If 'prefix' is set to "relative", the path of current file will be added prior to the value.
+to include in the set of available fonts.
+  </para><para>
+If 'prefix' is set to "default" or "cwd", the current working directory will be added as the path prefix prior to the value. If 'prefix' is set to "xdg", the value in the XDG_DATA_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. If 'prefix' is set to "relative", the path of current file will be added prior to the value.
+  </para><para>
+'salt' property affects to determine cache filename. this is useful for example when having different fonts sets on same path at container and share fonts from host on different font path.
   </para></refsect2>
   <refsect2><title><literal>&lt;cachedir prefix="default"&gt;</literal></title><para>
 This element contains a directory name that is supposed to be stored or read
@@ -352,12 +356,14 @@ Unicode characters which is supposed to be blank in an <literal>&lt;int&gt;</lit
 Characters outside of this set which are drawn as blank will be elided from
 the set of characters supported by the font.
   </para></refsect2>
-  <refsect2><title><literal>&lt;remap-dir prefix="default" as-path=""&lt;</literal></title><para>
+  <refsect2><title><literal>&lt;remap-dir prefix="default" as-path="" salt=""&lt;</literal></title><para>
 This element contains a directory name where will be mapped
 as the path 'as-path' in cached information.
 This is useful if the directory name is an alias
 (via a bind mount or symlink) to another directory in the system for
 which cached font information is likely to exist.
+  </para><para>
+'salt' property affects to determine cache filename as same as <literal>&lt;dir&gt;</literal> element.
   </para></refsect2>
   <refsect2><title><literal>&lt;reset-dirs /&gt;</literal></title><para>
 This element removes all of fonts directories where added by <literal>&lt;dir&gt;</literal> elements.
commit 2e8ce63514b06590d36d9bf5c332ff83fb72791a
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Jan 31 10:17:47 2019 +0000

    Add salt attribute to dir and remap-dir elements
    
    'salt' attribute affects a cache filename to generate different name from directory name.
    This is useful when sharing caches with host on sandbox and/or give a filename differently:
    
        <dir salt="randomdata">/usr/share/fonts</dir>
        <remap-dir as-path="/usr/share/fonts" salt="salt for /usr/share/fonts on host">/run/host/fonts</remap-dir>
    
    Applications can read caches as-is for fonts on /run/host/fonts where is mounted from host.
    and write a cache for their own fonts on /usr/share/fonts with different name.

diff --git a/src/fccache.c b/src/fccache.c
index bec017e..7c3edc5 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -152,14 +152,25 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
 {
     FcChar8		*new_dir;
     unsigned char 	hash[16];
-    FcChar8		*hex_hash;
+    FcChar8		*hex_hash, *key = NULL;
     int			cnt;
     struct MD5Context 	ctx;
+    const FcChar8	*salt;
 
+    salt = FcConfigMapSalt (config, dir);
     new_dir = FcConfigMapFontPath(config, dir);
     if (new_dir)
 	dir = new_dir;
+    if (salt)
+    {
+	size_t dl = strlen ((const char *) dir);
+	size_t sl = strlen ((const char *) salt);
 
+	key = (FcChar8 *) malloc (dl + sl + 1);
+	memcpy (key, dir, dl);
+	memcpy (key + dl, salt, sl + 1);
+	dir = key;
+    }
     MD5Init (&ctx);
     MD5Update (&ctx, (const unsigned char *)dir, strlen ((const char *) dir));
 
@@ -167,6 +178,8 @@ FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[
 
     if (new_dir)
 	FcStrFree(new_dir);
+    if (key)
+	FcStrFree (key);
 
     cache_base[0] = '/';
     hex_hash = cache_base + 1;
diff --git a/src/fccfg.c b/src/fccfg.c
index 422608c..db93118 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -540,9 +540,10 @@ FcConfigGetConfigDirs (FcConfig   *config)
 FcBool
 FcConfigAddFontDir (FcConfig	    *config,
 		    const FcChar8   *d,
-		    const FcChar8   *m)
+		    const FcChar8   *m,
+		    const FcChar8   *salt)
 {
-    return FcStrSetAddFilenamePair (config->fontDirs, d, m);
+    return FcStrSetAddFilenamePairWithSalt (config->fontDirs, d, m, salt);
 }
 
 FcBool
@@ -587,7 +588,7 @@ FcConfigMapFontPath(FcConfig		*config,
 {
     FcStrList	*list;
     FcChar8	*dir;
-    FcChar8	*map;
+    const FcChar8 *map;
     FcChar8     *retval;
 
     list = FcConfigGetFontDirs(config);
@@ -599,7 +600,7 @@ FcConfigMapFontPath(FcConfig		*config,
     FcStrListDone(list);
     if (!dir)
 	return 0;
-    map = FcStrPairSecond(dir);
+    map = FcStrTripleSecond(dir);
     if (!map)
 	return 0;
     retval = FcStrBuildFilename(map, path + strlen((char *) dir), NULL);
@@ -615,6 +616,26 @@ FcConfigMapFontPath(FcConfig		*config,
     return retval;
 }
 
+const FcChar8 *
+FcConfigMapSalt (FcConfig      *config,
+		 const FcChar8 *path)
+{
+    FcStrList *list;
+    FcChar8 *dir;
+
+    list = FcConfigGetFontDirs (config);
+    if (!list)
+	return NULL;
+    while ((dir = FcStrListNext (list)))
+	if (FcConfigPathStartsWith (path, dir))
+	    break;
+    FcStrListDone (list);
+    if (!dir)
+	return NULL;
+
+    return FcStrTripleThird (dir);
+}
+
 FcBool
 FcConfigAddCacheDir (FcConfig	    *config,
 		     const FcChar8  *d)
diff --git a/src/fcint.h b/src/fcint.h
index 5cfdcc3..7fad78f 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -660,7 +660,8 @@ FcConfigAddConfigDir (FcConfig	    *config,
 FcPrivate FcBool
 FcConfigAddFontDir (FcConfig	    *config,
 		    const FcChar8   *d,
-		    const FcChar8   *m);
+		    const FcChar8   *m,
+		    const FcChar8   *salt);
 
 FcPrivate FcBool
 FcConfigResetFontDirs (FcConfig *config);
@@ -669,6 +670,10 @@ FcPrivate FcChar8 *
 FcConfigMapFontPath(FcConfig		*config,
 		    const FcChar8	*path);
 
+FcPrivate const FcChar8 *
+FcConfigMapSalt (FcConfig      *config,
+		 const FcChar8 *path);
+
 FcPrivate FcBool
 FcConfigAddCacheDir (FcConfig	    *config,
 		     const FcChar8  *d);
@@ -1245,13 +1250,16 @@ FcPrivate void
 FcStrSetSort (FcStrSet * set);
 
 FcPrivate FcBool
-FcStrSetAddPair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b);
+FcStrSetAddTriple (FcStrSet *set, const FcChar8 *a, const FcChar8 *b, const FcChar8 *c);
 
-FcPrivate FcChar8 *
-FcStrPairSecond (FcChar8 *s);
+FcPrivate const FcChar8 *
+FcStrTripleSecond (FcChar8 *s);
+
+FcPrivate const FcChar8 *
+FcStrTripleThird (FcChar8 *str);
 
 FcPrivate FcBool
-FcStrSetAddFilenamePair (FcStrSet *strs, const FcChar8 *d, const FcChar8 *m);
+FcStrSetAddFilenamePairWithSalt (FcStrSet *strs, const FcChar8 *d, const FcChar8 *m, const FcChar8 *salt);
 
 FcPrivate FcBool
 FcStrSetDeleteAll (FcStrSet *set);
diff --git a/src/fcstr.c b/src/fcstr.c
index 53cd1f7..2d3c510 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -37,11 +37,12 @@ FcStrCopy (const FcChar8 *s)
 }
 
 static FcChar8 *
-FcStrMakePair (const FcChar8 *s1, const FcChar8 *s2)
+FcStrMakeTriple (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *s3)
 {
     int	    s1l = s1 ? strlen ((char *) s1) : 0;
     int	    s2l = s2 ? strlen ((char *) s2) : 0;
-    int	    l = s1l + 1 + s2l + 1;
+    int     s3l = s3 ? strlen ((char *) s3) : 0;
+    int	    l = s1l + 1 + s2l + 1 + s3l + 1;
     FcChar8 *s = malloc (l);
 
     if (!s)
@@ -54,6 +55,10 @@ FcStrMakePair (const FcChar8 *s1, const FcChar8 *s2)
 	memcpy (s + s1l + 1, s2, s2l + 1);
     else
 	s[s1l + 1] = '\0';
+    if (s3)
+	memcpy (s + s1l + 1 + s2l + 1, s3, s3l + 1);
+    else
+	s[s1l + 1 + s2l + 1] = '\0';
     return s;
 }
 
@@ -1255,9 +1260,9 @@ FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
 }
 
 FcBool
-FcStrSetAddPair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b)
+FcStrSetAddTriple (FcStrSet *set, const FcChar8 *a, const FcChar8 *b, const FcChar8 *c)
 {
-    FcChar8 *new = FcStrMakePair (a, b);
+    FcChar8 *new = FcStrMakeTriple (a, b, c);
     if (!new)
 	return FcFalse;
     if (!_FcStrSetAppend (set, new))
@@ -1268,8 +1273,8 @@ FcStrSetAddPair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b)
     return FcTrue;
 }
 
-FcChar8 *
-FcStrPairSecond (FcChar8 *str)
+const FcChar8 *
+FcStrTripleSecond (FcChar8 *str)
 {
     FcChar8 *second = str + strlen((char *) str) + 1;
 
@@ -1278,6 +1283,17 @@ FcStrPairSecond (FcChar8 *str)
     return second;
 }
 
+const FcChar8 *
+FcStrTripleThird (FcChar8 *str)
+{
+    FcChar8 *second = str + strlen ((char *) str) + 1;
+    FcChar8 *third = second + strlen ((char *) second) + 1;
+
+    if (*third == '\0')
+	return 0;
+    return third;
+}
+
 FcBool
 FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
 {
@@ -1293,7 +1309,7 @@ FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
 }
 
 FcBool
-FcStrSetAddFilenamePair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b)
+FcStrSetAddFilenamePairWithSalt (FcStrSet *set, const FcChar8 *a, const FcChar8 *b, const FcChar8 *salt)
 {
     FcChar8 *new_a = NULL;
     FcChar8 *new_b = NULL;
@@ -1315,7 +1331,7 @@ FcStrSetAddFilenamePair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b)
 	    return FcFalse;
 	}
     }
-    ret = FcStrSetAddPair (set, new_a, new_b);
+    ret = FcStrSetAddTriple (set, new_a, new_b, salt);
     if (new_a)
 	FcStrFree (new_a);
     if (new_b)
diff --git a/src/fcxml.c b/src/fcxml.c
index 955a2b0..88804d7 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -2057,7 +2057,7 @@ FcParseDescription (FcConfigParse *parse)
 static void
 FcParseRemapDir (FcConfigParse *parse)
 {
-    const FcChar8 *path, *attr, *data;
+    const FcChar8 *path, *attr, *data, *salt;
     FcChar8 *prefix = NULL;
 
     data = FcStrBufDoneStatic (&parse->pstack->str);
@@ -2073,12 +2073,13 @@ FcParseRemapDir (FcConfigParse *parse)
 	return;
     }
     attr = FcConfigGetAttribute (parse, "prefix");
+    salt = FcConfigGetAttribute (parse, "salt");
     prefix = _get_real_path_from_prefix (parse, data, attr);
     if (!prefix || prefix[0] == 0)
 	FcConfigMessage (parse, FcSevereWarning, "empty font directory name for remap ignored");
     else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
     {
-	if (!FcConfigAddFontDir (parse->config, prefix, path))
+	if (!FcConfigAddFontDir (parse->config, prefix, path, salt))
 	    FcConfigMessage (parse, FcSevereError, "out of memory; cannot create remap data for %s as %s", prefix, path);
     }
     FcStrBufDestroy (&parse->pstack->str);
@@ -2237,7 +2238,7 @@ FcParseUnary (FcConfigParse *parse, FcOp op)
 static void
 FcParseDir (FcConfigParse *parse)
 {
-    const FcChar8 *attr, *data;
+    const FcChar8 *attr, *data, *salt;
     FcChar8 *prefix = NULL;
 
     data = FcStrBufDoneStatic (&parse->pstack->str);
@@ -2247,12 +2248,13 @@ FcParseDir (FcConfigParse *parse)
 	return;
     }
     attr = FcConfigGetAttribute (parse, "prefix");
+    salt = FcConfigGetAttribute (parse, "salt");
     prefix = _get_real_path_from_prefix (parse, data, attr);
     if (!prefix || prefix[0] == 0)
 	FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
     else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
     {
-	if (!FcConfigAddFontDir (parse->config, prefix, NULL))
+	if (!FcConfigAddFontDir (parse->config, prefix, NULL, salt))
 	    FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", prefix);
     }
     FcStrBufDestroy (&parse->pstack->str);
diff --git a/test/run-test.sh b/test/run-test.sh
index 0183eaf..2bda9c2 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -172,6 +172,53 @@ if cmp flist1 flist2 > /dev/null ; then : ; else
   exit 1
 fi
 rm -rf $TESTTMPDIR out1 out2 xxx flist1 flist2 bind-fonts.conf
+
+dotest "Different directory content between host and sandbox"
+prep
+cp $FONT1 $FONTDIR
+$FCCACHE $FONTDIR
+sleep 1
+ls -1 --color=no $CACHEDIR/*cache*> out1
+stat -c '%n %s %y %z' `cat out1` > stat1
+TESTTMPDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
+TESTTMP2DIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
+cp $FONT2 $TESTTMP2DIR
+sed "s!@FONTDIR@!$TESTTMPDIR/fonts</dir><dir salt="'"'"salt-to-make-different"'"'">$FONTDIR!
+s!@REMAPDIR@!<remap-dir as-path="'"'"$FONTDIR"'"'">$TESTTMPDIR/fonts</remap-dir>!
+s!@CACHEDIR@!$TESTTMPDIR/cache.dir!" < $TESTDIR/fonts.conf.in > bind-fonts.conf
+$BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind $TESTTMP2DIR $FONTDIR --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/fc-match/fc-match$EXEEXT -f "%{file}\n" ":foundry=Misc" > xxx
+$BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind $TESTTMP2DIR $FONTDIR --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/test/test-bz106618$EXEEXT | sort > flist1
+$BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind $TESTTMP2DIR $FONTDIR --bind .. $TESTTMPDIR/build --dev-bind /dev /dev find $TESTTMPDIR/fonts/ -type f -name '*.pcf' | sort > flist2
+ls -1 --color=no $CACHEDIR/*cache* > out2
+stat -c '%n %s %y %z' `cat out1` > stat2
+if cmp stat1 stat2 > /dev/null ; then : ; else
+  echo "*** Test failed: $TEST"
+  echo "cache was created/updated."
+  cat stat1 stat2
+  exit 1
+fi
+if grep -v -- "`cat out1`" out2 > /dev/null ; then : ; else
+  echo "*** Test failed: $TEST"
+  echo "cache wasn't created for dir inside sandbox."
+  cat out1 out2
+  exit 1
+fi
+if [ x`cat xxx` != "x$TESTTMPDIR/fonts/4x6.pcf" ]; then
+  echo "*** Test failed: $TEST"
+  echo "file property doesn't point to the new place: $TESTTMPDIR/fonts/4x6.pcf"
+  exit 1
+fi
+if cmp flist1 flist2 > /dev/null ; then
+  echo "*** Test failed: $TEST"
+  echo "Missing fonts should be available on sandbox"
+  echo "Expected result:"
+  cat flist2
+  echo "Actual result:"
+  cat flist1
+  exit 1
+fi
+rm -rf $TESTTMPDIR $TESTTMP2DIR out1 out2 xxx flist1 flist2 stat1 stat2 bind-fonts.conf
+
 fi
 
 if [ "x$EXEEXT" = "x" ]; then
commit def1d00036a4e828382027292a167203c6c7a0b4
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Jan 31 07:52:09 2019 +0000

    Add reset-dirs element
    
    This element removes all of fonts directories where added by
    dir elements. it is useful to override fonts dirs from system
    to their own dirs only.

diff --git a/conf.d/05-reset-dirs-sample.conf b/conf.d/05-reset-dirs-sample.conf
new file mode 100644
index 0000000..80bb6fb
--- /dev/null
+++ b/conf.d/05-reset-dirs-sample.conf
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <description>Re-define fonts dirs sample</description>
+
+  <reset-dirs />
+  <dir prefix="xdg">fonts</dir>
+
+</fontconfig>
diff --git a/conf.d/Makefile.am b/conf.d/Makefile.am
index ff03fb2..d0f3f26 100644
--- a/conf.d/Makefile.am
+++ b/conf.d/Makefile.am
@@ -52,6 +52,7 @@ config_DATA = $(DOC_FILES)
 
 templatedir = $(TEMPLATEDIR)
 template_DATA =				\
+	05-reset-dirs-sample.conf	\
 	10-autohint.conf		\
 	10-hinting-full.conf		\
 	10-hinting-medium.conf		\
diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml
index f083394..f30b4f0 100644
--- a/doc/fontconfig-user.sgml
+++ b/doc/fontconfig-user.sgml
@@ -359,6 +359,10 @@ This is useful if the directory name is an alias
 (via a bind mount or symlink) to another directory in the system for
 which cached font information is likely to exist.
   </para></refsect2>
+  <refsect2><title><literal>&lt;reset-dirs /&gt;</literal></title><para>
+This element removes all of fonts directories where added by <literal>&lt;dir&gt;</literal> elements.
+This is useful to override fonts directories from system to own fonts directories only.
+  </para></refsect2>
   <refsect2><title><literal>&lt;rescan&gt;</literal></title><para>
 The <literal>&lt;rescan&gt;</literal> element holds an <literal>&lt;int&gt;</literal> element which indicates the default
 interval between automatic checks for font configuration changes.
diff --git a/fonts.dtd b/fonts.dtd
index d0e1700..f8c9f2c 100644
--- a/fonts.dtd
+++ b/fonts.dtd
@@ -8,6 +8,7 @@
 		      include |
 		      match |
 		      remap-dir |
+		      reset-dirs |
 		      selectfont)* >
 
 <!-- 
@@ -121,6 +122,11 @@
 	  xml:space (default|preserve)          "preserve">
 
 <!--
+    Reset the list of fonts directories
+-->
+<!ELEMENT reset-dirs >
+
+<!--
     Periodically rescan the font configuration and
     directories to synch internal state with filesystem
  -->
diff --git a/src/fccfg.c b/src/fccfg.c
index b2e2ce1..422608c 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -545,6 +545,12 @@ FcConfigAddFontDir (FcConfig	    *config,
     return FcStrSetAddFilenamePair (config->fontDirs, d, m);
 }
 
+FcBool
+FcConfigResetFontDirs (FcConfig *config)
+{
+    return FcStrSetDeleteAll (config->fontDirs);
+}
+
 FcStrList *
 FcConfigGetFontDirs (FcConfig	*config)
 {
diff --git a/src/fcint.h b/src/fcint.h
index 593b100..5cfdcc3 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -662,6 +662,9 @@ FcConfigAddFontDir (FcConfig	    *config,
 		    const FcChar8   *d,
 		    const FcChar8   *m);
 
+FcPrivate FcBool
+FcConfigResetFontDirs (FcConfig *config);
+
 FcPrivate FcChar8 *
 FcConfigMapFontPath(FcConfig		*config,
 		    const FcChar8	*path);
@@ -1250,6 +1253,9 @@ FcStrPairSecond (FcChar8 *s);
 FcPrivate FcBool
 FcStrSetAddFilenamePair (FcStrSet *strs, const FcChar8 *d, const FcChar8 *m);
 
+FcPrivate FcBool
+FcStrSetDeleteAll (FcStrSet *set);
+
 FcPrivate void
 FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size);
 
diff --git a/src/fcstr.c b/src/fcstr.c
index 4e0a2b6..53cd1f7 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -1388,6 +1388,22 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s)
     return FcFalse;
 }
 
+FcBool
+FcStrSetDeleteAll (FcStrSet *set)
+{
+    int i;
+
+    if (FcRefIsConst (&set->ref))
+	return FcFalse;
+
+    for (i = set->num; i > 0; i--)
+    {
+	FcStrFree (set->strs[i - 1]);
+	set->num--;
+    }
+    return FcTrue;
+}
+
 /* TODO Make public */
 static FcStrSet *
 FcStrSetReference (FcStrSet *set)
diff --git a/src/fcxml.c b/src/fcxml.c
index 856400f..955a2b0 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -359,6 +359,7 @@ typedef enum _FcElement {
     FcElementAlias,
     FcElementDescription,
     FcElementRemapDir,
+    FcElementResetDirs,
 	
     FcElementRescan,
 
@@ -423,6 +424,7 @@ static const struct {
     { "alias",		FcElementAlias },
     { "description",	FcElementDescription },
     { "remap-dir",	FcElementRemapDir },
+    { "reset-dirs",	FcElementResetDirs },
 
     { "rescan",		FcElementRescan },
 
@@ -2085,6 +2087,16 @@ FcParseRemapDir (FcConfigParse *parse)
 	FcStrFree (prefix);
 }
 
+static void
+FcParseResetDirs (FcConfigParse *parse)
+{
+    if (!parse->scanOnly)
+    {
+	if (!FcConfigResetFontDirs (parse->config))
+	    FcConfigMessage (parse, FcSevereError, "Unable to reset fonts dirs");
+    }
+}
+
 static FcExpr *
 FcPopExpr (FcConfigParse *parse)
 {
@@ -3065,6 +3077,9 @@ FcEndElement(void *userData, const XML_Char *name FC_UNUSED)
     case FcElementRemapDir:
 	FcParseRemapDir (parse);
 	break;
+    case FcElementResetDirs:
+	FcParseResetDirs (parse);
+	break;
 
     case FcElementRescan:
 	FcParseRescan (parse);
commit 5e46f1545100f12ee1daaa41bccc6c3914bd2d83
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Thu Jan 31 07:10:41 2019 +0000

    Fix a typo

diff --git a/fonts.dtd b/fonts.dtd
index 2323c46..d0e1700 100644
--- a/fonts.dtd
+++ b/fonts.dtd
@@ -114,7 +114,8 @@
 <!--
     Map a font path as the path "as-path"
 -->
-<!ELEMENT remap-dir
+<!ELEMENT remap-dir (#PCDATA)>
+<!ATTLIST remap-dir
           as-path   CDATA                       #REQUIRED
           prefix    (default|xdg|relative|cwd)  "default"
 	  xml:space (default|preserve)          "preserve">
commit acc017e67210ee6d8fed7ffd41a1f55fe04d056b
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Jan 29 07:55:22 2019 +0000

    Drop unnecessary line to include uuid.h

diff --git a/src/fchash.c b/src/fchash.c
index 481bf21..e91c72f 100644
--- a/src/fchash.c
+++ b/src/fchash.c
@@ -20,9 +20,6 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 #include "fcint.h"
-#ifndef _WIN32
-#include <uuid/uuid.h>
-#endif
 
 #define FC_HASH_SIZE 227
 
commit 635921e64d074ce5c7b8ca4a6f535241a2b8c75f
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Jan 29 07:49:22 2019 +0000

    Update deps to run CI

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0780b2b..cbb624a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@ stages:
 before_script:
   - dnf -y upgrade --disablerepo=rawhide-modular --nogpgcheck fedora-repos fedora-repos-rawhide
   - dnf -y upgrade --disablerepo=rawhide-modular
-  - dnf -y install --disablerepo=rawhide-modular --allowerasing --skip-broken @buildsys-build autoconf automake libtool gettext gettext-devel gperf expat-devel freetype-devel libuuid-devel json-c-devel git docbook-utils docbook-utils-pdf bubblewrap
+  - dnf -y install --disablerepo=rawhide-modular --allowerasing --skip-broken @buildsys-build autoconf automake libtool gettext gettext-devel gperf expat-devel freetype-devel json-c-devel git docbook-utils docbook-utils-pdf bubblewrap
   - dnf -y install --disablerepo=rawhide-modular --allowerasing --skip-broken mingw64-gettext mingw64-freetype mingw64-expat wine
 
 shared-build:
commit 916cf6caa3d754f4d267eb1fc3cede9c86aa4e15
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Jan 29 07:03:58 2019 +0000

    Update testcase

diff --git a/test/Makefile.am b/test/Makefile.am
index 81aace0..ff693e4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,4 @@
-check_SCRIPTS=run-test.sh run-test-map.sh
+check_SCRIPTS=run-test.sh
 TEST_EXTENSIONS = \
 	.sh \
 	$(NULL)
diff --git a/test/fonts.conf.in b/test/fonts.conf.in
index 24bd58b..12a0b76 100644
--- a/test/fonts.conf.in
+++ b/test/fonts.conf.in
@@ -1,4 +1,5 @@
 <fontconfig>
-<dir @MAP@>@FONTDIR@</dir>
+@REMAPDIR@
+<dir>@FONTDIR@</dir>
 <cachedir>@CACHEDIR@</cachedir>
 </fontconfig>
diff --git a/test/run-test.sh b/test/run-test.sh
index b9a07b8..0183eaf 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -73,7 +73,7 @@ dotest () {
 }
 
 sed "s!@FONTDIR@!$FONTDIR!
-s!@MAP@!!
+s!@REMAPDIR@!!
 s!@CACHEDIR@!$CACHEDIR!" < $TESTDIR/fonts.conf.in > fonts.conf
 
 FONTCONFIG_FILE="$MyPWD"/fonts.conf
@@ -146,11 +146,17 @@ sleep 1
 ls -l $CACHEDIR > out1
 TESTTMPDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
 sed "s!@FONTDIR@!$TESTTMPDIR/fonts!
-s!@MAP@!map="'"'"$FONTDIR"'"'"!
+s!@REMAPDIR@!<remap-dir as-path="'"'"$FONTDIR"'"'">$TESTTMPDIR/fonts</remap-dir>!
 s!@CACHEDIR@!$TESTTMPDIR/cache.dir!" < $TESTDIR/fonts.conf.in > bind-fonts.conf
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/fc-match/fc-match$EXEEXT -f "%{file}\n" ":foundry=Misc" > xxx
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/test/test-bz106618$EXEEXT | sort > flist1
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev find $TESTTMPDIR/fonts/ -type f -name '*.pcf' | sort > flist2
+ls -l $CACHEDIR > out2
+if cmp out1 out2 > /dev/null ; then : ; else
+  echo "*** Test failed: $TEST"
+  echo "cache was created/updated."
+  exit 1
+fi
 if [ x`cat xxx` != "x$TESTTMPDIR/fonts/4x6.pcf" ]; then
   echo "*** Test failed: $TEST"
   echo "file property doesn't point to the new place: $TESTTMPDIR/fonts/4x6.pcf"
diff --git a/test/test-d1f48f11.c b/test/test-d1f48f11.c
index a5ecac9..929afd9 100644
--- a/test/test-d1f48f11.c
+++ b/test/test-d1f48f11.c
@@ -268,7 +268,9 @@ main (void)
     }
 
     free (d);
+    FcConfigDestroy (cfg);
     setenv ("FONTCONFIG_SYSROOT", sysroot, 1);
+    cfg = FcConfigCreate ();
     dsa = FcStrBuildFilename (sysroot, da, NULL);
     dsac = FcStrCanonFilename (dsa);
     d = FcConfigRealFilename (cfg, dc);
diff --git a/test/test-issue110.c b/test/test-issue110.c
index 0ab40e3..3794b08 100644
--- a/test/test-issue110.c
+++ b/test/test-issue110.c
@@ -224,7 +224,9 @@ main(void)
 	goto bail;
     free (ret);
     free (s);
+    FcConfigDestroy (cfg);
     setenv ("FONTCONFIG_SYSROOT", sysroot, 1);
+    cfg = FcConfigCreate ();
     fprintf (stderr, "D: Creating %s\n", sysroot);
     mkdir_p (sysroot);
     retval++;
commit 2e09c62ba1ff3477b4c64d4721337b62024832c8
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Tue Jan 29 07:02:37 2019 +0000

    Trim the last slash
    
    This fixes MD5 wrongly generated.

diff --git a/src/fccfg.c b/src/fccfg.c
index fee2053..b2e2ce1 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -582,6 +582,7 @@ FcConfigMapFontPath(FcConfig		*config,
     FcStrList	*list;
     FcChar8	*dir;
     FcChar8	*map;
+    FcChar8     *retval;
 
     list = FcConfigGetFontDirs(config);
     if (!list)
@@ -595,7 +596,17 @@ FcConfigMapFontPath(FcConfig		*config,
     map = FcStrPairSecond(dir);
     if (!map)
 	return 0;
-    return FcStrBuildFilename(map, path + strlen((char *) dir), NULL);
+    retval = FcStrBuildFilename(map, path + strlen((char *) dir), NULL);
+    if (retval)
+    {
+	size_t len = strlen ((const char *) retval);
+	if (retval[len-1] == '/')
+	{
+	    /* trim the last slash */
+	    retval[len-1] = 0;
+	}
+    }
+    return retval;
 }
 
 FcBool
commit a563a1802ef930374f88e6c7198e1b5ffe7582dd
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Jan 28 09:59:29 2019 +0000

    Add new element remap-dir instead of extending dir element

diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml
index 92e3e5a..f083394 100644
--- a/doc/fontconfig-user.sgml
+++ b/doc/fontconfig-user.sgml
@@ -310,15 +310,9 @@ following structure:
 This is the top level element for a font configuration and can contain
 <literal>&lt;dir&gt;</literal>, <literal>&lt;cachedir&gt;</literal>, <literal>&lt;include&gt;</literal>, <literal>&lt;match&gt;</literal> and <literal>&lt;alias&gt;</literal> elements in any order.
   </para></refsect2>
-  <refsect2><title><literal>&lt;dir prefix="default" map=""&gt;</literal></title><para>
+  <refsect2><title><literal>&lt;dir prefix="default"&gt;</literal></title><para>
 This element contains a directory name which will be scanned for font files
 to include in the set of available fonts. If 'prefix' is set to "default" or "cwd", the current working directory will be added as the path prefix prior to the value. If 'prefix' is set to "xdg", the value in the XDG_DATA_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. If 'prefix' is set to "relative", the path of current file will be added prior to the value.
-</para><para>
-If a 'map' attribute is specified, its value will replace the
-directory path when matching cached information for fonts contained in
-this directory. This is useful if the directory name is an alias
-(via a bind mount or symlink) to another directory in the system for
-which cached font information is likely to exist.
   </para></refsect2>
   <refsect2><title><literal>&lt;cachedir prefix="default"&gt;</literal></title><para>
 This element contains a directory name that is supposed to be stored or read
@@ -358,6 +352,13 @@ Unicode characters which is supposed to be blank in an <literal>&lt;int&gt;</lit
 Characters outside of this set which are drawn as blank will be elided from
 the set of characters supported by the font.
   </para></refsect2>
+  <refsect2><title><literal>&lt;remap-dir prefix="default" as-path=""&lt;</literal></title><para>
+This element contains a directory name where will be mapped
+as the path 'as-path' in cached information.
+This is useful if the directory name is an alias
+(via a bind mount or symlink) to another directory in the system for
+which cached font information is likely to exist.
+  </para></refsect2>
   <refsect2><title><literal>&lt;rescan&gt;</literal></title><para>
 The <literal>&lt;rescan&gt;</literal> element holds an <literal>&lt;int&gt;</literal> element which indicates the default
 interval between automatic checks for font configuration changes.
diff --git a/fonts.dtd b/fonts.dtd
index 8a95fa5..2323c46 100644
--- a/fonts.dtd
+++ b/fonts.dtd
@@ -7,6 +7,7 @@
 		      dir |
 		      include |
 		      match |
+		      remap-dir |
 		      selectfont)* >
 
 <!-- 
@@ -14,7 +15,6 @@
 -->
 <!ELEMENT dir (#PCDATA)>
 <!ATTLIST dir
-	  map       CDATA                         #IMPLIED
 	  prefix    (default|xdg|relative|cwd)    "default"
 	  xml:space (default|preserve)            'preserve'>
 
@@ -110,6 +110,15 @@
 	</edit>
     </match>
 -->
+
+<!--
+    Map a font path as the path "as-path"
+-->
+<!ELEMENT remap-dir
+          as-path   CDATA                       #REQUIRED
+          prefix    (default|xdg|relative|cwd)  "default"
+	  xml:space (default|preserve)          "preserve">
+
 <!--
     Periodically rescan the font configuration and
     directories to synch internal state with filesystem
diff --git a/src/fcxml.c b/src/fcxml.c
index c2ad723..856400f 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -358,6 +358,7 @@ typedef enum _FcElement {
     FcElementMatch,
     FcElementAlias,
     FcElementDescription,
+    FcElementRemapDir,
 	
     FcElementRescan,
 
@@ -421,6 +422,7 @@ static const struct {
     { "match",		FcElementMatch },
     { "alias",		FcElementAlias },
     { "description",	FcElementDescription },
+    { "remap-dir",	FcElementRemapDir },
 
     { "rescan",		FcElementRescan },
 
@@ -490,6 +492,19 @@ FcElementMap (const XML_Char *name)
     return FcElementUnknown;
 }
 
+static const char *
+FcElementReverseMap (FcElement e)
+{
+    int i;
+
+    for (i = 0; i < NUM_ELEMENT_MAPS; i++)
+	if (fcElementMap[i].element == e)
+	    return fcElementMap[i].name;
+
+    return NULL;
+}
+
+
 typedef struct _FcPStack {
     struct _FcPStack   *prev;
     FcElement		element;
@@ -1265,6 +1280,112 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
     return 0;
 }
 
+static FcChar8 *
+_get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcChar8 *prefix)
+{
+#ifdef _WIN32
+    const FcChar8 *data;
+    FcChar8 buffer[1000];
+#endif
+    FcChar8 *parent = NULL, *retval = NULL;
+
+    if (prefix)
+    {
+	if (FcStrCmp (prefix, (const FcChar8 *) "xdg") == 0)
+	{
+	    parent = FcConfigXdgDataHome ();
+	    if (!parent)
+	    {
+		/* Home directory might be disabled */
+		return NULL;
+	    }
+	}
+	else if (FcStrCmp (prefix, (const FcChar8 *) "default") == 0 ||
+		 FcStrCmp (prefix, (const FcChar8 *) "cwd") == 0)
+	{
+	    /* Nothing to do */
+	}
+	else if (FcStrCmp (prefix, (const FcChar8 *) "relative") == 0)
+	{
+	    parent = FcStrDirname (parse->name);
+	    if (!parent)
+		return NULL;
+	}
+    }
+#ifndef _WIN32
+    /* For Win32, check this later for dealing with special cases */
+    else
+    {
+	if (!FcStrIsAbsoluteFilename (path) && path[0] != '~')
+	    FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous path in <%s> element. please add prefix=\"cwd\" if current behavior is desired.", FcElementReverseMap (parse->pstack->element));
+    }
+#endif
+    if (parent)
+    {
+	retval = FcStrBuildFilename (parent, path, NULL);
+    }
+    else
+    {
+	retval = FcStrdup (path);
+    }
+#ifdef _WIN32
+    if (strcmp ((const char *) path, "CUSTOMFONTDIR") == 0)
+    {
+	FcChar8 *p;
+	data = buffer;
+	if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
+	{
+	    FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+	    goto bail;
+	}
+	/*
+	 * Must use the multi-byte aware function to search
+	 * for backslash because East Asian double-byte code
+	 * pages have characters with backslash as the second
+	 * byte.
+	 */
+	p = _mbsrchr (data, '\\');
+	if (p) *p = '\0';
+	strcat ((char *) data, "\\fonts");
+    }
+    else if (strcmp ((const char *) path, "APPSHAREFONTDIR") == 0)
+    {
+	FcChar8 *p;
+	data = buffer;
+	if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
+	{
+	    FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+	    goto bail;
+	}
+	p = _mbsrchr (data, '\\');
+	if (p) *p = '\0';
+	strcat ((char *) data, "\\..\\share\\fonts");
+    }
+    else if (strcmp ((const char *) path, "WINDOWSFONTDIR") == 0)
+    {
+	int rc;
+	data = buffer;
+	rc = pGetSystemWindowsDirectory ((LPSTR) buffer, sizeof (buffer) - 20);
+	if (rc == 0 || rc > sizeof (buffer) - 20)
+	{
+	    FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed");
+	    goto bail;
+	}
+	if (data [strlen ((const char *) data) - 1] != '\\')
+	    strcat ((char *) data, "\\");
+	strcat ((char *) data, "fonts");
+    }
+    else if (!prefix)
+    {
+	if (!FcStrIsAbsoluteFilename (path) && path[0] != '~')
+	    FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous path in <%s> element. please add prefix=\"cwd\" if current behavior is desired.", FcElementReverseMap (parse->pstack->element));
+    }
+    retval = FcStrdup (data);
+#endif
+
+    return retval;
+}
+
 static void
 FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
 {
@@ -1931,6 +2052,39 @@ FcParseDescription (FcConfigParse *parse)
     FcStrFree (desc);
 }
 
+static void
+FcParseRemapDir (FcConfigParse *parse)
+{
+    const FcChar8 *path, *attr, *data;
+    FcChar8 *prefix = NULL;
+
+    data = FcStrBufDoneStatic (&parse->pstack->str);
+    if (!data)
+    {
+	FcConfigMessage (parse, FcSevereError, "out of memory");
+	return;
+    }
+    path = FcConfigGetAttribute (parse, "as-path");
+    if (!path)
+    {
+	FcConfigMessage (parse, FcSevereWarning, "Missing as-path in remap-dir");
+	return;
+    }
+    attr = FcConfigGetAttribute (parse, "prefix");
+    prefix = _get_real_path_from_prefix (parse, data, attr);
+    if (!prefix || prefix[0] == 0)
+	FcConfigMessage (parse, FcSevereWarning, "empty font directory name for remap ignored");
+    else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
+    {
+	if (!FcConfigAddFontDir (parse->config, prefix, path))
+	    FcConfigMessage (parse, FcSevereError, "out of memory; cannot create remap data for %s as %s", prefix, path);
+    }
+    FcStrBufDestroy (&parse->pstack->str);
+
+    if (prefix)
+	FcStrFree (prefix);
+}
+
 static FcExpr *
 FcPopExpr (FcConfigParse *parse)
 {
@@ -2071,130 +2225,26 @@ FcParseUnary (FcConfigParse *parse, FcOp op)
 static void
 FcParseDir (FcConfigParse *parse)
 {
-    const FcChar8 *attr, *data, *map;
-    FcChar8 *prefix = NULL, *p;
-#ifdef _WIN32
-    FcChar8         buffer[1000];
-#endif
+    const FcChar8 *attr, *data;
+    FcChar8 *prefix = NULL;
 
-    attr = FcConfigGetAttribute (parse, "prefix");
-    map = FcConfigGetAttribute (parse, "map");
     data = FcStrBufDoneStatic (&parse->pstack->str);
-    if (attr)
-    {
-	if (FcStrCmp (attr, (const FcChar8 *)"xdg") == 0)
-	{
-	    prefix = FcConfigXdgDataHome ();
-	    /* home directory might be disabled.
-	     * simply ignore this element.
-	     */
-	    if (!prefix)
-		goto bail;
-	}
-	else if (FcStrCmp (attr, (const FcChar8 *)"default") == 0 || FcStrCmp (attr, (const FcChar8 *)"cwd") == 0)
-	{
-	}
-	else if (FcStrCmp (attr, (const FcChar8 *)"relative") == 0)
-	{
-	    prefix = FcStrDirname (parse->name);
-	    if (!prefix)
-		goto bail;
-	}
-    }
-#ifndef _WIN32
-    /* For Win32, check this later for dealing with special cases */
-    else
-    {
-	if (!FcStrIsAbsoluteFilename (data) && data[0] != '~')
-	    FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous <dir> element. please add prefix=\"cwd\" if current behavior is desired.");
-    }
-#endif
     if (!data)
     {
 	FcConfigMessage (parse, FcSevereError, "out of memory");
-	data = prefix;
-	goto bail;
-    }
-    if (prefix)
-    {
-	size_t plen = strlen ((const char *)prefix);
-	size_t dlen = strlen ((const char *)data);
-
-	p = realloc (prefix, plen + 1 + dlen + 1);
-	if (!p)
-	{
-	    FcConfigMessage (parse, FcSevereError, "out of memory");
-	    goto bail;
-	}
-	prefix = p;
-	prefix[plen] = FC_DIR_SEPARATOR;
-	memcpy (&prefix[plen + 1], data, dlen);
-	prefix[plen + 1 + dlen] = 0;
-	data = prefix;
-    }
-#ifdef _WIN32
-    if (strcmp ((const char *) data, "CUSTOMFONTDIR") == 0)
-    {
-	FcChar8 *p;
-	data = buffer;
-	if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
-	{
-	    FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
-	    goto bail;
-	}
-	/*
-	 * Must use the multi-byte aware function to search
-	 * for backslash because East Asian double-byte code
-	 * pages have characters with backslash as the second
-	 * byte.
-	 */
-	p = _mbsrchr (data, '\\');
-	if (p) *p = '\0';
-	strcat ((char *) data, "\\fonts");
-    }
-    else if (strcmp ((const char *) data, "APPSHAREFONTDIR") == 0)
-    {
-	FcChar8 *p;
-	data = buffer;
-	if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
-	{
-	    FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
-	    goto bail;
-	}
-	p = _mbsrchr (data, '\\');
-	if (p) *p = '\0';
-	strcat ((char *) data, "\\..\\share\\fonts");
-    }
-    else if (strcmp ((const char *) data, "WINDOWSFONTDIR") == 0)
-    {
-	int rc;
-	data = buffer;
-	rc = pGetSystemWindowsDirectory ((LPSTR) buffer, sizeof (buffer) - 20);
-	if (rc == 0 || rc > sizeof (buffer) - 20)
-	{
-	    FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed");
-	    goto bail;
-	}
-	if (data [strlen ((const char *) data) - 1] != '\\')
-	    strcat ((char *) data, "\\");
-	strcat ((char *) data, "fonts");
-    }
-    else if (!attr)
-    {
-	if (!FcStrIsAbsoluteFilename (data) && data[0] != '~')
-	    FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous <dir> element. please add prefix=\"cwd\" if current behavior is desired.");
+	return;
     }
-#endif
-    if (strlen ((char *) data) == 0)
+    attr = FcConfigGetAttribute (parse, "prefix");
+    prefix = _get_real_path_from_prefix (parse, data, attr);
+    if (!prefix || prefix[0] == 0)
 	FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
-    else if (!parse->scanOnly && (!FcStrUsesHome (data) || FcConfigHome ()))
+    else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
     {
-	if (!FcConfigAddFontDir (parse->config, data, map))
-	    FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data);
+	if (!FcConfigAddFontDir (parse->config, prefix, NULL))
+	    FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", prefix);
     }
     FcStrBufDestroy (&parse->pstack->str);
 
-  bail:
     if (prefix)
 	FcStrFree (prefix);
 }
@@ -3012,6 +3062,9 @@ FcEndElement(void *userData, const XML_Char *name FC_UNUSED)
     case FcElementDescription:
 	FcParseDescription (parse);
 	break;
+    case FcElementRemapDir:
+	FcParseRemapDir (parse);
+	break;
 
     case FcElementRescan:
 	FcParseRescan (parse);
commit 9d3fb5b38563300e0e31bf7f99f723309ec6316a
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Jan 28 09:40:21 2019 +0000

    Fix make check fail on run-test-conf.sh

diff --git a/test/test-conf.c b/test/test-conf.c
index c0a08de..a8ff1bb 100644
--- a/test/test-conf.c
+++ b/test/test-conf.c
@@ -29,6 +29,7 @@
 
 struct _FcConfig {
     FcStrSet	*configDirs;	    /* directories to scan for fonts */
+    FcStrSet    *configMapDirs;
     FcStrSet	*fontDirs;
     FcStrSet	*cacheDirs;
     FcStrSet	*configFiles;	    /* config files loaded */
commit 500e77a01d00471900755d96ba6ad236d916947a
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Jan 28 04:47:16 2019 +0000

    Drop a line to include uuid.h

diff --git a/src/fccache.c b/src/fccache.c
index c728553..bec017e 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -38,8 +38,6 @@
 #endif
 #if defined(_WIN32)
 #include <sys/locking.h>
-#else
-#include <uuid/uuid.h>
 #endif
 
 #ifndef O_BINARY
commit 04f75fce0bd060b780af6d05314852be6df27216
Author: Akira TAGOH <akira@xxxxxxxxx>
Date:   Mon Jan 28 04:44:31 2019 +0000

    Add FcDirCacheCreateUUID doc back to pass make check

diff --git a/doc/fccache.fncs b/doc/fccache.fncs
index 2b435a0..cf79134 100644
--- a/doc/fccache.fncs
+++ b/doc/fccache.fncs
@@ -89,6 +89,17 @@ to <parameter>config</parameter>.
 @@
 
 @RET@		FcBool
+@FUNC@		FcDirCacheCreateUUID
+@TYPE1@		FcChar8 *			@ARG1@		dir
+@TYPE2@		FcBool				@ARG2@		force
+@TYPE3@		FcConfig *			@ARG3@		config
+@PURPOSE@	Create .uuid file at a directory
+@DESC@
+This function is deprecated. it doesn't take any effects.
+@SINCE@		2.12.92
+@@
+
+@RET@		FcBool
 @FUNC@		FcDirCacheDeleteUUID
 @TYPE1@		const FcChar8 *			@ARG1@		dir
 @TYPE2@		FcConfig *			@ARG2@		config
commit c4324f54ee16e648ba91f3e9c66af13ab3b1754c
Author: Keith Packard <keithp@xxxxxxxxxx>
Date:   Mon Oct 29 16:39:05 2018 -0700

    Replace UUID file mechanism with per-directory 'map' attribute [v2]
    
    The UUID files would be placed in each font directory to provide the
    unique cache name, independent of path, for that directory. The UUID
    files are undesireable for a couple of reasons:
    
     1) They must be placed in the font directories to be useful. This
        requires modifying the font directories themselves, introducing
        potential visible timestamp changes when running multiple
        applications, and makes the cache processing inconsistent between
        applications with permission to write to the font directories and
        applications without such permission.
    
     2) The UUID contents were generated randomly, which makes the font
        cache not reproducible across multiple runs.
    
    One proposed fix for 2) is to make the UUID dependent on the font
    directory path, but once we do that, we can simply use the font
    directory path itself as the key as the original MD5-based font cache
    naming mechanism did.
    
    The goal of the UUID file mechanism was to fix startup time of
    flatpaks; as the font path names inside the flatpak did not match the
    font path names in the base system, the font cache would need to be
    reconstructed the first time the flatpak was launched.
    
    The new mechanism for doing this is to allow each '<dir>' element in
    the configuration include a 'map' attribute. When looking for a cache
    file for a particular directory, if the directory name starts with the
    contents of the <dir> element, that portion of the name will be
    replaced with the value of the 'map' attribute.
    
    Outside of the flatpak, nothing need change -- fontconfig will build
    cache files using real directory names.
    
    Inside the flatpak, the custom fonts.conf file will now include
    mappings such as this:
    
            <dir map="/usr/share/fonts">/run/host/fonts</dir>
    
    When scanning the directory /run/host/fonts/ttf, fontconfig will
    use the name /usr/share/fonts/ttf as the source for building the cache
    file name.
    
    The existing FC_FILE replacement code used for the UUID-based
    implementation continues to correctly adapt font path names seen by
    applications.
    
    v2:
            Leave FcDirCacheCreateUUID stub around to avoid removing
            public API function.
    
            Document 'map' attribute of <dir> element in
            fontconfig-user.sgml
    
            Suggested-by: Akira TAGOH <akira@xxxxxxxxx>
    
    Signed-off-by: Keith Packard <keithp@xxxxxxxxxx>

diff --git a/configure.ac b/configure.ac
index 5eaadb8..ff5f2c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -333,39 +333,6 @@ LIBS="$fontconfig_save_libs"
 CFLAGS="$fontconfig_save_cflags"
 
 #
-# Check for uuid
-#
-if test "$os_win32" != "yes"; then
-	use_pkgconfig_for_uuid=yes
-	if test -n "${UUID_LIBS}"; then
-		save_UUID_LIBS=$UUID_LIBS
-	fi
-	PKG_CHECK_MODULES([UUID], [uuid],
-			  [use_pkgconfig_for_uuid=yes],
-			  [use_pkgconfig_for_uuid=no])
-	if test "x$use_pkgconfig_for_uuid" = "xno"; then
-		AC_MSG_CHECKING([where uuid functions comes from])
-		AC_TRY_LINK([#include <uuid/uuid.h>],
-			[uuid_t a; uuid_generate(a);],
-			[AC_MSG_RESULT([builtin])
-			 UUID_CFLAGS=""
-			 UUID_LIBS=""
-			],[AC_MSG_ERROR([
-*** uuid is required. install util-linux.
-			])])
-	else
-		if test -z "${save_UUID_LIBS+x}" && test "x${UUID_LIBS}" != "x"; then
-			PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY uuid"
-		fi
-	fi
-else
-	UUID_CFLAGS=""
-	UUID_LIBS=""
-fi
-AC_SUBST(UUID_CFLAGS)
-AC_SUBST(UUID_LIBS)
-
-#
 # Check expat configuration
 #
 AC_ARG_WITH(expat,
diff --git a/doc/fccache.fncs b/doc/fccache.fncs
index 972b642..2b435a0 100644
--- a/doc/fccache.fncs
+++ b/doc/fccache.fncs
@@ -89,20 +89,6 @@ to <parameter>config</parameter>.
 @@
 
 @RET@		FcBool
-@FUNC@		FcDirCacheCreateUUID
-@TYPE1@		FcChar8 *			@ARG1@		dir
-@TYPE2@		FcBool				@ARG2@		force
-@TYPE3@		FcConfig *			@ARG3@		config
-@PURPOSE@	Create .uuid file at a directory
-@DESC@
-This is to create .uuid file containing an UUID at a font directory of
-<parameter>dir</parameter>.
-The UUID will be used to identify the font directory and is used to determine
-the cache filename if available.
-@SINCE@		2.12.92
-@@
-
-@RET@		FcBool
 @FUNC@		FcDirCacheDeleteUUID
 @TYPE1@		const FcChar8 *			@ARG1@		dir
 @TYPE2@		FcConfig *			@ARG2@		config
diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml
index f23ae36..92e3e5a 100644
--- a/doc/fontconfig-user.sgml
+++ b/doc/fontconfig-user.sgml
@@ -310,9 +310,15 @@ following structure:
 This is the top level element for a font configuration and can contain
 <literal>&lt;dir&gt;</literal>, <literal>&lt;cachedir&gt;</literal>, <literal>&lt;include&gt;</literal>, <literal>&lt;match&gt;</literal> and <literal>&lt;alias&gt;</literal> elements in any order.
   </para></refsect2>
-  <refsect2><title><literal>&lt;dir prefix="default"&gt;</literal></title><para>
+  <refsect2><title><literal>&lt;dir prefix="default" map=""&gt;</literal></title><para>
 This element contains a directory name which will be scanned for font files
 to include in the set of available fonts. If 'prefix' is set to "default" or "cwd", the current working directory will be added as the path prefix prior to the value. If 'prefix' is set to "xdg", the value in the XDG_DATA_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. If 'prefix' is set to "relative", the path of current file will be added prior to the value.
+</para><para>
+If a 'map' attribute is specified, its value will replace the
+directory path when matching cached information for fonts contained in
+this directory. This is useful if the directory name is an alias
+(via a bind mount or symlink) to another directory in the system for
+which cached font information is likely to exist.
   </para></refsect2>
   <refsect2><title><literal>&lt;cachedir prefix="default"&gt;</literal></title><para>
 This element contains a directory name that is supposed to be stored or read
diff --git a/fc-cache/fc-cache.c b/fc-cache/fc-cache.c
index 71cb61f..e0816c9 100644
--- a/fc-cache/fc-cache.c
+++ b/fc-cache/fc-cache.c
@@ -203,7 +203,6 @@ scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force,
 	if (really_force)
 	{
 	    FcDirCacheUnlink (dir, config);
-	    FcDirCacheCreateUUID ((FcChar8 *) dir, FcTrue, config);
 	}
 
 	cache = NULL;
diff --git a/fonts.dtd b/fonts.dtd
index 2d75682..8a95fa5 100644
--- a/fonts.dtd
+++ b/fonts.dtd
@@ -14,6 +14,7 @@
 -->
 <!ELEMENT dir (#PCDATA)>
 <!ATTLIST dir
+	  map       CDATA                         #IMPLIED
 	  prefix    (default|xdg|relative|cwd)    "default"
 	  xml:space (default|preserve)            'preserve'>
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 7b414df..35e820d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,7 +77,6 @@ AM_CPPFLAGS = 						\
 	$(ICONV_CFLAGS)					\
 	$(LIBXML2_CFLAGS)				\
 	$(EXPAT_CFLAGS)					\
-	$(UUID_CFLAGS)					\
 	$(WARN_CFLAGS)					\
 	-DFC_CACHEDIR='"$(FC_CACHEDIR)"'                \
 	-DFONTCONFIG_PATH='"$(BASECONFIGDIR)"'		\
@@ -167,7 +166,7 @@ lib_LTLIBRARIES = libfontconfig.la
 libfontconfig_la_LDFLAGS =			\
 	-version-info @LIBT_VERSION_INFO@ -no-undefined $(export_symbols)
 
-libfontconfig_la_LIBADD = $(ICONV_LIBS) $(FREETYPE_LIBS) $(LIBXML2_LIBS) $(EXPAT_LIBS) $(UUID_LIBS) $(LTLIBINTL)
+libfontconfig_la_LIBADD = $(ICONV_LIBS) $(FREETYPE_LIBS) $(LIBXML2_LIBS) $(EXPAT_LIBS) $(LTLIBINTL)
 
 libfontconfig_la_DEPENDENCIES = $(fontconfig_def_dependency)
 
diff --git a/src/fccache.c b/src/fccache.c
index fa3451e..c728553 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -51,103 +51,7 @@ FcDirCacheCreateUUID (FcChar8  *dir,
 		      FcBool    force,
 		      FcConfig *config)
 {
-    FcBool ret = FcTrue;
-#ifndef _WIN32
-    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
-    FcChar8 *target;
-    FcChar8 *uuidname;
-
-    if (sysroot)
-	target = FcStrBuildFilename (sysroot, dir, NULL);
-    else
-	target = FcStrdup (dir);
-    uuidname = FcStrBuildFilename (target, ".uuid", NULL);
-
-    if (!uuidname)
-    {
-	FcStrFree (target);
-	return FcFalse;
-    }
-
-    if (force || access ((const char *) uuidname, F_OK) < 0)
-    {
-	FcAtomic *atomic;
-	int fd;
-	uuid_t uuid;
-	char out[37];
-	FcBool (* hash_add) (FcHashTable *, void*, void*);
-	struct stat statb;
-	struct timeval times[2];
-
-	if (FcStat (target, &statb) != 0)
-	{
-	    ret = FcFalse;
-	    goto bail1;
-	}
-	atomic = FcAtomicCreate (uuidname);
-	if (!atomic)
-	{
-	    ret = FcFalse;
-	    goto bail1;
-	}
-	if (!FcAtomicLock (atomic))
-	{
-	    ret = FcFalse;
-	    goto bail2;
-	}
-	fd = FcOpen ((char *)FcAtomicNewFile (atomic), O_RDWR | O_CREAT, 0644);
-	if (fd == -1)
-	{
-	    ret = FcFalse;
-	    goto bail3;
-	}
-	uuid_generate_random (uuid);
-	if (force)
-	    hash_add = FcHashTableReplace;
-	else
-	    hash_add = FcHashTableAdd;
-	if (!hash_add (config->uuid_table, target, uuid))
-	{
-	    ret = FcFalse;
-	    FcAtomicDeleteNew (atomic);
-	    close (fd);
-	    goto bail3;
-	}
-	uuid_unparse (uuid, out);
-	if (FcDebug () & FC_DBG_CACHE)
-	    printf ("FcDirCacheCreateUUID %s: %s\n", uuidname, out);
-	write (fd, out, strlen (out));
-	close (fd);
-	FcAtomicReplaceOrig (atomic);
-    bail3:
-	FcAtomicUnlock (atomic);
-    bail2:
-	FcAtomicDestroy (atomic);
-
-	if (ret)
-	{
-	    /* revert mtime of the directory */
-	    times[0].tv_sec = statb.st_atime;
-	    times[1].tv_sec = statb.st_mtime;
-#ifdef HAVE_STRUCT_STAT_ST_MTIM
-	    times[0].tv_usec = statb.st_atim.tv_nsec / 1000;
-	    times[1].tv_usec = statb.st_mtim.tv_nsec / 1000;
-#else
-	    times[0].tv_usec = 0;
-	    times[1].tv_usec = 0;
-#endif
-	    if (utimes ((const  char *) target, times) != 0)
-	    {
-		fprintf (stderr, "Unable to revert mtime: %s\n", target);
-	    }
-	}
-    }
-bail1:
-    FcStrFree (uuidname);
-    FcStrFree (target);
-#endif
-
-    return ret;
+    return FcTrue;
 }
 
 FcBool
@@ -187,7 +91,6 @@ FcDirCacheDeleteUUID (const FcChar8  *dir,
 	{
 	    fprintf (stderr, "Unable to revert mtime: %s\n", d);
 	}
-	FcHashTableRemove (config->uuid_table, target);
     }
     FcStrFree (target);
 bail:
@@ -197,59 +100,6 @@ bail:
     return ret;
 }
 
-#ifndef _WIN32
-static void
-FcDirCacheReadUUID (FcChar8  *dir,
-		    FcConfig *config)
-{
-    void *u;
-    uuid_t uuid;
-    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
-    FcChar8 *target;
-
-    if (sysroot)
-	target = FcStrBuildFilename (sysroot, dir, NULL);
-    else
-	target = FcStrdup (dir);
-
-    if (!FcHashTableFind (config->uuid_table, target, &u))
-    {
-	FcChar8 *uuidname = FcStrBuildFilename (target, ".uuid", NULL);
-	int fd;
-
-	if ((fd = FcOpen ((char *) uuidname, O_RDONLY)) >= 0)
-	{
-	    char suuid[37];
-	    ssize_t len;
-
-	    memset (suuid, 0, sizeof (suuid));
-	    len = read (fd, suuid, 36);
-	    if (len != -1)
-	    {
-		suuid[len] = 0;
-		memset (uuid, 0, sizeof (uuid));
-		if (uuid_parse (suuid, uuid) == 0)
-		{
-		    if (FcDebug () & FC_DBG_CACHE)
-			printf ("FcDirCacheReadUUID %s -> %s\n", uuidname, suuid);
-		    FcHashTableAdd (config->uuid_table, target, uuid);
-		}
-	    }
-	    close (fd);
-	}
-	else
-	{
-	    if (FcDebug () & FC_DBG_CACHE)
-		printf ("FcDirCacheReadUUID Unable to read %s\n", uuidname);
-	}
-	FcStrFree (uuidname);
-    }
-    else
-	FcHashUuidFree (u);
-    FcStrFree (target);
-}
-#endif
-
 struct MD5Context {
         FcChar32 buf[4];
         FcChar32 bits[2];
@@ -300,18 +150,26 @@ static const char bin2hex[] = { '0', '1', '2', '3',
 				'c', 'd', 'e', 'f' };
 
 static FcChar8 *
-FcDirCacheBasenameMD5 (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
+FcDirCacheBasenameMD5 (FcConfig *config, const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
 {
+    FcChar8		*new_dir;
     unsigned char 	hash[16];
     FcChar8		*hex_hash;
     int			cnt;
     struct MD5Context 	ctx;
 
+    new_dir = FcConfigMapFontPath(config, dir);
+    if (new_dir)
+	dir = new_dir;
+
     MD5Init (&ctx);
     MD5Update (&ctx, (const unsigned char *)dir, strlen ((const char *) dir));
 
     MD5Final (hash, &ctx);
 
+    if (new_dir)
+	FcStrFree(new_dir);
+
     cache_base[0] = '/';
     hex_hash = cache_base + 1;
     for (cnt = 0; cnt < 16; ++cnt)
@@ -325,31 +183,6 @@ FcDirCacheBasenameMD5 (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN])
     return cache_base;
 }
 
-#ifndef _WIN32
-static FcChar8 *
-FcDirCacheBasenameUUID (const FcChar8 *dir, FcChar8 cache_base[CACHEBASE_LEN], FcConfig *config)
-{
-    void *u;
-    FcChar8 *target;
-    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
-
-    if (sysroot)
-	target = FcStrBuildFilename (sysroot, dir, NULL);
-    else
-	target = FcStrdup (dir);
-    if (FcHashTableFind (config->uuid_table, target, &u))
-    {
-	uuid_unparse (u, (char *) cache_base);
-	strcat ((char *) cache_base, "-" FC_ARCHITECTURE FC_CACHE_SUFFIX);
-	FcHashUuidFree (u);
-	FcStrFree (target);
-	return cache_base;
-    }
-    FcStrFree (target);
-    return NULL;
-}
-#endif
-
 FcBool
 FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
 {
@@ -359,10 +192,7 @@ FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
     FcChar8	*cache_dir;
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
 
-#ifndef _WIN32
-    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
-#endif
-	FcDirCacheBasenameMD5 (dir, cache_base);
+    FcDirCacheBasenameMD5 (config, dir, cache_base);
 
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
@@ -439,10 +269,7 @@ FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
     }
     FcStrFree (d);
 
-#ifndef _WIN32
-    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
-#endif
-	FcDirCacheBasenameMD5 (dir, cache_base);
+    FcDirCacheBasenameMD5 (config, dir, cache_base);
 
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
@@ -1070,9 +897,6 @@ FcDirCacheLoad (const FcChar8 *dir, FcConfig *config, FcChar8 **cache_file)
 {
     FcCache *cache = NULL;
 
-#ifndef _WIN32
-    FcDirCacheReadUUID ((FcChar8 *) dir, config);
-#endif
     if (!FcDirCacheProcess (config, dir,
 			    FcDirCacheMapHelper,
 			    &cache, cache_file))
@@ -1377,10 +1201,7 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
     if (!cache_dir)
 	return FcFalse;
 
-#ifndef _WIN32
-    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
-#endif
-	FcDirCacheBasenameMD5 (dir, cache_base);
+    FcDirCacheBasenameMD5 (config, dir, cache_base);
     cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
     FcStrFree (cache_dir);
     if (!cache_hashed)
@@ -1577,10 +1398,7 @@ FcDirCacheLock (const FcChar8 *dir,
     const FcChar8 *sysroot = FcConfigGetSysRoot (config);
     int fd = -1;
 
-#ifndef _WIN32
-    if (!FcDirCacheBasenameUUID (dir, cache_base, config))
-#endif
-	FcDirCacheBasenameMD5 (dir, cache_base);
+    FcDirCacheBasenameMD5 (config, dir, cache_base);
     list = FcStrListCreate (config->cacheDirs);
     if (!list)
 	return -1;
diff --git a/src/fccfg.c b/src/fccfg.c
index 11df5ca..fee2053 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -52,18 +52,6 @@ retry:
     return config;
 }
 
-static FcChar32
-FcHashAsStrIgnoreCase (const void *data)
-{
-    return FcStrHashIgnoreCase (data);
-}
-
-static int
-FcCompareAsStr (const void *v1, const void *v2)
-{
-    return FcStrCmp (v1, v2);
-}
-
 static void
 FcDestroyAsRule (void *data)
 {
@@ -76,12 +64,6 @@ FcDestroyAsRuleSet (void *data)
     FcRuleSetDestroy (data);
 }
 
-static void
-FcDestroyAsStr (void *data)
-{
-    FcStrFree (data);
-}
-
 FcBool
 FcConfigInit (void)
 {
@@ -127,6 +109,10 @@ FcConfigCreate (void)
     if (!config->configDirs)
 	goto bail1;
 
+    config->configMapDirs = FcStrSetCreate();
+    if (!config->configMapDirs)
+	goto bail1_5;
+
     config->configFiles = FcStrSetCreate ();
     if (!config->configFiles)
 	goto bail2;
@@ -182,13 +168,6 @@ FcConfigCreate (void)
     if (!config->availConfigFiles)
 	goto bail10;
 
-    config->uuid_table = FcHashTableCreate (FcHashAsStrIgnoreCase,
-					    FcCompareAsStr,
-					    FcHashStrCopy,
-					    FcHashUuidCopy,
-					    FcDestroyAsStr,
-					    FcHashUuidFree);
-
     FcRefInit (&config->ref, 1);
 
     return config;
@@ -213,6 +192,8 @@ bail4:
 bail3:
     FcStrSetDestroy (config->configFiles);
 bail2:
+    FcStrSetDestroy (config->configMapDirs);
+bail1_5:
     FcStrSetDestroy (config->configDirs);
 bail1:
     free (config);
@@ -324,6 +305,7 @@ FcConfigDestroy (FcConfig *config)
     (void) fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL);
 
     FcStrSetDestroy (config->configDirs);
+    FcStrSetDestroy (config->configMapDirs);
     FcStrSetDestroy (config->fontDirs);
     FcStrSetDestroy (config->cacheDirs);
     FcStrSetDestroy (config->configFiles);
@@ -350,8 +332,6 @@ FcConfigDestroy (FcConfig *config)
     if (config->sysRoot)
 	FcStrFree (config->sysRoot);
 
-    FcHashTableDestroy (config->uuid_table);
-
     free (config);
 }
 
@@ -559,9 +539,10 @@ FcConfigGetConfigDirs (FcConfig   *config)
 
 FcBool
 FcConfigAddFontDir (FcConfig	    *config,
-		    const FcChar8   *d)
+		    const FcChar8   *d,
+		    const FcChar8   *m)
 {
-    return FcStrSetAddFilename (config->fontDirs, d);
+    return FcStrSetAddFilenamePair (config->fontDirs, d, m);
 }
 
 FcStrList *
@@ -576,6 +557,47 @@ FcConfigGetFontDirs (FcConfig	*config)
     return FcStrListCreate (config->fontDirs);
 }
 
+static FcBool
+FcConfigPathStartsWith(const FcChar8	*path,
+		       const FcChar8	*start)
+{
+    int len = strlen((char *) start);
+
+    if (strncmp((char *) path, (char *) start, len) != 0)
+	return FcFalse;
+
+    switch (path[len]) {
+    case '\0':
+    case FC_DIR_SEPARATOR:
+	return FcTrue;
+    default:
+	return FcFalse;
+    }
+}
+
+FcChar8 *
+FcConfigMapFontPath(FcConfig		*config,
+		    const FcChar8	*path)
+{
+    FcStrList	*list;
+    FcChar8	*dir;
+    FcChar8	*map;
+
+    list = FcConfigGetFontDirs(config);
+    if (!list)
+	return 0;
+    while ((dir = FcStrListNext(list)))
+	if (FcConfigPathStartsWith(path, dir))
+	    break;
+    FcStrListDone(list);
+    if (!dir)
+	return 0;
+    map = FcStrPairSecond(dir);
+    if (!map)
+	return 0;
+    return FcStrBuildFilename(map, path + strlen((char *) dir), NULL);
+}
+
 FcBool
 FcConfigAddCacheDir (FcConfig	    *config,
 		     const FcChar8  *d)
diff --git a/src/fcdir.c b/src/fcdir.c
index bfcdf95..7d7b23c 100644
--- a/src/fcdir.c
+++ b/src/fcdir.c
@@ -413,7 +413,6 @@ FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config)
 {
     FcCache		*cache = NULL;
 
-    FcDirCacheCreateUUID ((FcChar8 *) dir, FcFalse, config);
     /* Try to use existing cache file */
     if (!force)
 	cache = FcDirCacheLoad (dir, config, NULL);
diff --git a/src/fchash.c b/src/fchash.c
index 2f06f1a..481bf21 100644
--- a/src/fchash.c
+++ b/src/fchash.c
@@ -52,23 +52,6 @@ FcHashStrCopy (const void  *src,
     return *dest != NULL;
 }
 
-FcBool
-FcHashUuidCopy (const void  *src,
-		void       **dest)
-{
-#ifndef _WIN32
-    *dest = malloc (sizeof (uuid_t));
-    uuid_copy (*dest, src);
-#endif
-    return FcTrue;
-}
-
-void
-FcHashUuidFree (void *data)
-{
-    free (data);
-}
-
 FcHashTable *
 FcHashTableCreate (FcHashFunc    hash_func,
 		   FcCompareFunc compare_func,
diff --git a/src/fcint.h b/src/fcint.h
index d473955..593b100 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -509,6 +509,7 @@ struct _FcConfig {
      * and those directives may occur in any order
      */
     FcStrSet	*configDirs;	    /* directories to scan for fonts */
+    FcStrSet	*configMapDirs;	    /* mapped names to generate cache entries */
     /*
      * List of directories containing fonts,
      * built by recursively scanning the set
@@ -565,7 +566,6 @@ struct _FcConfig {
     FcChar8     *sysRoot;	    /* override the system root directory */
     FcStrSet	*availConfigFiles;  /* config files available */
     FcPtrList	*rulesetList;	    /* List of rulesets being installed */
-    FcHashTable *uuid_table;	    /* UUID table for cachedirs */
 };
 
 typedef struct _FcFileTime {
@@ -659,7 +659,12 @@ FcConfigAddConfigDir (FcConfig	    *config,
 
 FcPrivate FcBool
 FcConfigAddFontDir (FcConfig	    *config,
-		    const FcChar8   *d);
+		    const FcChar8   *d,
+		    const FcChar8   *m);
+
+FcPrivate FcChar8 *
+FcConfigMapFontPath(FcConfig		*config,
+		    const FcChar8	*path);
 
 FcPrivate FcBool
 FcConfigAddCacheDir (FcConfig	    *config,
@@ -1236,6 +1241,15 @@ FcStrSetAddLangs (FcStrSet *strs, const char *languages);
 FcPrivate void
 FcStrSetSort (FcStrSet * set);
 
+FcPrivate FcBool
+FcStrSetAddPair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b);
+
+FcPrivate FcChar8 *
+FcStrPairSecond (FcChar8 *s);
+
+FcPrivate FcBool
+FcStrSetAddFilenamePair (FcStrSet *strs, const FcChar8 *d, const FcChar8 *m);
+
 FcPrivate void
 FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size);
 
diff --git a/src/fcstr.c b/src/fcstr.c
index 4247c85..4e0a2b6 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -36,6 +36,27 @@ FcStrCopy (const FcChar8 *s)
     return FcStrdup (s);
 }
 
+static FcChar8 *
+FcStrMakePair (const FcChar8 *s1, const FcChar8 *s2)
+{
+    int	    s1l = s1 ? strlen ((char *) s1) : 0;
+    int	    s2l = s2 ? strlen ((char *) s2) : 0;
+    int	    l = s1l + 1 + s2l + 1;
+    FcChar8 *s = malloc (l);
+
+    if (!s)
+	return 0;
+    if (s1)
+	memcpy (s, s1, s1l + 1);
+    else
+	s[0] = '\0';
+    if (s2)
+	memcpy (s + s1l + 1, s2, s2l + 1);
+    else
+	s[s1l + 1] = '\0';
+    return s;
+}
+
 FcChar8 *
 FcStrPlus (const FcChar8 *s1, const FcChar8 *s2)
 {
@@ -1234,6 +1255,30 @@ FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
 }
 
 FcBool
+FcStrSetAddPair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b)
+{
+    FcChar8 *new = FcStrMakePair (a, b);
+    if (!new)
+	return FcFalse;
+    if (!_FcStrSetAppend (set, new))
+    {
+	FcStrFree (new);
+	return FcFalse;
+    }
+    return FcTrue;
+}
+
+FcChar8 *
+FcStrPairSecond (FcChar8 *str)
+{
+    FcChar8 *second = str + strlen((char *) str) + 1;
+
+    if (*second == '\0')
+	return 0;
+    return second;
+}
+
+FcBool
 FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
 {
     FcChar8 *new = FcStrCopyFilename (s);
@@ -1248,6 +1293,37 @@ FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
 }
 
 FcBool
+FcStrSetAddFilenamePair (FcStrSet *set, const FcChar8 *a, const FcChar8 *b)
+{
+    FcChar8 *new_a = NULL;
+    FcChar8 *new_b = NULL;
+    FcBool  ret;
+
+    if (a)
+    {
+	new_a = FcStrCopyFilename (a);
+	if (!new_a)
+	    return FcFalse;
+    }
+    if (b)
+    {
+	new_b = FcStrCopyFilename(b);
+	if (!new_b)
+	{
+	    if (new_a)
+		FcStrFree(new_a);
+	    return FcFalse;
+	}
+    }
+    ret = FcStrSetAddPair (set, new_a, new_b);
+    if (new_a)
+	FcStrFree (new_a);
+    if (new_b)
+	FcStrFree (new_b);
+    return ret;
+}
+
+FcBool
 FcStrSetAddLangs (FcStrSet *strs, const char *languages)
 {
     const char *p = languages, *next;
diff --git a/src/fcxml.c b/src/fcxml.c
index 103b248..c2ad723 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -2071,13 +2071,14 @@ FcParseUnary (FcConfigParse *parse, FcOp op)
 static void
 FcParseDir (FcConfigParse *parse)
 {
-    const FcChar8 *attr, *data;
+    const FcChar8 *attr, *data, *map;
     FcChar8 *prefix = NULL, *p;
 #ifdef _WIN32
     FcChar8         buffer[1000];
 #endif
 
     attr = FcConfigGetAttribute (parse, "prefix");
+    map = FcConfigGetAttribute (parse, "map");
     data = FcStrBufDoneStatic (&parse->pstack->str);
     if (attr)
     {
@@ -2188,7 +2189,7 @@ FcParseDir (FcConfigParse *parse)
 	FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
     else if (!parse->scanOnly && (!FcStrUsesHome (data) || FcConfigHome ()))
     {
-	if (!FcConfigAddFontDir (parse->config, data))
+	if (!FcConfigAddFontDir (parse->config, data, map))
 	    FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data);
     }
     FcStrBufDestroy (&parse->pstack->str);
diff --git a/test/Makefile.am b/test/Makefile.am
index ff693e4..81aace0 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,4 @@
-check_SCRIPTS=run-test.sh
+check_SCRIPTS=run-test.sh run-test-map.sh
 TEST_EXTENSIONS = \
 	.sh \
 	$(NULL)
diff --git a/test/fonts.conf.in b/test/fonts.conf.in
index 95def72..24bd58b 100644
--- a/test/fonts.conf.in
+++ b/test/fonts.conf.in
@@ -1,4 +1,4 @@
 <fontconfig>
-<dir>@FONTDIR@</dir>
+<dir @MAP@>@FONTDIR@</dir>
 <cachedir>@CACHEDIR@</cachedir>
 </fontconfig>
diff --git a/test/run-test-map.sh b/test/run-test-map.sh
new file mode 100755
index 0000000..869d7b2
--- /dev/null
+++ b/test/run-test-map.sh
@@ -0,0 +1,107 @@
+#!/bin/bash
+# fontconfig/test/run-test-cache-map.sh
+#
+# Copyright © 2018 Keith Packard
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that copyright
+# notice and this permission notice appear in supporting documentation, and
+# that the name of the copyright holders not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  The copyright holders make no representations
+# about the suitability of this software for any purpose.  It is provided "as
+# is" without express or implied warranty.
+#
+# THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+case "$OSTYPE" in
+    msys ) MyPWD=`pwd -W` ;;  # On Msys/MinGW, returns a MS Windows style path.
+    *    ) MyPWD=`pwd`    ;;  # On any other platforms, returns a Unix style path.
+esac
+
+TESTDIR=${srcdir-"$MyPWD"}
+BUILDTESTDIR=${builddir-"$MyPWD"}
+
+FONTDIRA="$MyPWD"/fontsa
+FONTDIRB="$MyPWD"/fontsb
+CACHEDIR="$MyPWD"/cache.dir
+EXPECTEDIN=${EXPECTEDIN-"out-map.expected.in"}
+EXPECTEDA="out-map-a.expected"
+EXPECTEDB="out-map-b.expected"
+EXPECTED="out-map.expected"
+
+FCLIST=../fc-list/fc-list$EXEEXT
+FCCACHE=../fc-cache/fc-cache$EXEEXT
+
+which bwrap > /dev/null 2>&1
+if [ $? -eq 0 ]; then
+    BWRAP=`which bwrap`
+fi
+
+FONT1=$TESTDIR/4x6.pcf
+FONT2=$TESTDIR/8x16.pcf
+
+check () {
+  $FCLIST - file family pixelsize | sort > out
+  echo "=" >> out
+  $FCLIST - file family pixelsize | sort >> out
+  echo "=" >> out
+  $FCLIST - file family pixelsize | sort >> out
+  tr -d '\015' <out >out.tmp; mv out.tmp out
+  if cmp out $BUILDTESTDIR/$EXPECTED > /dev/null ; then : ; else
+    echo "*** Test failed: $TEST"
+    echo "*** output is in 'out', expected output in '$EXPECTED'"
+    exit 1
+  fi
+  rm -f out
+}
+
+prep() {
+  rm -rf $CACHEDIR
+  rm -rf $FONTDIRA $FONTDIRB
+  mkdir $FONTDIRA
+  mkdir $CACHEDIR
+}
+
+dotest () {
+  TEST=$1
+  test x$VERBOSE = x || echo Running: $TEST
+}
+
+sed "s!@FONTDIR@!$FONTDIRA!
+s!@MAP@!!
+s!@CACHEDIR@!$CACHEDIR!" < $TESTDIR/fonts.conf.in > fonts-a.conf
+
+sed "s!@FONTDIR@!$FONTDIRB!
+s!@MAP@!map="'"'"$FONTDIRA"'"'"!
+s!@CACHEDIR@!$CACHEDIR!" < $TESTDIR/fonts.conf.in > fonts-b.conf
+
+sed "s!@FONTDIR@!$FONTDIRA!" < $EXPECTEDIN > $EXPECTEDA
+sed "s!@FONTDIR@!$FONTDIRB!" < $EXPECTEDIN > $EXPECTEDB
+
+FONTCONFIG_FILE="$MyPWD"/fonts-a.conf
+export FONTCONFIG_FILE
+
+dotest "Basic check"
+prep
+cp $FONT1 $FONT2 $FONTDIRA
+cp $EXPECTEDA $EXPECTED
+$FCCACHE $FONTDIRA
+check
+
+dotest "mapped check"
+prep
+cp $FONT1 $FONT2 $FONTDIRA
+cp $EXPECTEDB $EXPECTED
+$FCCACHE $FONTDIRA
+mv $FONTDIRA $FONTDIRB
+export FONTCONFIG_FILE="$MyPWD"/fonts-b.conf
+check
diff --git a/test/run-test.sh b/test/run-test.sh
index a05dadb..b9a07b8 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -73,6 +73,7 @@ dotest () {
 }
 
 sed "s!@FONTDIR@!$FONTDIR!
+s!@MAP@!!
 s!@CACHEDIR@!$CACHEDIR!" < $TESTDIR/fonts.conf.in > fonts.conf
 
 FONTCONFIG_FILE="$MyPWD"/fonts.conf
@@ -145,6 +146,7 @@ sleep 1
 ls -l $CACHEDIR > out1
 TESTTMPDIR=`mktemp -d /tmp/fontconfig.XXXXXXXX`
 sed "s!@FONTDIR@!$TESTTMPDIR/fonts!
+s!@MAP@!map="'"'"$FONTDIR"'"'"!
 s!@CACHEDIR@!$TESTTMPDIR/cache.dir!" < $TESTDIR/fonts.conf.in > bind-fonts.conf
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/fc-match/fc-match$EXEEXT -f "%{file}\n" ":foundry=Misc" > xxx
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/test/test-bz106618$EXEEXT | sort > flist1
commit 4cde12bfda1316e6d5464a2d9607d15322ef8024
Author: Keith Packard <keithp@xxxxxxxxxx>
Date:   Mon Oct 29 16:25:13 2018 -0700

    Remove UUID-related tests
    
    Remove test-hash
    Remove UUID tests from run-test.sh
    
    Signed-off-by: Keith Packard <keithp@xxxxxxxxxx>

diff --git a/test/Makefile.am b/test/Makefile.am
index afdf343..ff693e4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -76,12 +76,6 @@ endif
 check_PROGRAMS += test-bz106618
 test_bz106618_LDADD = $(top_builddir)/src/libfontconfig.la
 
-if !OS_WIN32
-check_PROGRAMS += test-hash
-test_hash_CFLAGS = -I$(top_builddir) -I$(top_builddir)/src $(UUID_CFLAGS)
-test_hash_LDADD = $(UUID_LIBS)
-TESTS += test-hash
-
 check_PROGRAMS += test-bz106632
 test_bz106632_CFLAGS =					\
 	-I$(top_builddir)				\
diff --git a/test/run-test.sh b/test/run-test.sh
index fdf8d6a..a05dadb 100644
--- a/test/run-test.sh
+++ b/test/run-test.sh
@@ -123,51 +123,6 @@ mkdir $FONTDIR/a
 cp $FONT2 $FONTDIR/a
 check
 
-if [ "x$EXEEXT" = "x" ]; then
-dotest "Re-creating .uuid"
-prep
-cp $FONT1 $FONTDIR
-$FCCACHE $FONTDIR
-cat $FONTDIR/.uuid > out1
-$FCCACHE -f $FONTDIR
-cat $FONTDIR/.uuid > out2
-if cmp out1 out2 > /dev/null ; then : ; else
-  echo "*** Test failed: $TEST"
-  echo "*** .uuid was modified unexpectedly"
-  exit 1
-fi
-$FCCACHE -r $FONTDIR
-cat $FONTDIR/.uuid > out2
-if cmp out1 out2 > /dev/null ; then
-  echo "*** Test failed: $TEST"
-  echo "*** .uuid wasn't modified"
-  exit 1
-fi
-rm -f out1 out2
-
-dotest "Consistency between .uuid and cache name"
-prep
-cp $FONT1 $FONTDIR
-$FCCACHE $FONTDIR
-cat $FONTDIR/.uuid
-$FCCACHE -r $FONTDIR
-uuid=`cat $FONTDIR/.uuid`
-ls $CACHEDIR/$uuid*
-if [ $? != 0 ]; then
-  echo "*** Test failed: $TEST"
-  echo "No cache for $uuid"
-  ls $CACHEDIR
-  exit 1
-fi
-n=`ls -1 $CACHEDIR/*cache-* | wc -l`
-if [ $n != 1 ]; then
-  echo "*** Test failed: $TEST"
-  echo "Unexpected cache was created"
-  ls $CACHEDIR
-  exit 1
-fi
-fi
-
 dotest "Keep mtime of the font directory"
 prep
 cp $FONT1 $FONTDIR
@@ -194,12 +149,6 @@ s!@CACHEDIR@!$TESTTMPDIR/cache.dir!" < $TESTDIR/fonts.conf.in > bind-fonts.conf
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/fc-match/fc-match$EXEEXT -f "%{file}\n" ":foundry=Misc" > xxx
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev --setenv FONTCONFIG_FILE $TESTTMPDIR/build/test/bind-fonts.conf $TESTTMPDIR/build/test/test-bz106618$EXEEXT | sort > flist1
 $BWRAP --bind / / --bind $CACHEDIR $TESTTMPDIR/cache.dir --bind $FONTDIR $TESTTMPDIR/fonts --bind .. $TESTTMPDIR/build --dev-bind /dev /dev find $TESTTMPDIR/fonts/ -type f -name '*.pcf' | sort > flist2
-ls -l $CACHEDIR > out2
-if cmp out1 out2 > /dev/null ; then : ; else
-  echo "*** Test failed: $TEST"
-  echo "cache was updated."
-  exit 1
-fi
 if [ x`cat xxx` != "x$TESTTMPDIR/fonts/4x6.pcf" ]; then
   echo "*** Test failed: $TEST"
   echo "file property doesn't point to the new place: $TESTTMPDIR/fonts/4x6.pcf"
@@ -225,18 +174,14 @@ mkdir -p $MyPWD/sysroot/$CACHEDIR
 cp $FONT1 $MyPWD/sysroot/$FONTDIR
 cp $MyPWD/fonts.conf $MyPWD/sysroot/$MyPWD/fonts.conf
 $FCCACHE -y $MyPWD/sysroot
-stat $MyPWD/sysroot/$FONTDIR/.uuid
-if test $? != 0; then
-  echo "*** Test failed: $TEST"
-  exit 1
-fi
 
-dotest "creating uuid-based cache file on sysroot"
-uuid=`cat $MyPWD/sysroot/$FONTDIR/.uuid`
-ls $MyPWD/sysroot/$CACHEDIR/$uuid*
+dotest "creating cache file on sysroot"
+md5=`echo -n $FONTDIR | md5sum | sed 's/ .*$//'`
+echo "checking for cache file $md5"
+ls "$MyPWD/sysroot/$CACHEDIR/$md5"*
 if [ $? != 0 ]; then
   echo "*** Test failed: $TEST"
-  echo "No cache for $uuid"
+  echo "No cache for $FONTDIR ($md5)"
   ls $MyPWD/sysroot/$CACHEDIR
   exit 1
 fi
@@ -245,19 +190,4 @@ rm -rf $MyPWD/sysroot
 
 fi
 
-# dotest "deleting .uuid file on empty dir"
-# prep
-# cp $FONT1 $FONT2 $FONTDIR
-# $FCCACHE $FONTDIR
-# sleep 1
-# rm -f $FONTDIR/*pcf
-# $FCCACHE $FONTDIR
-# rmdir $FONTDIR > /dev/null 2>&1
-# if [ $? != 0 ]; then
-#   echo "*** Test failed: $TEST"
-#   echo "$FONTDIR isn't empty"
-#   ls -al $FONTDIR
-#   exit 1
-# fi
-
 rm -rf $FONTDIR $CACHEFILE $CACHEDIR $FONTCONFIG_FILE out
diff --git a/test/test-hash.c b/test/test-hash.c
deleted file mode 100644
index 7220273..0000000
--- a/test/test-hash.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include "../src/fchash.c"
-#include "../src/fcstr.c"
-
-FcChar8 *
-FcLangNormalize (const FcChar8 *lang)
-{
-    return NULL;
-}
-
-FcChar8 *
-FcConfigHome (void)
-{
-    return NULL;
-}
-
-typedef struct _Test
-{
-    FcHashTable *table;
-} Test;
-
-static Test *
-init (void)
-{
-    Test *ret;
-
-    ret = malloc (sizeof (Test));
-    if (ret)
-    {
-	ret->table = FcHashTableCreate ((FcHashFunc) FcStrHashIgnoreCase,
-					(FcCompareFunc) FcStrCmp,
-					FcHashStrCopy,
-					FcHashUuidCopy,
-					(FcDestroyFunc) FcStrFree,
-					FcHashUuidFree);
-    }
-
-    return ret;
-}
-
-static void
-fini (Test *test)
-{
-    FcHashTableDestroy (test->table);
-    free (test);
-}
-
-static FcBool
-test_add (Test *test, char *key, FcBool replace)
-{
-    uuid_t uuid;
-    void *u;
-    FcBool (*hash_add) (FcHashTable *, void *, void *);
-    FcBool ret = FcFalse;
-
-    uuid_generate_random (uuid);
-    if (replace)
-	hash_add = FcHashTableReplace;
-    else
-	hash_add = FcHashTableAdd;
-    if (!hash_add (test->table, key, uuid))
-	return FcFalse;
-    if (!FcHashTableFind (test->table, key, &u))
-	return FcFalse;
-    ret = (uuid_compare (uuid, u) == 0);
-    FcHashUuidFree (u);
-
-    return ret;
-}
-
-static FcBool
-test_remove (Test *test, char *key)
-{
-    void *u;
-
-    if (!FcHashTableFind (test->table, key, &u))
-	return FcFalse;
-    FcHashUuidFree (u);
-    if (!FcHashTableRemove (test->table, key))
-	return FcFalse;
-    if (FcHashTableFind (test->table, key, &u))
-	return FcFalse;
-
-    return FcTrue;
-}
-
-int
-main (void)
-{
-    Test *test;
-    int ret = 0;
-
-    test = init ();
-    /* first op to add */
-    if (!test_add (test, "foo", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* second op to add */
-    if (!test_add (test, "bar", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* dup not allowed */
-    if (test_add (test, "foo", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* replacement */
-    if (!test_add (test, "foo", FcTrue))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* removal */
-    if (!test_remove (test, "foo"))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* not found to remove */
-    if (test_remove (test, "foo"))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* complex op in pointer */
-    if (!test_add (test, "foo", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    if (test_add (test, "foo", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    if (!test_remove (test, "foo"))
-    {
-	ret = 1;
-	goto bail;
-    }
-    if (!test_add (test, "foo", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    if (!test_remove (test, "bar"))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* completely remove */
-    if (!test_remove (test, "foo"))
-    {
-	ret = 1;
-	goto bail;
-    }
-    /* completely remove from the last one */
-    if (!test_add (test, "foo", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    if (!test_add (test, "bar", FcFalse))
-    {
-	ret = 1;
-	goto bail;
-    }
-    if (!test_remove (test, "bar"))
-    {
-	ret = 1;
-	goto bail;
-    }
-    if (!test_remove (test, "foo"))
-    {
-	ret = 1;
-	goto bail;
-    }
-bail:
-    fini (test);
-
-    return ret;
-}
commit a8c4fc5e1f2c4215544aff004d42f235d7e9d14f
Author: Keith Packard <keithp@xxxxxxxxxx>
Date:   Mon Oct 29 16:36:11 2018 -0700

    Add delays to test-bz106632, check UptoDate separately
    
    On a file system with one-second time stamps, extra delays are needed
    between cache modification operations to ensure that fontconfig isn't
    fooled.
    
    And, when the timestamps are checked correctly, we need to make sure
    that FcConfigUptoDate returns false whenever we change a font
    directory, so separate that out from the call to reinitialize the core
    config.
    
    Signed-off-by: Keith Packard <keithp@xxxxxxxxxx>

diff --git a/test/test-bz106632.c b/test/test-bz106632.c
index cf3bbcf..5db912b 100644
--- a/test/test-bz106632.c
+++ b/test/test-bz106632.c
@@ -191,7 +191,7 @@ main (void)
     mkdir_p ((const char *) cachedir);
 
     fprintf (stderr, "D: Copying %s to %s\n", FONTFILE, fontdir);
-    snprintf (cmd, 512, "cp -a %s %s", FONTFILE, fontdir);
+    snprintf (cmd, 512, "sleep 1; cp -a %s %s; sleep 1", FONTFILE, fontdir);
     (void) system (cmd);
 
     fprintf (stderr, "D: Loading a config\n");
@@ -220,15 +220,21 @@ main (void)
 	goto bail;
     }
     fprintf (stderr, "D: Removing %s\n", fontdir);
-    snprintf (cmd, 512, "rm -f %s%s*; sleep 1", fontdir, FC_DIR_SEPARATOR_S);
+    snprintf (cmd, 512, "sleep 1; rm -f %s%s*; sleep 1", fontdir, FC_DIR_SEPARATOR_S);
     (void) system (cmd);
     fprintf (stderr, "D: Reinitializing\n");
-    if (!FcConfigUptoDate (config) || !FcInitReinitialize ())
+    if (FcConfigUptoDate(config))
     {
-	fprintf (stderr, "E: Unable to reinitialize\n");
+	fprintf (stderr, "E: Config reports up-to-date\n");
 	ret = 2;
 	goto bail;
     }
+    if (!FcInitReinitialize ())
+    {
+	fprintf (stderr, "E: Unable to reinitialize\n");
+	ret = 3;
+	goto bail;
+    }
     if (FcConfigGetCurrent () == config)
     {
 	fprintf (stderr, "E: config wasn't reloaded\n");
@@ -259,10 +265,16 @@ main (void)
 	goto bail;
     }
     fprintf (stderr, "D: Copying %s to %s\n", FONTFILE, fontdir);
-    snprintf (cmd, 512, "cp -a %s %s; sleep 1", FONTFILE, fontdir);
+    snprintf (cmd, 512, "sleep 1; cp -a %s %s; sleep 1", FONTFILE, fontdir);
     (void) system (cmd);
     fprintf (stderr, "D: Reinitializing\n");
-    if (!FcConfigUptoDate (config) || !FcInitReinitialize ())
+    if (FcConfigUptoDate(config))
+    {
+	fprintf (stderr, "E: Config up-to-date after addition\n");
+	ret = 3;
+	goto bail;
+    }
+    if (!FcInitReinitialize ())
     {
 	fprintf (stderr, "E: Unable to reinitialize\n");
 	ret = 2;
commit 2a81aa51f08085c81666f40f34068f2c6512e974
Author: Keith Packard <keithp@xxxxxxxxxx>
Date:   Mon Oct 29 16:26:11 2018 -0700

    Remove '-u' option from run-test-conf.sh
    
    This causes a failure when evaluating $OSTYPE on systems which do not
    set that variable (everything but Msys/MinGW)
    
    Signed-off-by: Keith Packard <keithp@xxxxxxxxxx>

diff --git a/test/run-test-conf.sh b/test/run-test-conf.sh
index 80a5d6b..f9e0abd 100644
--- a/test/run-test-conf.sh
+++ b/test/run-test-conf.sh
@@ -21,7 +21,7 @@
 # DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
-set -eu
+set -e
 
 case "$OSTYPE" in
     msys ) MyPWD=`pwd -W` ;;  # On Msys/MinGW, returns a MS Windows style path.
commit 67e9c12c5a85e4ee95eb8576d094988d1c765c44
Author: Keith Packard <keithp@xxxxxxxxxx>
Date:   Mon Oct 29 17:00:28 2018 -0700

    Fetch FONTCONFIG_SYSROOT in FcConfigCreate
    
    This saves the value of FONTCONFIG_SYSROOT in the config instead of
    having to call getenv every time we need this value.
    
    This also uses 'realpath' to construct a canonical path to sysroot,
    eliminating symlinks and relative path names.
    
    Signed-off-by: Keith Packard <keithp@xxxxxxxxxx>

diff --git a/src/fccfg.c b/src/fccfg.c
index a87dfec..11df5ca 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -96,6 +96,20 @@ FcConfigFini (void)
 	FcConfigDestroy (cfg);
 }
 
+static FcChar8 *
+FcConfigRealPath(const FcChar8 *path)
+{
+    char	resolved_name[PATH_MAX+1];
+    char	*resolved_ret;
+
+    if (!path)
+	return NULL;
+
+    resolved_ret = realpath((const char *) path, resolved_name);
+    if (resolved_ret)
+	path = (FcChar8 *) resolved_ret;
+    return FcStrCopyFilename(path);
+}
 
 FcConfig *
 FcConfigCreate (void)
@@ -159,7 +173,7 @@ FcConfigCreate (void)
 
     config->expr_pool = NULL;
 
-    config->sysRoot = NULL;
+    config->sysRoot = FcConfigRealPath((const FcChar8 *) getenv("FONTCONFIG_SYSROOT"));
 
     config->rulesetList = FcPtrListCreate (FcDestroyAsRuleSet);
     if (!config->rulesetList)
@@ -2462,11 +2476,7 @@ FcConfigGetSysRoot (const FcConfig *config)
 	if (!config)
 	    return NULL;
     }
-
-    if (config->sysRoot)
-        return config->sysRoot;
-
-    return (FcChar8 *) getenv ("FONTCONFIG_SYSROOT");
+    return config->sysRoot;
 }
 
 void
@@ -2495,7 +2505,7 @@ FcConfigSetSysRoot (FcConfig      *config,
 
     if (sysroot)
     {
-	s = FcStrCopyFilename (sysroot);
+	s = FcConfigRealPath(sysroot);
 	if (!s)
 	    return;
     }
_______________________________________________
Fontconfig mailing list
Fontconfig@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/fontconfig




[Index of Archives]     [Fedora Fonts]     [Fedora Users]     [Fedora Cloud]     [Kernel]     [Fedora Packaging]     [Fedora Desktop]     [PAM]     [Gimp Graphics Editor]     [Yosemite News]

  Powered by Linux