Resolves symlinks against <dir prefix="relative">

When a config file is symlinked and obtaining an relative path from it for <dir>,
it behaved like:

$ realpath /path/to/foo.conf
/path/to/realpath/foo.conf
$ FONTCONFIG_FILE=/path/to/foo.conf fc-cache -v
Font directories:
        /path/to/fonts
/path/to/fonts: skipping, existing cache is valid: 1 fonts, 0 dirs
/path/to/cachedir: cleaning cache directory
fc-cache: succeeded

And after this change:

$ FONTCONFIG_FILE=/path/to/foo.conf fc-cache -v
Font directories:
        /path/to/relpath/fonts
/path/to/realpath/fonts: skipping, existing cache is valid: 1 fonts, 0 dirs
/path/to/cachedir: cleaning cache directory
fc-cache: succeeded

Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/290
This commit is contained in:
Akira TAGOH 2021-10-11 18:35:58 +09:00
parent 2d17232a45
commit 1d76699927
4 changed files with 38 additions and 28 deletions

View File

@ -131,30 +131,6 @@ FcConfigFini (void)
free_lock (); free_lock ();
} }
static FcChar8 *
FcConfigRealPath(const FcChar8 *path)
{
char resolved_name[FC_PATH_MAX+1];
char *resolved_ret;
if (!path)
return NULL;
#ifndef _WIN32
resolved_ret = realpath((const char *) path, resolved_name);
#else
if (GetFullPathNameA ((LPCSTR) path, FC_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);
}
FcConfig * FcConfig *
FcConfigCreate (void) FcConfigCreate (void)
{ {
@ -221,7 +197,7 @@ FcConfigCreate (void)
config->expr_pool = NULL; config->expr_pool = NULL;
config->sysRoot = FcConfigRealPath((const FcChar8 *) getenv("FONTCONFIG_SYSROOT")); config->sysRoot = FcStrRealPath ((const FcChar8 *) getenv("FONTCONFIG_SYSROOT"));
config->rulesetList = FcPtrListCreate (FcDestroyAsRuleSet); config->rulesetList = FcPtrListCreate (FcDestroyAsRuleSet);
if (!config->rulesetList) if (!config->rulesetList)
@ -3048,7 +3024,7 @@ retry:
if (sysroot) if (sysroot)
{ {
s = FcConfigRealPath(sysroot); s = FcStrRealPath (sysroot);
if (!s) if (!s)
return; return;
} }

View File

@ -1345,6 +1345,9 @@ FcStrHashIgnoreCase (const FcChar8 *s);
FcPrivate FcChar32 FcPrivate FcChar32
FcStrHashIgnoreBlanksAndCase (const FcChar8 *s); FcStrHashIgnoreBlanksAndCase (const FcChar8 *s);
FcPrivate FcChar8 *
FcStrRealPath (const FcChar8 *path);
FcPrivate FcChar8 * FcPrivate FcChar8 *
FcStrCanonFilename (const FcChar8 *s); FcStrCanonFilename (const FcChar8 *s);

View File

@ -1091,6 +1091,30 @@ FcStrBasename (const FcChar8 *file)
return FcStrCopy (slash + 1); return FcStrCopy (slash + 1);
} }
FcChar8 *
FcStrRealPath (const FcChar8 *path)
{
char resolved_name[FC_PATH_MAX+1];
char *resolved_ret;
if (!path)
return NULL;
#ifndef _WIN32
resolved_ret = realpath((const char *) path, resolved_name);
#else
if (GetFullPathNameA ((LPCSTR) path, FC_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);
}
static FcChar8 * static FcChar8 *
FcStrCanonAbsoluteFilename (const FcChar8 *s) FcStrCanonAbsoluteFilename (const FcChar8 *s)
{ {

View File

@ -1318,9 +1318,16 @@ _get_real_paths_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcC
} }
else if (FcStrCmp (prefix, (const FcChar8 *) "relative") == 0) else if (FcStrCmp (prefix, (const FcChar8 *) "relative") == 0)
{ {
parent = FcStrDirname (parse->name); FcChar8 *p = FcStrRealPath (parse->name);
if (!parent)
if (!p)
return NULL; return NULL;
parent = FcStrDirname (p);
if (!parent)
{
free (p);
return NULL;
}
} }
} }
#ifndef _WIN32 #ifndef _WIN32