From: Andrew Gregory <andrew.gregory.8@gmail.com> --- I did this as a patch against your working branch since it requires changes outside the scope of your original patch. This adds a check that all files/directories are within root before we bother looking for an owner which removes the need for a special check just for '/'. I didn't test this extensively, but it handled `./pacman -Qo / firefox /usr/bin/firefox /tmp /tmp/` correctly. src/pacman/query.c | 51 +++++++++++++++++++++++++++------------------------ src/pacman/util.c | 4 ++++ 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/pacman/query.c b/src/pacman/query.c index 67dd11c..d99d5df 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -109,7 +109,7 @@ static int query_fileowner(alpm_list_t *targets) { int ret = 0; char path[PATH_MAX]; - const char *root; + char *root; size_t rootlen; alpm_list_t *t; alpm_db_t *db_local; @@ -124,9 +124,15 @@ static int query_fileowner(alpm_list_t *targets) /* Set up our root path buffer. We only need to copy the location of root in * once, then we can just overwrite whatever file was there on the previous * iteration. */ - root = alpm_option_get_root(config->handle); + /* I don't know if we can assume that root doesn't contain symlinks, + * if not we should go ahead and resolve it */ + root = strdup(resolve_path(alpm_option_get_root(config->handle))); rootlen = strlen(root); - if(rootlen + 1 > PATH_MAX) { + if(root[rootlen - 1] != '/' && rootlen + 1 < PATH_MAX){ + strcat(root, "/"); + rootlen++; + } + if(rootlen + 1 > PATH_MAX || root[rootlen - 1] != '/') { /* we are in trouble here */ pm_printf(ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, ""); return 1; @@ -177,32 +183,28 @@ static int query_fileowner(alpm_list_t *targets) bname_len = strlen(bname); dname = mdirname(filename); - /* for files in '/', there is no directory name to match */ - if(strcmp(dname, "") == 0) { - rpath = NULL; - } else { - rpath = resolve_path(dname); + rpath = resolve_path(dname); - if(!rpath) { - pm_printf(ALPM_LOG_ERROR, _("cannot determine real path for '%s': %s\n"), - filename, strerror(errno)); - free(dname); - ret++; - goto cleanup; - } + if(!rpath) { + pm_printf(ALPM_LOG_ERROR, _("cannot determine real path for '%s': %s\n"), + dname, strerror(errno)); + free(dname); + ret++; + goto cleanup; } free(dname); + if(strstr(root, rpath) && *bname == '\0') { + /* path is either outside root or *is* root */ + pm_printf(ALPM_LOG_ERROR, _("cannot determine ownership of file outside root directory\n")); + ret++; + goto cleanup; + } + if(isdir) { - if(!rpath) { - pm_printf(ALPM_LOG_ERROR, _("cannot determine ownership of root directory\n")); - ret++; - goto cleanup; - } else { - rpath_len = strlen(rpath); - rpath_bname = mbasename(rpath); - rpath_bname_len = strlen(rpath_bname); - } + rpath_len = strlen(rpath); + rpath_bname = mbasename(rpath); + rpath_bname_len = strlen(rpath_bname); } for(i = packages; i && (!found || isdir); i = alpm_list_next(i)) { @@ -276,6 +278,7 @@ cleanup: free(filename); free(rpath); } + free(root); return ret; } diff --git a/src/pacman/util.c b/src/pacman/util.c index 7f7f6a7..1914b70 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -242,6 +242,10 @@ char *mdirname(const char *path) ret = strdup(path); last = strrchr(ret, '/'); + if(last == ret){ + free(ret); + return strdup("/"); + } if(last != NULL) { /* we found a '/', so terminate our string */ *last = '\0'; -- 1.7.10.2