Commit d1f48f11 authored by Tom Anderson's avatar Tom Anderson Committed by Behdad Esfahbod

Return canonicalized paths from FcConfigRealFilename

FcConfigRealFilename() follows symlinks, but the link may be relative to the
directory containing the link.  For example, on my system, I have this file:

/etc/fonts/conf.d/99-language-selector-zh.conf ->
    ../conf.avail/99-language-selector-zh.conf

Since /etc/fonts/conf.d is probably not in PATH, open()ing the file would fail.
This change makes FcConfigRealFilename() return the canonicalized filename
instead.  So for the example above, it would return:

/etc/fonts/conf.avail/99-language-selector-zh.conf

This was causing bad font rendering in Chromium [1] after the regression I
introduced in 7ad010e8.

[1] https://bugs.chromium.org/p/chromium/issues/detail?id=857511
parent 48e9e5f4
......@@ -2191,42 +2191,28 @@ FcConfigFilename (const FcChar8 *url)
}
file = 0;
#ifdef _WIN32
if (isalpha (*url) &&
url[1] == ':' &&
(url[2] == '/' || url[2] == '\\'))
goto absolute_path;
#endif
if (FcStrIsAbsoluteFilename(url))
return FcConfigFileExists (0, url);
switch (*url) {
case '~':
if (*url == '~')
{
dir = FcConfigHome ();
if (dir)
file = FcConfigFileExists (dir, url + 1);
else
file = 0;
break;
#ifdef _WIN32
case '\\':
absolute_path:
#endif
case '/':
file = FcConfigFileExists (0, url);
break;
default:
path = FcConfigGetPath ();
if (!path)
return NULL;
for (p = path; *p; p++)
{
file = FcConfigFileExists (*p, url);
if (file)
break;
}
FcConfigFreePath (path);
break;
}
path = FcConfigGetPath ();
if (!path)
return NULL;
for (p = path; *p; p++)
{
file = FcConfigFileExists (*p, url);
if (file)
break;
}
FcConfigFreePath (path);
return file;
}
......@@ -2252,8 +2238,27 @@ FcConfigRealFilename (FcConfig *config,
if ((len = FcReadLink (nn, buf, sizeof (buf) - 1)) != -1)
{
buf[len] = 0;
FcStrFree (nn);
nn = FcStrdup (buf);
if (!FcStrIsAbsoluteFilename (buf))
{
FcChar8 *dirname = FcStrDirname (nn);
FcStrFree (nn);
if (!dirname)
return NULL;
FcChar8 *path = FcStrBuildFilename (dirname, buf, NULL);
FcStrFree (dirname);
if (!path)
return NULL;
nn = FcStrCanonFilename (path);
FcStrFree (path);
}
else
{
FcStrFree (nn);
nn = FcStrdup (buf);
}
}
}
......
......@@ -1279,6 +1279,9 @@ FcStrGlobMatch (const FcChar8 *glob,
FcPrivate FcBool
FcStrUsesHome (const FcChar8 *s);
FcPrivate FcBool
FcStrIsAbsoluteFilename (const FcChar8 *s);
FcPrivate FcChar8 *
FcStrBuildFilename (const FcChar8 *path,
...);
......
......@@ -867,6 +867,17 @@ FcStrUsesHome (const FcChar8 *s)
return *s == '~';
}
FcBool
FcStrIsAbsoluteFilename (const FcChar8 *s)
{
#ifdef _WIN32
if (*s == '\\' ||
(isalpha (*s) && s[1] == ':' && (s[2] == '/' || s[2] == '\\'))
return FcTrue;
#endif
return *s == '/';
}
FcChar8 *
FcStrBuildFilename (const FcChar8 *path,
...)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment