forked from ariadne/pkgconf
Rework path handling on native Windows
The current approach was to parse the .pc and, detect the prefix, throw everything together and at the end replace all \ with / to not produce invalid escape sequences. This has the problem that escaping in .pc files is ignored and no longer possible. Also in case the prefix path has a space in it the result would be invalid because of missing escaping. This changes the following things: * We no longer normalize values at the end. Instead we assume .pc files use "/" as a directory separator or "\\", same format as under Unix. "\" alone no longer works. This shouldn't be a problem since most build tools produce .pc files with "/" like meson, cmake, autotools. * When injecting the prefix at runtime we convert the prefix to use "/" and escape spaces so that in combination with the .pc content the result is a valid escaped path value again. This patch has been used in MSYS2 for some months now. See #212master
parent
4be39c59fb
commit
4f73f6a1d6
|
@ -331,18 +331,5 @@ pkgconf_path_relocate(char *buf, size_t buflen)
|
||||||
free(tmpbuf);
|
free(tmpbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
/*
|
|
||||||
* Rewrite any backslash path delimiters for best compatibility.
|
|
||||||
* Originally, we did this in cygwin/msys case, but now we build pkgconf
|
|
||||||
* natively on Windows without cygwin/msys, so do it in all cases.
|
|
||||||
*/
|
|
||||||
for (ti = buf; *ti != '\0'; ti++)
|
|
||||||
{
|
|
||||||
if (*ti == '\\')
|
|
||||||
*ti = '/';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,37 @@ determine_prefix(const pkgconf_pkg_t *pkg, char *buf, size_t buflen)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Takes a real path and converts it to a pkgconf value. This means normalizing
|
||||||
|
* directory separators and escaping things (only spaces covered atm).
|
||||||
|
*
|
||||||
|
* This is useful for things like prefix/pcfiledir which might get injected
|
||||||
|
* at runtime and are not sourced from the .pc file.
|
||||||
|
*
|
||||||
|
* "C:\foo bar\baz" -> "C:/foo\ bar/baz"
|
||||||
|
* "/foo bar/baz" -> "/foo\ bar/baz"
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
convert_path_to_value(const char *path)
|
||||||
|
{
|
||||||
|
char *buf = calloc((strlen(path) + 1) * 2, 1);
|
||||||
|
char *bptr = buf;
|
||||||
|
const char *i;
|
||||||
|
|
||||||
|
for (i = path; *i != '\0'; i++)
|
||||||
|
{
|
||||||
|
if (*i == PKG_DIR_SEP_S)
|
||||||
|
*bptr++ = '/';
|
||||||
|
else if (*i == ' ') {
|
||||||
|
*bptr++ = '\\';
|
||||||
|
*bptr++ = *i;
|
||||||
|
} else
|
||||||
|
*bptr++ = *i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_additional_separators(char *buf)
|
remove_additional_separators(char *buf)
|
||||||
{
|
{
|
||||||
|
@ -238,16 +269,6 @@ remove_additional_separators(char *buf)
|
||||||
static void
|
static void
|
||||||
canonicalize_path(char *buf)
|
canonicalize_path(char *buf)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
char *p = buf;
|
|
||||||
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '\\')
|
|
||||||
*p = '/';
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
remove_additional_separators(buf);
|
remove_additional_separators(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,8 +315,10 @@ pkgconf_pkg_parser_value_set(void *opaque, const size_t lineno, const char *keyw
|
||||||
|
|
||||||
if (relvalue != NULL)
|
if (relvalue != NULL)
|
||||||
{
|
{
|
||||||
|
char *prefix_value = convert_path_to_value(relvalue);
|
||||||
pkg->orig_prefix = pkgconf_tuple_add(pkg->owner, &pkg->vars, "orig_prefix", canonicalized_value, true);
|
pkg->orig_prefix = pkgconf_tuple_add(pkg->owner, &pkg->vars, "orig_prefix", canonicalized_value, true);
|
||||||
pkg->prefix = pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, relvalue, false);
|
pkg->prefix = pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, prefix_value, false);
|
||||||
|
free(prefix_value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, value, true);
|
pkgconf_tuple_add(pkg->owner, &pkg->vars, keyword, value, true);
|
||||||
|
@ -376,7 +399,10 @@ pkgconf_pkg_new_from_file(pkgconf_client_t *client, const char *filename, FILE *
|
||||||
pkg->owner = client;
|
pkg->owner = client;
|
||||||
pkg->filename = strdup(filename);
|
pkg->filename = strdup(filename);
|
||||||
pkg->pc_filedir = pkg_get_parent_dir(pkg);
|
pkg->pc_filedir = pkg_get_parent_dir(pkg);
|
||||||
pkgconf_tuple_add(client, &pkg->vars, "pcfiledir", pkg->pc_filedir, true);
|
|
||||||
|
char *pc_filedir_value = convert_path_to_value(pkg->pc_filedir);
|
||||||
|
pkgconf_tuple_add(client, &pkg->vars, "pcfiledir", pc_filedir_value, true);
|
||||||
|
free(pc_filedir_value);
|
||||||
|
|
||||||
/* make module id */
|
/* make module id */
|
||||||
if ((idptr = strrchr(pkg->filename, PKG_DIR_SEP_S)) != NULL)
|
if ((idptr = strrchr(pkg->filename, PKG_DIR_SEP_S)) != NULL)
|
||||||
|
|
Loading…
Reference in New Issue