.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><dir></literal>, <literal><cachedir></literal>, <literal><include></literal>, <literal><match></literal> and <literal><alias></literal> elements in any order. </para></refsect2> - <refsect2><title><literal><dir prefix="default"></literal></title><para> + <refsect2><title><literal><dir prefix="default" salt=""></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><cachedir prefix="default"></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><int></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><remap-dir prefix="default" as-path=""<</literal></title><para> + <refsect2><title><literal><remap-dir prefix="default" as-path="" salt=""<</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><dir></literal> element. </para></refsect2> <refsect2><title><literal><reset-dirs /></literal></title><para> This element removes all of fonts directories where added by <literal><dir></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><reset-dirs /></literal></title><para> +This element removes all of fonts directories where added by <literal><dir></literal> elements. +This is useful to override fonts directories from system to own fonts directories only. + </para></refsect2> <refsect2><title><literal><rescan></literal></title><para> The <literal><rescan></literal> element holds an <literal><int></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><dir></literal>, <literal><cachedir></literal>, <literal><include></literal>, <literal><match></literal> and <literal><alias></literal> elements in any order. </para></refsect2> - <refsect2><title><literal><dir prefix="default" map=""></literal></title><para> + <refsect2><title><literal><dir prefix="default"></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><cachedir prefix="default"></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><int></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><remap-dir prefix="default" as-path=""<</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><rescan></literal></title><para> The <literal><rescan></literal> element holds an <literal><int></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><dir></literal>, <literal><cachedir></literal>, <literal><include></literal>, <literal><match></literal> and <literal><alias></literal> elements in any order. </para></refsect2> - <refsect2><title><literal><dir prefix="default"></literal></title><para> + <refsect2><title><literal><dir prefix="default" map=""></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><cachedir prefix="default"></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