[pacman-dev] [PATCH] Allow -Qo to perform a functional 'which'
Allan McRae
allan at archlinux.org
Sat Mar 6 22:02:37 EST 2010
When pacman queries the ownership of an object that is not a path,
it will check in the users PATH for a match. Implements FS#8798.
Original-patch-by: Shankar <jatheendra at gmail.com>
Signed-off-by: Allan McRae <allan at archlinux.org>
---
This should address all comments I had when this was submitted a
few months back.
src/pacman/query.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/src/pacman/query.c b/src/pacman/query.c
index 6b6a25d..038072f 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -56,10 +56,44 @@ static char *resolve_path(const char* file)
return(str);
}
+/* check if filename exists in PATH */
+static int search_path(char *filename, size_t size, struct stat * bufptr)
+{
+ char *envpath, *envpathsplit, *path, fullname[PATH_MAX+1];
+ int len;
+
+ if ((envpath = getenv("PATH")) == NULL) {
+ return(-1);
+ }
+ if ((envpath = envpathsplit = strdup(envpath)) == NULL) {
+ return(-1);
+ }
+
+ while ((path = strsep(&envpathsplit, ":")) != NULL) {
+ len = strlen(path);
+
+ /* strip the trailing slash if one exists */
+ while(path[len - 1] == '/') {
+ path[--len] = '\0';
+ }
+
+ snprintf(fullname, sizeof(fullname), "%s/%s", path, filename);
+
+ if(stat(fullname, bufptr) == 0) {
+ strncpy(filename, fullname, size);
+ free(envpath);
+ return(0);
+ }
+ }
+ free(envpath);
+ return(-1);
+}
+
static int query_fileowner(alpm_list_t *targets)
{
int ret = 0;
alpm_list_t *t;
+ size_t len=PATH_MAX+1;
/* This code is here for safety only */
if(targets == NULL) {
@@ -67,19 +101,31 @@ static int query_fileowner(alpm_list_t *targets)
return(1);
}
+ char *filename = calloc(len, sizeof(char));
+
for(t = targets; t; t = alpm_list_next(t)) {
int found = 0;
- char *filename = alpm_list_getdata(t);
+ strncpy(filename, alpm_list_getdata(t), len);
char *bname, *dname, *rpath;
const char *root;
struct stat buf;
alpm_list_t *i, *j;
if(lstat(filename, &buf) == -1) {
- pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"),
- filename, strerror(errno));
- ret++;
- continue;
+ /* if it is not a path but a program name, then check in PATH */
+ if(strchr(filename, '/') == NULL) {
+ if(search_path(filename, len, &buf) == -1) {
+ pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"),
+ filename, strerror(errno));
+ ret++;
+ continue;
+ }
+ } else {
+ pm_fprintf(stderr, PM_LOG_ERROR, _("failed to read file '%s': %s\n"),
+ filename, strerror(errno));
+ ret++;
+ continue;
+ }
}
if(S_ISDIR(buf.st_mode)) {
@@ -140,6 +186,7 @@ static int query_fileowner(alpm_list_t *targets)
free(rpath);
}
+ free(filename);
return ret;
}
--
1.7.0.1
More information about the pacman-dev
mailing list