public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/portage-utils:master commit in: /, man/include/
@ 2018-04-15 12:04 Fabian Groffen
  0 siblings, 0 replies; only message in thread
From: Fabian Groffen @ 2018-04-15 12:04 UTC (permalink / raw
  To: gentoo-commits

commit:     23c09a20dfcc044343b16bfe4b5873f663a46286
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Apr 15 12:03:14 2018 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sun Apr 15 12:03:14 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=23c09a20

qfile: fix matching of files

A bit overenthusiastic check for files in the current directory caused
weird directory prefixes to be ignored.

Bug: https://bugs.gentoo.org/652720

 man/include/qfile-01-owners.include |  9 ++--
 qfile.c                             | 94 ++++++++++++++++++++++---------------
 2 files changed, 60 insertions(+), 43 deletions(-)

diff --git a/man/include/qfile-01-owners.include b/man/include/qfile-01-owners.include
index c9ce378..a4bdc76 100644
--- a/man/include/qfile-01-owners.include
+++ b/man/include/qfile-01-owners.include
@@ -1,13 +1,14 @@
-.SH "FINDING FILES OWNERS"
+.SH "FINDING FILE OWNERS"
 .PP
 This is the default behavior of \fBqfile\fP.  It will list the packages which
 own the files (or directories, or symlinks, or anything else Portage can 
-install) you are querying.  Query items may be file paths or simple file names.
+install) you are querying.  Query items may be file paths or simple file
+names when the \fB\-b\fP option is used.
 By default, output includes packages names and the complete paths to
 the matching files.  If using \fB\-\-exact\fP, versions of the packages will 
 also be shown.  At the contrary, when using \fB\-\-quiet\fP, only package 
 names are listed, without files paths.  Finally, \fB\-\-verbose\fP is similar
-to \fB\-\-exact\fP, but may adds a few warnings.  The return status of 
+to \fB\-\-exact\fP, but may add a few warnings.  The return status of 
 \fBqfile\fP will be \fI0\fP as soon as an owning package has been found for 
 one of the query items.
 .PP
@@ -19,7 +20,7 @@ Find names of package(s) owning "/bin/bash":
 .PP
 Find package(s) owning any file named "bash", and show paths of this files:
 .nf\fI
-	$ qfile bash
+	$ qfile -b bash
 	app-shells/bash (/bin/bash)
 	app-shells/bash (/etc/bash)
 .fi

