[pacman-dev] [PATCH v3] Allow querying directory ownership

Andrew Gregory andrew.gregory.8 at gmail.com
Tue May 22 11:22:21 EDT 2012


From: Andrew Gregory <andrew.gregory.8 at 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



More information about the pacman-dev mailing list