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.
This commit is contained in:
Akira TAGOH 2019-01-31 10:17:47 +00:00
parent def1d00036
commit 2e8ce63514
6 changed files with 129 additions and 22 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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