diff --git a/qfile.c b/qfile.c
index 08ba642..285277b 100644
--- a/qfile.c
+++ b/qfile.c
@@ -118,66 +118,73 @@ static int qfile_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
 		goto qlist_done;
 
 	while (getline(&state->buf, &state->buflen, fp) != -1) {
+		size_t dirname_len;
 		contents_entry *e;
+
 		e = contents_parse_line(state->buf);
 		if (!e)
 			continue;
 
-		/* assume sane basename() -- doesnt modify argument */
-		if ((base = basename(e->name)) == NULL)
+		/* basename(3) possibly modifies e->name (if it has trailing
+		 * slashes) but this is not likely since it comes from VDB which
+		 * has normalised everything, so effectively e->name isn't
+		 * touched, however, it /can/ return a pointer to a private
+		 * allocation */
+		base = basename(e->name);
+		if (base < e->name || base > (e->name + strlen(e->name)))
 			continue;
 
+		/* basename(/usr)     = usr, dirname(/usr)     = /
+		 * basename(/usr/bin) = bin, dirname(/usr/bin) = /usr */
+		if ((dirname_len = (base - e->name - 1)) == 0)
+			dirname_len = 1;
+
 		for (i = 0; i < args->length; i++) {
 			if (base_names[i] == NULL)
 				continue;
 			if (non_orphans && non_orphans[i])
 				continue;
 
-			/* For optimization of qfile(), we also give it an array of the first char
-			 * of each basename.  This way we avoid numerous strcmp() calls.
-			*/
-			if (base[0] != base_names[i][0] || strcmp(base, base_names[i]))
+			/* For optimization of qfile(), we also give it an array of
+			 * the first char of each basename.  This way we avoid
+			 * numerous strcmp() calls. */
+			if (base[0] != base_names[i][0] || strcmp(base, base_names[i]) != 0)
 				continue;
 
 			path_ok = false;
 
-			/* check the full filepath ... */
-			size_t dirname_len = (base - e->name - 1);
-			/* basename(/usr)     = usr, dirname(/usr)     = /
-			 * basename(/usr/bin) = bin, dirname(/usr/bin) = /usr
-			 */
-			if (dirname_len == 0)
-				dirname_len = 1;
-
 			if (dir_names[i] &&
 			    strncmp(e->name, dir_names[i], dirname_len) == 0 &&
-			    dir_names[i][dirname_len] == '\0') {
+				dir_names[i][dirname_len] == '\0')
+			{
 				/* dir_name == dirname(CONTENTS) */
 				path_ok = true;
-
 			} else if (real_dir_names[i] &&
-			         strncmp(e->name, real_dir_names[i], dirname_len) == 0 &&
-			         real_dir_names[i][dirname_len] == '\0') {
+					strncmp(e->name, real_dir_names[i], dirname_len) == 0 &&
+					real_dir_names[i][dirname_len] == '\0')
+			{
 				/* real_dir_name == dirname(CONTENTS) */
 				path_ok = true;
-
 			} else if (real_root[0]) {
-				char rpath[_Q_PATH_MAX + 1], *_rpath;
-				char *fullpath;
+				char rpath[_Q_PATH_MAX + 1];
+				char *_rpath;
+				char fullpath[_Q_PATH_MAX + 1];
 				size_t real_root_len = state->real_root_len;
 
-				xasprintf(&fullpath, "%s%s", real_root, e->name);
-				fullpath[real_root_len + dirname_len] = '\0';
+				snprintf(fullpath, sizeof(fullpath), "%s%s",
+						real_root, e->name);
 				_rpath = rpath + real_root_len;
 				if (realpath(fullpath, rpath) == NULL) {
 					if (verbose) {
-						warnp("Could not read real path of \"%s\" (from %s)", fullpath, pkg);
-						warn("We'll never know whether \"%s\" was a result for your query...",
-								e->name);
+						warnp("Could not read real path of \"%s\" (from %s)",
+								fullpath, pkg);
+						warn("We'll never know whether \"%s\" was a result "
+								"for your query...", e->name);
 					}
 				} else if (!qfile_is_prefix(rpath, real_root, real_root_len)) {
 					if (verbose)
-						warn("Real path of \"%s\" is not under ROOT: %s", fullpath, rpath);
+						warn("Real path of \"%s\" is not under ROOT: %s",
+								fullpath, rpath);
 				} else if (dir_names[i] &&
 				           strcmp(_rpath, dir_names[i]) == 0) {
 					/* dir_name == realpath(dirname(CONTENTS)) */
@@ -187,11 +194,12 @@ static int qfile_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
 					/* real_dir_name == realpath(dirname(CONTENTS)) */
 					path_ok = true;
 				}
-				free(fullpath);
 			} else if (state->basename) {
 				path_ok = true;
-			} else if (state->pwd) {
-				if (!strncmp(e->name, state->pwd, dirname_len))
+			} else if (state->pwd && dir_names[i] == NULL) {
+				/* try to match file in current directory */
+				if (strncmp(e->name, state->pwd, dirname_len) == 0 &&
+						state->pwd[dirname_len] == '\0')
 					path_ok = true;
 			}
 			if (!path_ok)
@@ -222,7 +230,6 @@ static int qfile_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
 					puts("");
 				else
 					printf(" (%s%s)\n", state->root ? : "", e->name);
-
 			} else {
 				non_orphans[i] = 1;
 			}
@@ -285,7 +292,8 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
 
 	for (i = 0; i < argc; ++i) {
 		/* Record basename, but if it is ".", ".." or "/" */
-		strncpy(abspath, argv[i], _Q_PATH_MAX); /* strncopy so that "argv" can be "const" */
+		/* strncopy so that "argv" can be "const" */
+		strncpy(abspath, argv[i], _Q_PATH_MAX);
 		strncpy(tmppath, basename(abspath), _Q_PATH_MAX);
 		if ((strlen(tmppath) > 2) ||
 		    (strncmp(tmppath, "..", strlen(tmppath))
@@ -299,7 +307,8 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
 				continue;
 		}
 
-		/* Make sure we have an absolute path available (with "realpath(ROOT)" prefix) */
+		/* Make sure we have an absolute path available (with
+		 * "realpath(ROOT)" prefix) */
 		if (argv[i][0] == '/') {
 			if (state->assume_root_prefix)
 				strncpy(abspath, argv[i], _Q_PATH_MAX);
@@ -309,9 +318,11 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
 			if (state->assume_root_prefix)
 				snprintf(abspath, _Q_PATH_MAX, "%s/%s", pwd, argv[i]);
 			else
-				snprintf(abspath, _Q_PATH_MAX, "%s%s/%s", real_root, pwd, argv[i]);
+				snprintf(abspath, _Q_PATH_MAX, "%s%s/%s",
+						real_root, pwd, argv[i]);
 		} else {
-			warn("$PWD was not found in environment, or is not an absolute path");
+			warn("$PWD was not found in environment, "
+					"or is not an absolute path");
 			goto skip_query_item;
 		}
 
@@ -328,12 +339,14 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
 			if (realpath(abspath, tmppath) == NULL) {
 				if (verbose) {
 					warnp("Could not read real path of \"%s\"", abspath);
-					warn("Results for query item \"%s\" may be inaccurate.", argv[i]);
+					warn("Results for query item \"%s\" may be inaccurate.",
+							argv[i]);
 				}
 				continue;
 			}
 			if (!qfile_is_prefix(tmppath, real_root, real_root_len)) {
-				warn("Real path of \"%s\" is not under ROOT: %s", abspath, tmppath);
+				warn("Real path of \"%s\" is not under ROOT: %s",
+						abspath, tmppath);
 				goto skip_query_item;
 			}
 			if (tmppath[real_root_len] == '\0')
@@ -350,7 +363,8 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st
 				goto skip_query_item;
 			}
 			if (!qfile_is_prefix(tmppath, real_root, real_root_len)) {
-				warn("Real path of \"%s\" is not under ROOT: %s", abspath, tmppath);
+				warn("Real path of \"%s\" is not under ROOT: %s",
+						abspath, tmppath);
 				goto skip_query_item;
 			}
 			strncpy(abspath, tmppath, _Q_PATH_MAX);
@@ -470,7 +484,9 @@ int qfile_main(int argc, char **argv)
 			if (state.args.non_orphans[i])
 				continue;
 			if (state.args.basenames[i]) {
-				found = 0; /* ~inverse return code (as soon as an orphan is found, return non-zero) */
+				/* inverse return code (as soon as an orphan is found,
+				 * return non-zero) */
+				found = 0;
 				if (!quiet)
 					puts(argv[i]);
 				else


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2018-04-15 12:04 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-15 12:04 [gentoo-commits] proj/portage-utils:master commit in: /, man/include/ Fabian Groffen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox