path: add pkgconf_path_prepend API for --with-path

Otherwise, PKG_CONFIG_PATH and PKG_CONFIG_LIBDIR elements would be processed backwards.

Fixes: 384ade5 (path: prepend paths rather than append paths when processing --with-path arguments)
Closes: #250
Signed-off-by: Ariadne Conill <ariadne@dereferenced.org>
Ariadne Conill 2023-10-08 22:27:56 +00:00
parent a6fb59a0ed
commit 652aff9790
3 changed files with 69 additions and 36 deletions

View File

@ -967,7 +967,7 @@ main(int argc, char *argv[])
logfile_arg = pkg_optarg;
break;
case 42:
pkgconf_path_add(pkg_optarg, &dir_list, true);
pkgconf_path_prepend(pkg_optarg, &dir_list, true);
break;
case 43:
pkgconf_client_set_prefix_varname(&pkg_client, pkg_optarg);

View File

@ -411,6 +411,7 @@ PKGCONF_API void pkgconf_audit_log_dependency(pkgconf_client_t *client, const pk
/* path.c */
PKGCONF_API void pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API void pkgconf_path_prepend(const char *text, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API size_t pkgconf_path_split(const char *text, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API size_t pkgconf_path_build_from_environ(const char *envvarname, const char *fallback, pkgconf_list_t *dirlist, bool filter);
PKGCONF_API bool pkgconf_path_match_list(const char *path, const pkgconf_list_t *dirlist);

View File

@ -58,6 +58,51 @@ path_list_contains_entry(const char *text, pkgconf_list_t *dirlist)
* variables.
*/
static pkgconf_path_t *
prepare_path_node(const char *text, pkgconf_list_t *dirlist, bool filter)
{
pkgconf_path_t *node;
char path[PKGCONF_ITEM_SIZE];
pkgconf_strlcpy(path, text, sizeof path);
pkgconf_path_relocate(path, sizeof path);
#ifdef PKGCONF_CACHE_INODES
struct stat st;
if (filter)
{
if (lstat(path, &st) == -1)
return NULL;
if (S_ISLNK(st.st_mode))
{
char pathbuf[PKGCONF_ITEM_SIZE * 4];
char *linkdest = realpath(path, pathbuf);
if (linkdest != NULL && stat(linkdest, &st) == -1)
return NULL;
}
if (path_list_contains_entry(path, dirlist, &st))
return NULL;
}
#else
if (filter && path_list_contains_entry(path, dirlist))
return NULL;
#endif
node = calloc(sizeof(pkgconf_path_t), 1);
node->path = strdup(path);
#ifdef PKGCONF_CACHE_INODES
if (filter) {
node->handle_path = (void *)(intptr_t) st.st_ino;
node->handle_device = (void *)(intptr_t) st.st_dev;
}
#endif
return node;
}
/*
* !doc
*
@ -73,44 +118,31 @@ path_list_contains_entry(const char *text, pkgconf_list_t *dirlist)
void
pkgconf_path_add(const char *text, pkgconf_list_t *dirlist, bool filter)
{
pkgconf_path_t *node;
char path[PKGCONF_ITEM_SIZE];
pkgconf_strlcpy(path, text, sizeof path);
pkgconf_path_relocate(path, sizeof path);
#ifdef PKGCONF_CACHE_INODES
struct stat st;
if (filter)
{
if (lstat(path, &st) == -1)
pkgconf_path_t *node = prepare_path_node(text, dirlist, filter);
if (node == NULL)
return;
if (S_ISLNK(st.st_mode))
{
char pathbuf[PKGCONF_ITEM_SIZE * 4];
char *linkdest = realpath(path, pathbuf);
if (linkdest != NULL && stat(linkdest, &st) == -1)
return;
}
if (path_list_contains_entry(path, dirlist, &st))
return;
}
#else
if (filter && path_list_contains_entry(path, dirlist))
return;
#endif
pkgconf_node_insert_tail(&node->lnode, node, dirlist);
}
node = calloc(sizeof(pkgconf_path_t), 1);
node->path = strdup(path);
#ifdef PKGCONF_CACHE_INODES
if (filter) {
node->handle_path = (void *)(intptr_t) st.st_ino;
node->handle_device = (void *)(intptr_t) st.st_dev;
}
#endif
/*
* !doc
*
* .. c:function:: void pkgconf_path_prepend(const char *text, pkgconf_list_t *dirlist)
*
* Prepends a path node to a path list. If the path is already in the list, do nothing.
*
* :param char* text: The path text to add as a path node.
* :param pkgconf_list_t* dirlist: The path list to add the path node to.
* :param bool filter: Whether to perform duplicate filtering.
* :return: nothing
*/
void
pkgconf_path_prepend(const char *text, pkgconf_list_t *dirlist, bool filter)
{
pkgconf_path_t *node = prepare_path_node(text, dirlist, filter);
if (node == NULL)
return;
pkgconf_node_insert(&node->lnode, node, dirlist);
}