From: Andrew Gregory <[email protected]>

---

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


Reply via email to