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

commit:     81df4a8cfbd2998e43842440bb2d57d620b6ff7d
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Tue Apr  3 13:13:21 2018 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Tue Apr  3 13:13:21 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=81df4a8c

qsearch: improve documentation

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

 man/include/qsearch.desc         |  3 +++
 man/include/qsearch.optdesc.yaml |  2 ++
 man/qsearch.1                    | 36 ++++++++++++++++++++----------------
 qsearch.c                        |  6 +++---
 4 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/man/include/qsearch.desc b/man/include/qsearch.desc
new file mode 100644
index 0000000..281c5a3
--- /dev/null
+++ b/man/include/qsearch.desc
@@ -0,0 +1,3 @@
+\fIqsearch\fR performs a search over the name and/or description of
+packages.  By default, a search over all package names is performed over
+all ebuilds in the tree.

diff --git a/man/include/qsearch.optdesc.yaml b/man/include/qsearch.optdesc.yaml
new file mode 100644
index 0000000..9bbaeaa
--- /dev/null
+++ b/man/include/qsearch.optdesc.yaml
@@ -0,0 +1,2 @@
+verbose: Ignored for compatibility with other qapplets.
+quiet: Ignored for compatibility with other qapplets.

diff --git a/man/qsearch.1 b/man/qsearch.1
index 5f888ba..3c6032d 100644
--- a/man/qsearch.1
+++ b/man/qsearch.1
@@ -1,56 +1,60 @@
-.TH qsearch "1" "Mar 2016" "Gentoo Foundation" "qsearch"
+.\" generated by mkman.py, please do NOT edit!
+.TH qsearch "1" "Apr 2018" "Gentoo Foundation" "qsearch"
 .SH NAME
 qsearch \- search pkgname/desc
 .SH SYNOPSIS
 .B qsearch
 \fI[opts] <regex>\fR
 .SH DESCRIPTION
-
+\fIqsearch\fR performs a search over the name and/or description of
+packages.  By default, a search over all package names is performed over
+all ebuilds in the tree.
 .SH OPTIONS
 .TP
 \fB\-a\fR, \fB\-\-all\fR
-List the descriptions of every package in the cache
+List the descriptions of every package in the cache.
 .TP
 \fB\-c\fR, \fB\-\-cache\fR
-Use the portage cache (default)
+Use the portage cache.
 .TP
 \fB\-e\fR, \fB\-\-ebuilds\fR
-Use the portage ebuild tree
+Use the portage ebuild tree (default).
 .TP
 \fB\-s\fR, \fB\-\-search\fR
-Regex search package basenames
+Regex search package basenames.
 .TP
 \fB\-S\fR \fI<arg>\fR, \fB\-\-desc\fR \fI<arg>\fR
-Regex search package descriptions
+Regex search package descriptions.
 .TP
 \fB\-N\fR, \fB\-\-name\-only\fR
-Only show package name
+Only show package name.
 .TP
 \fB\-H\fR, \fB\-\-homepage\fR
-Show homepage info
+Show homepage info.
 .TP
 \fB\-\-root\fR \fI<arg>\fR
-Set the ROOT env var
+Set the ROOT env var.
 .TP
 \fB\-v\fR, \fB\-\-verbose\fR
-Make a lot of noise
+Ignored for compatibility with other qapplets.
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
-Tighter output; suppress warnings
+Ignored for compatibility with other qapplets.
 .TP
 \fB\-C\fR, \fB\-\-nocolor\fR
-Don't output color
+Don't output color.
 .TP
 \fB\-h\fR, \fB\-\-help\fR
-Print this help and exit
+Print this help and exit.
 .TP
 \fB\-V\fR, \fB\-\-version\fR
-Print version and exit
+Print version and exit.
 
 .SH "REPORTING BUGS"
 Please report bugs via http://bugs.gentoo.org/
 .br
-Product: Portage Development; Component: Tools
+Product: Portage Development; Component: Tools, Assignee:
+portage-utils@gentoo.org
 .SH AUTHORS
 .nf
 Ned Ludd <solar@gentoo.org>

diff --git a/qsearch.c b/qsearch.c
index a620f95..4fce4de 100644
--- a/qsearch.c
+++ b/qsearch.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2014 Gentoo Foundation
+ * Copyright 2005-2018 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
@@ -21,8 +21,8 @@ static struct option const qsearch_long_opts[] = {
 };
 static const char * const qsearch_opts_help[] = {
 	"List the descriptions of every package in the cache",
-	"Use the portage cache (default)",
-	"Use the portage ebuild tree",
+	"Use the portage cache",
+	"Use the portage ebuild tree (default)",
 	"Regex search package basenames",
 	"Regex search package descriptions",
 	"Only show package name",


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/include/, man/, /
@ 2018-04-03 13:39 Fabian Groffen
  0 siblings, 0 replies; 6+ messages in thread
From: Fabian Groffen @ 2018-04-03 13:39 UTC (permalink / raw
  To: gentoo-commits

commit:     ea69f8fc6eb1e1ee71eea57b938eac631dedb4de
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Tue Apr  3 13:39:15 2018 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Tue Apr  3 13:39:15 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=ea69f8fc

qsize: improve documentation

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

 man/include/qpkg.optdesc.yaml |  2 +-
 man/qsize.1                   | 37 +++++++++++++++++++++----------------
 qsize.c                       |  6 +++---
 3 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/man/include/qpkg.optdesc.yaml b/man/include/qpkg.optdesc.yaml
index 2da2810..62c0b52 100644
--- a/man/include/qpkg.optdesc.yaml
+++ b/man/include/qpkg.optdesc.yaml
@@ -1,2 +1,2 @@
 verbose: Check and report MD5 hash mismatches during install.
-quiet: Ignored for compatability with other qapplets.
+quiet: Ignored for compatibility with other qapplets.

diff --git a/man/qsize.1 b/man/qsize.1
index aa613f8..a734afd 100644
--- a/man/qsize.1
+++ b/man/qsize.1
@@ -1,56 +1,61 @@
-.TH qsize "1" "Mar 2016" "Gentoo Foundation" "qsize"
+.\" generated by mkman.py, please do NOT edit!
+.TH qsize "1" "Apr 2018" "Gentoo Foundation" "qsize"
 .SH NAME
 qsize \- calculate size usage
 .SH SYNOPSIS
 .B qsize
 \fI[opts] <pkgname>\fR
 .SH DESCRIPTION
-
+\fIqsize\fR calculates the storage size taken by an installed package.
+The reported sizes can be the recorded exact sizes of all files, or the
+storage space they consume given the underlying filesystem.
 .SH OPTIONS
 .TP
 \fB\-f\fR, \fB\-\-filesystem\fR
-Show size used on disk
+Show size used on disk.
 .TP
 \fB\-s\fR, \fB\-\-sum\fR
-Include a summary
+Include a summary.
 .TP
 \fB\-S\fR, \fB\-\-sum\-only\fR
-Show just the summary
+Show just the summary.
 .TP
 \fB\-m\fR, \fB\-\-megabytes\fR
-Display size in megabytes
+Display all sizes in megabytes.
 .TP
 \fB\-k\fR, \fB\-\-kilobytes\fR
-Display size in kilobytes
+Display all sizes in kilobytes.
 .TP
 \fB\-b\fR, \fB\-\-bytes\fR
-Display size in bytes
+Display all sizes in bytes.
 .TP
 \fB\-i\fR \fI<arg>\fR, \fB\-\-ignore\fR \fI<arg>\fR
-Ignore regexp string
+Filter out entries matching \fI<arg>\fR, which is a regular
+expression, before calculating size.
 .TP
 \fB\-\-root\fR \fI<arg>\fR
-Set the ROOT env var
+Set the ROOT env var.
 .TP
 \fB\-v\fR, \fB\-\-verbose\fR
-Make a lot of noise
+Ignored for compatibility with other qapplets.
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
-Tighter output; suppress warnings
+Ignored for compatibility with other qapplets.
 .TP
 \fB\-C\fR, \fB\-\-nocolor\fR
-Don't output color
+Don't output color.
 .TP
 \fB\-h\fR, \fB\-\-help\fR
-Print this help and exit
+Print this help and exit.
 .TP
 \fB\-V\fR, \fB\-\-version\fR
-Print version and exit
+Print version and exit.
 
 .SH "REPORTING BUGS"
 Please report bugs via http://bugs.gentoo.org/
 .br
-Product: Portage Development; Component: Tools
+Product: Portage Development; Component: Tools, Assignee:
+portage-utils@gentoo.org
 .SH AUTHORS
 .nf
 Ned Ludd <solar@gentoo.org>

diff --git a/qsize.c b/qsize.c
index c485aa6..78b8f88 100644
--- a/qsize.c
+++ b/qsize.c
@@ -23,9 +23,9 @@ static const char * const qsize_opts_help[] = {
 	"Show size used on disk",
 	"Include a summary",
 	"Show just the summary",
-	"Display size in megabytes",
-	"Display size in kilobytes",
-	"Display size in bytes",
+	"Display all sizes in megabytes",
+	"Display all sizes in kilobytes",
+	"Display all sizes in bytes",
 	"Ignore regexp string",
 	COMMON_OPTS_HELP
 };


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/include/, man/, /
@ 2018-05-18 10:15 Fabian Groffen
  0 siblings, 0 replies; 6+ messages in thread
From: Fabian Groffen @ 2018-05-18 10:15 UTC (permalink / raw
  To: gentoo-commits

commit:     04b4c6834fd83bf0329198c56894bd7dad6f7a6a
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Fri May 18 10:12:40 2018 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Fri May 18 10:12:40 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=04b4c683

qtegrity: new applet by Sam Besselink for use with IMA, bug #619988

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

 applets.h                                      |   7 +-
 man/include/qtegrity-70-relevant-files.include |   9 +
 man/include/qtegrity-authors.include           |   1 +
 man/include/qtegrity.desc                      |   8 +
 man/qtegrity.1                                 |  81 ++++
 qtegrity.c                                     | 509 +++++++++++++++++++++++++
 6 files changed, 614 insertions(+), 1 deletion(-)

diff --git a/applets.h b/applets.h
index 93146c6..daf7047 100644
--- a/applets.h
+++ b/applets.h
@@ -31,6 +31,7 @@ DECLARE_APPLET(qatom)
 DECLARE_APPLET(qmerge)
 DECLARE_APPLET(qcache)
 DECLARE_APPLET(qglsa) /* disable */
+DECLARE_APPLET(qtegrity)
 #undef DECLARE_APPLET
 
 #define DEFINE_APPLET_STUB(applet) \
@@ -62,8 +63,9 @@ static const struct applet_t {
 	{"qtbz2",     qtbz2_main,     "<misc args>",     "manipulate tbz2 packages"},
 	{"quse",      quse_main,      "<useflag>",       "find pkgs using useflags"},
 	{"qxpak",     qxpak_main,     "<misc args>",     "manipulate xpak archives"},
+	{"qtegrity",  qtegrity_main,  "<misc args>",     "verify files with IMA"},
 
-	/* aliases for equery capatability */
+	/* aliases for equery compatibility */
 	{"belongs",   qfile_main,     NULL, NULL},
 	/*"changes"*/
 	{"check",     qcheck_main,    NULL, NULL},
@@ -82,6 +84,9 @@ static const struct applet_t {
 	{"uickpkg",   qpkg_main,      NULL, NULL},
 	/* {"glsa",      qglsa_main,     NULL, NULL}, */
 
+	/* alias for qtegrity */
+	{"integrity", qtegrity_main,  NULL, NULL},
+
 	{NULL, NULL, NULL, NULL}
 };
 

diff --git a/man/include/qtegrity-70-relevant-files.include b/man/include/qtegrity-70-relevant-files.include
new file mode 100644
index 0000000..742658f
--- /dev/null
+++ b/man/include/qtegrity-70-relevant-files.include
@@ -0,0 +1,9 @@
+.SH RELEVANT FILES
+.PP
+Central list of known good digests
+.nf\fI
+	/var/db/QTEGRITY\fi
+.PP
+Linux kernel's recorded digests
+.nf\fI
+	/sys/kernel/security/ima/ascii_runtime_measurements\fi

diff --git a/man/include/qtegrity-authors.include b/man/include/qtegrity-authors.include
new file mode 100644
index 0000000..160ea6a
--- /dev/null
+++ b/man/include/qtegrity-authors.include
@@ -0,0 +1 @@
+Sam Besselink

diff --git a/man/include/qtegrity.desc b/man/include/qtegrity.desc
new file mode 100644
index 0000000..5f9029b
--- /dev/null
+++ b/man/include/qtegrity.desc
@@ -0,0 +1,8 @@
+The default behavior of \fBqtegrity\fP is to verify digests of performed
+executables to a list of known good digests. This requires an IMA-enabled
+linux kernel, which records digests of performed executables and exports them
+through securityfs. Using \fB\-\-ignore-non-existent\fP suppresses messages
+about recorded files that can't be accessed (assuming they got removed).
+By using \fB\-\-add\fP, the program behaves differently. No verification is
+performed, instead a digest is made of the provided file and appended to
+the list of known good digests.

diff --git a/man/qtegrity.1 b/man/qtegrity.1
new file mode 100644
index 0000000..76ed731
--- /dev/null
+++ b/man/qtegrity.1
@@ -0,0 +1,81 @@
+.\" generated by mkman.py, please do NOT edit!
+.TH qtegrity "1" "May 2018" "Gentoo Foundation" "qtegrity"
+.SH NAME
+qtegrity \- verify files with IMA
+.SH SYNOPSIS
+.B qtegrity
+\fI[opts] <misc args>\fR
+.SH DESCRIPTION
+The default behavior of \fBqtegrity\fP is to verify digests of performed
+executables to a list of known good digests. This requires an IMA-enabled
+linux kernel, which records digests of performed executables and exports them
+through securityfs. Using \fB\-\-ignore-non-existent\fP suppresses messages
+about recorded files that can't be accessed (assuming they got removed).
+By using \fB\-\-add\fP, the program behaves differently. No verification is
+performed, instead a digest is made of the provided file and appended to
+the list of known good digests.
+.SH OPTIONS
+.TP
+\fB\-a\fR \fI<arg>\fR, \fB\-\-add\fR \fI<arg>\fR
+Add file to store of known-good digests.
+.TP
+\fB\-i\fR, \fB\-\-ignore\-non\-existent\fR
+Be silent if recorded file no longer exists.
+.TP
+\fB\-s\fR, \fB\-\-show\-matches\fR
+Show recorded digests that match with known-good digests.
+.TP
+\fB\-\-root\fR \fI<arg>\fR
+Set the ROOT env var.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Make a lot of noise.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+Tighter output; suppress warnings.
+.TP
+\fB\-C\fR, \fB\-\-nocolor\fR
+Don't output color.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print this help and exit.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print version and exit.
+.SH RELEVANT FILES
+.PP
+Central list of known good digests
+.nf\fI
+	/var/db/QTEGRITY\fi
+.PP
+Linux kernel's recorded digests
+.nf\fI
+	/sys/kernel/security/ima/ascii_runtime_measurements\fi
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.br
+Product: Portage Development; Component: Tools, Assignee:
+portage-utils@gentoo.org
+.SH AUTHORS
+.nf
+Ned Ludd <solar@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+Sam Besselink
+.fi
+.SH "SEE ALSO"
+.BR q (1),
+.BR qatom (1),
+.BR qcache (1),
+.BR qcheck (1),
+.BR qdepends (1),
+.BR qfile (1),
+.BR qgrep (1),
+.BR qlist (1),
+.BR qlop (1),
+.BR qmerge (1),
+.BR qpkg (1),
+.BR qsearch (1),
+.BR qsize (1),
+.BR qtbz2 (1),
+.BR quse (1),
+.BR qxpak (1)

diff --git a/qtegrity.c b/qtegrity.c
new file mode 100644
index 0000000..8af5b08
--- /dev/null
+++ b/qtegrity.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright 2005-2018 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ *
+ * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
+ * Copyright 2005-2014 Mike Frysinger  - <vapier@gentoo.org>
+ * Copyright 2017-2018 Sam Besselink
+ */
+
+#ifdef APPLET_qtegrity
+
+#define QTEGRITY_FLAGS "a:is" COMMON_FLAGS
+static struct option const qtegrity_long_opts[] = {
+	{"add",			a_argument, NULL, 'a'},
+	{"ignore-non-existent", no_argument, NULL, 'i'},
+	{"show-matches", no_argument, NULL, 's'},
+/* TODO, add this functionality
+	{"convert", a_argument, NULL, 'c'}
+*/
+	COMMON_LONG_OPTS
+};
+static const char * const qtegrity_opts_help[] = {
+	"Add file to store of known-good digests",
+	"Be silent if recorded file no longer exists",
+	"Show recorded digests that match with known-good digests",
+/* TODO
+	"Convert known good digests to different hash function",
+*/
+	COMMON_OPTS_HELP
+};
+#define qtegrity_usage(ret) usage(ret, QTEGRITY_FLAGS, qtegrity_long_opts, qtegrity_opts_help, NULL, lookup_applet_idx("qtegrity"))
+
+struct qtegrity_opt_state {
+	bool ima;
+	bool add;
+	char* add_file;
+	bool ignore_non_exist;
+	bool show_matches;
+/* TODO
+	bool convert;
+*/
+};
+
+#define FILE_SUCCESS 1
+#define FILE_EMPTY 2
+#define FILE_RELATIVE 3
+
+#define SHA1_DIGEST_LENGTH 40
+#define SHA256_PREFIX_LENGTH 8
+#define SHA256_DIGEST_LENGTH 64
+#define SHA256_LENGTH (SHA256_PREFIX_LENGTH + SHA256_DIGEST_LENGTH)
+#define SHA512_DIGEST_LENGTH 128
+
+static void external_check_sha(char * ret_digest, char * filepath, char * algo) {
+	size_t size_digest = 1;
+
+	if (strcmp(algo, "sha256") == 0) {
+		size_digest = 64;
+	} else if (strcmp(algo, "sha512") == 0) {
+		size_digest = 128;
+	}
+
+	if ((strcmp(algo, "sha256") != 0) && (strcmp(algo, "sha512") != 0)) {
+		return;
+	}
+
+	char cmd[11];
+	snprintf(cmd, 10, "%ssum", algo);
+
+	int pipefd[2];
+	pid_t pid;
+
+	if (pipe(pipefd) == -1) {
+		perror("Couldn't create pipe to shasum\n");
+		exit(1);
+	}
+	if ((pid = fork()) == -1) {
+		perror("Couldn't fork to shasum\n");
+		exit(1);
+	}
+	if (pid == 0)
+	{
+		/* Child. Redirect stdout and stderr to pipe, replace execution
+		 * environment */
+		close(pipefd[0]);
+		dup2(pipefd[1], STDOUT_FILENO);
+		dup2(pipefd[1], STDERR_FILENO);
+		execlp(cmd, cmd, filepath, NULL);
+		perror("Executing shasum failed\n");
+		exit(1);
+	}
+
+	/* Only parent gets here. Listen to pipe */
+	close(pipefd[1]);
+	FILE* output = fdopen(pipefd[0], "r");
+	if (output == NULL) {
+		printf("Failed to run command '%s'\n", cmd);
+		exit(1);
+	}
+
+	/* Read pipe line for line */
+	while (fgets(ret_digest, size_digest+1, output))
+	{
+		if (strlen(ret_digest) == 64) /* Found what we need, can stop */
+		{
+			kill(pid, SIGKILL);
+			break;
+		}
+	}
+
+	pclose(output);
+	return;
+}
+
+static void get_fname_from_line(char * line, char **ret, int digest_size, int offset)
+{
+	size_t dlenstr = strlen(line);
+	char *p;
+	/* Skip first 123 chars to get to file depends on digest_func in IMA */
+	size_t skip = ((digest_size == SHA256_DIGEST_LENGTH) ||
+			(digest_size == SHA512_DIGEST_LENGTH)) ?
+		digest_size+offset+8 : digest_size+offset+6;
+
+	if (dlenstr > skip) { /* assume file is at least two chars long */
+		int segment_size = dlenstr - skip - 1;
+		p = xmalloc(segment_size+1);
+		memcpy(p, line + skip, segment_size);
+		p[segment_size] = '\0';
+	} else {
+		/* E.g. digest used wrong hash algo, or malformed input */
+		p = NULL;
+	}
+
+	*ret = p;
+}
+
+static void get_digest_from_line(char * line, char * ret, int digest_size, int offset)
+{
+	size_t dlenstr = strlen(line);
+	/* Skip first chars to get to digest depends on digest_func in IMA */
+	int skip = ((digest_size == SHA256_DIGEST_LENGTH) ||
+			(digest_size == SHA512_DIGEST_LENGTH)) ?
+		offset+8 : offset+6;
+
+	if (dlenstr > (digest_size+skip+1)) {
+		memcpy(ret, line+skip, digest_size);
+		ret[digest_size] = '\0';
+	}
+}
+
+static void get_known_good_digest(const char * fn_store, char * recorded_fname, char * ret, int recorded_digest_size)
+{
+	/* Open file with known good hashes */
+	int fd_store;
+	FILE *fp_store;
+
+	fd_store = open(fn_store, O_RDONLY|O_CLOEXEC, 0);
+	if (fd_store == -1) {
+		warnp("unable to open(%s)", fn_store);
+		exit(0);
+	}
+	if ((fp_store = fdopen(fd_store, "r")) == NULL) {
+		warnp("unable to fopen(%s, r)", fn_store);
+		close(fd_store);
+		exit(0);
+	}
+
+	char *buffered_line, *line, *fname;
+	size_t linelen;
+
+	/* Iterate over lines in known-good-hashes-file; per line: if fname
+	 * matches, grab hash. */
+	buffered_line = line = fname = NULL;
+	while (getline(&line, &linelen, fp_store) != -1) {
+		free(buffered_line);
+		buffered_line = xstrdup(line);
+
+		get_fname_from_line(line, &fname, recorded_digest_size, 15);
+
+		if (fname == NULL) {
+			/* probably line without digest (e.g. symlink) */
+			continue;
+		}
+
+		if (strcmp(recorded_fname, fname) == 0) {
+			get_digest_from_line(line, ret, recorded_digest_size, 9);
+
+			free(fname);
+			break;
+		}
+
+		free(fname);
+	}
+
+	free(line);
+	free(buffered_line);
+
+	close(fd_store);
+	fclose(fp_store);
+}
+
+static int get_size_digest(char * line)
+{
+	int ret = 0;
+
+	char *pfound;
+	/* find colon; it is boundary between end of hash func & begin of
+	 * digest */
+	pfound = strchr(line, ':');
+	if (pfound != NULL) {
+		int dpfound = pfound - line;
+		int cutoff_prefix = 0;
+
+		if (dpfound == 55 || dpfound == 6) {
+			ret = SHA1_DIGEST_LENGTH;
+		} else if (dpfound == 57) {
+			cutoff_prefix = 51;
+		} else if (dpfound == 8) {
+			cutoff_prefix = 0;
+		}
+
+		int dsegment = dpfound - cutoff_prefix;
+
+		char *line_segment;
+		line_segment = xmalloc(dsegment + 1);
+		/* chop off the first chars to get to the hash func */
+		memcpy(line_segment, line + cutoff_prefix, dsegment);
+		line_segment[dsegment] = '\0';
+
+		/* If line segment equals name of hash func, then return
+		 * relevant const. */
+		if (strcmp(line_segment, "sha512") == 0) {
+			ret = SHA512_DIGEST_LENGTH;
+		} else if (strcmp(line_segment, "sha256") == 0) {
+			ret = SHA256_DIGEST_LENGTH;
+		} else {
+			printf("Expected sha algo, got %s", line_segment);
+		}
+
+		free(line_segment);
+	}
+
+	return ret;
+}
+
+static int check_file(char * filename)
+{
+	/* TODO, this is 4096 too low, because this variable also holds
+	 * path; for linux path is max 4096 chars */
+	if (strlen(filename) > 255)
+		err("Filename too long");
+
+	if (filename[0] != '/') {
+		return FILE_RELATIVE;
+	}
+
+	return FILE_SUCCESS;
+}
+
+int qtegrity_main(int argc, char **argv)
+{
+	int i;
+
+	struct qtegrity_opt_state state = {
+		.ima = true,
+		.add = false,
+		.ignore_non_exist = false,
+		.show_matches = false,
+/* TODO
+		.convert = false;
+*/
+	};
+
+	while ((i = GETOPT_LONG(QTEGRITY, qtegrity, "")) != -1) {
+		switch (i) {
+			COMMON_GETOPTS_CASES(qtegrity)
+			case 'a':
+				state.ima = false;
+				state.add = true;
+				if (check_file(optarg) == FILE_SUCCESS) {
+					state.add_file = xstrdup(optarg);
+				} else {
+					err("Expected absolute file as argument, got '%s'", optarg);
+				}
+				break;
+			case 'i': state.ignore_non_exist = true; break;
+			case 's': state.show_matches = true; break;
+		}
+	}
+
+	if (state.ima) {
+		const char *fn_ima =
+			"/sys/kernel/security/ima/ascii_runtime_measurements";
+		int fd_ima;
+		FILE *fp_ima;
+		struct stat st;
+
+		fd_ima = open(fn_ima, O_RDONLY|O_CLOEXEC, 0);
+		if (fd_ima == -1) {
+			/* TODO, shouldn't we explicitly remind user IMA/securityfs
+			 * is needed? */
+			warnp("Unable to open(%s)", fn_ima);
+			exit(0);
+		}
+		if ((fp_ima = fdopen(fd_ima, "r")) == NULL) {
+			warnp("Unable to fopen(%s, r)", fn_ima);
+			close(fd_ima);
+			exit(0);
+		}
+
+		char *buffered_line, *line, *recorded_fname;
+		int recorded_digest_size = 0;
+		size_t linelen;
+
+		/* Iterate over IMA file, grab fname and digest, get known good
+		 * digest for fname and compare */
+		buffered_line = line = recorded_fname = NULL;
+		while (getline(&line, &linelen, fp_ima) != -1) {
+			char *recorded_digest;
+			char *digest;
+
+			free(buffered_line);
+			buffered_line = xstrdup(line);
+
+			if (buffered_line[0] != '1' || buffered_line[1] != '0')
+				continue;
+
+			recorded_digest_size = get_size_digest(buffered_line);
+			recorded_digest = xmalloc(recorded_digest_size+1);
+			recorded_digest[0] = '\0';
+
+			/* grab fname from IMA file line */
+			get_fname_from_line(buffered_line, &recorded_fname,
+					recorded_digest_size, 51);
+			/* grab digest from IMA file line, @TODO, check whether
+			 * digest == 000etc */
+			get_digest_from_line(buffered_line, recorded_digest,
+					recorded_digest_size, 50);
+
+			if (recorded_fname == NULL || recorded_digest == NULL) {
+				printf("Empty recorded filename: %s\n", line);
+
+				if (recorded_fname != NULL)
+					free(recorded_fname);
+
+				if (recorded_digest != NULL)
+					free(recorded_digest);
+
+				continue;
+			}
+
+			if (check_file(recorded_fname) == FILE_RELATIVE) {
+				printf("Seems like a kernel process: %s\n", recorded_fname);
+
+				free(recorded_fname);
+				free(recorded_digest);
+				continue;
+			}
+
+			if (stat(recorded_fname, &st) < 0) {
+				if (!state.ignore_non_exist)
+					printf("Couldn't access recorded file '%s'\n",
+							recorded_fname);
+
+				free(recorded_fname);
+				free(recorded_digest);
+				continue;
+			}
+
+			if (!(st.st_mode & S_IXUSR ||
+						st.st_mode & S_IXGRP ||
+						st.st_mode & S_IXOTH))
+			{
+				free(recorded_fname);
+				free(recorded_digest);
+				continue;
+			}
+
+			digest = xmalloc(recorded_digest_size+1);
+			digest[0] = '\0';
+
+			/* first try custom known good digests for fname */
+			get_known_good_digest("/var/db/QTEGRITY_custom",
+					recorded_fname, digest, recorded_digest_size);
+
+			if (digest[0] == '\0') {
+				digest[0] = '\0';
+				/* then try from OS source */
+				get_known_good_digest("/var/db/QTEGRITY",
+						recorded_fname, digest, recorded_digest_size);
+
+				if (digest[0] == '\0') {
+					printf("No digest found for: %s\n", line);
+
+					free(recorded_fname);
+					free(recorded_digest);
+					free(digest);
+					continue;
+				}
+			}
+
+			if (strcmp(recorded_digest, digest) != 0) {
+				printf("Digest didn't match for %s\n", recorded_fname);
+				printf("Known-good: '%s'...\nRecorded: '%s'\n\n",
+						digest, recorded_digest);
+			} else if (state.show_matches) {
+				printf("Success! Digest matched for %s\n", recorded_fname);
+			}
+
+			free(recorded_fname);
+			free(recorded_digest);
+			free(digest);
+		}
+
+		free(line);
+		free(buffered_line);
+
+		close(fd_ima);
+		fclose(fp_ima);
+	} else if (state.add) {
+		/* Add a single executable file+digest to the custom digest store */
+		const char *fn_qtegrity_custom = "/var/db/QTEGRITY_custom";
+		int fd_qtegrity_custom;
+		FILE *fp_qtegrity_custom;
+		struct stat st;
+		int flush_status;
+
+		fd_qtegrity_custom =
+			open(fn_qtegrity_custom, O_RDWR|O_CREAT|O_CLOEXEC, 0);
+		if (fd_qtegrity_custom == -1) {
+			warnp("Unable to open(%s)", fn_qtegrity_custom);
+			exit(0);
+		}
+		if ((fp_qtegrity_custom = fdopen(fd_qtegrity_custom, "w+")) == NULL) {
+			warnp("Unable to fopen(%s, r)", fn_qtegrity_custom);
+			close(fd_qtegrity_custom);
+			exit(0);
+		}
+
+		printf("Adding %s to %s\n", state.add_file, fn_qtegrity_custom);
+
+		if (stat(state.add_file, &st) < 0)
+			err("Couldn't access file '%s'\n", state.add_file);
+
+		if (!(st.st_mode & S_IXUSR ||
+					st.st_mode & S_IXGRP ||
+					st.st_mode & S_IXOTH))
+			err("File '%s' is not executable\n", state.add_file);
+
+		/* add digest */
+		char *hash_algo = (char *)"sha256";
+		char *file_digest;
+		file_digest = xmalloc(SHA256_DIGEST_LENGTH+1);
+		file_digest[0] = '\0';
+		external_check_sha(file_digest, state.add_file, hash_algo);
+
+		/* Iterate over lines; if fname matches, exit-loop */
+		char *line, *fname;
+		size_t linelen;
+		int recorded_digest_size = 0;
+		int skip = 0;
+		line = fname = NULL;
+		while (getline(&line, &linelen, fp_qtegrity_custom) != -1) {
+			recorded_digest_size = get_size_digest(line);
+			get_fname_from_line(line, &fname, recorded_digest_size, 5);
+
+			/* probably line without digest (e.g. symlink) */
+			if (fname == NULL)
+				continue;
+
+			if (strcmp(state.add_file, fname) == 0) {
+				printf("Executable already recorded, "
+						"replacing digest with %s\n", file_digest);
+				skip = ((recorded_digest_size == SHA256_DIGEST_LENGTH) ||
+						(recorded_digest_size == SHA512_DIGEST_LENGTH)) ?
+					recorded_digest_size+6+8 : recorded_digest_size+6+6;
+				fseek(fp_qtegrity_custom, -skip-strlen(fname), SEEK_CUR);
+				free(fname);
+				break;
+			}
+
+			free(fname);
+		}
+
+		free(line);
+
+		fputs(hash_algo, fp_qtegrity_custom);
+		fputs(":", fp_qtegrity_custom);
+		fputs(file_digest, fp_qtegrity_custom);
+		fputs(" file:", fp_qtegrity_custom);
+		fputs(state.add_file, fp_qtegrity_custom);
+		fputs("\n", fp_qtegrity_custom);
+
+		flush_status = fflush(fp_qtegrity_custom);
+		if (flush_status != 0)
+			puts("Error flushing stream!");
+
+		free(file_digest);
+	}
+
+	if (state.add)
+		free(state.add_file);
+
+	return EXIT_SUCCESS;
+}
+
+#else
+DEFINE_APPLET_STUB(qtegrity)
+#endif


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/include/, man/, /
@ 2019-06-12  9:13 Fabian Groffen
  0 siblings, 0 replies; 6+ messages in thread
From: Fabian Groffen @ 2019-06-12  9:13 UTC (permalink / raw
  To: gentoo-commits

commit:     753605792fab143ded32ebabbf85cc840151f0d2
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Wed Jun 12 09:11:44 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Wed Jun 12 09:11:44 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=75360579

quse: add mode for querying installed packages (only)

Instead of traversing the tree(s), look in the VDB (= installed
packages).  While doing this, when using -v, we can print the enabled
flags next to the flag and its description, as with `equery uses'.

Bug: https://bugs.gentoo.org/656550
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/quse.optdesc.yaml |  4 +++
 man/quse.1                    |  7 +++-
 quse.c                        | 81 +++++++++++++++++++++++++++++++++++--------
 3 files changed, 76 insertions(+), 16 deletions(-)

diff --git a/man/include/quse.optdesc.yaml b/man/include/quse.optdesc.yaml
index 79a98fa..693aade 100644
--- a/man/include/quse.optdesc.yaml
+++ b/man/include/quse.optdesc.yaml
@@ -4,3 +4,7 @@ verbose: |
     Also shows problems encountered during parsing.  These are mostly
     diagnostic and indicate possible incorrectness in the results.
 quiet: Ignored for compatibility with other qapplets.
+installed: |
+    Only search installed packages.  Together with \fB-v\fR this shows
+    USE-flags and their descriptions, and currently enabled flags
+    prefixed with an asterisk (\fI*\fR).

diff --git a/man/quse.1 b/man/quse.1
index 7f559fd..0a031ba 100644
--- a/man/quse.1
+++ b/man/quse.1
@@ -1,5 +1,5 @@
 .\" generated by mkman.py, please do NOT edit!
-.TH quse "1" "May 2019" "Gentoo Foundation" "quse"
+.TH quse "1" "Jun 2019" "Gentoo Foundation" "quse"
 .SH NAME
 quse \- find pkgs using useflags
 .SH SYNOPSIS
@@ -22,6 +22,11 @@ Use the LICENSE vs IUSE.
 \fB\-D\fR, \fB\-\-describe\fR
 Describe the USE flag.
 .TP
+\fB\-I\fR, \fB\-\-installed\fR
+Only search installed packages.  Together with \fB-v\fR this shows
+USE-flags and their descriptions, and currently enabled flags
+prefixed with an asterisk (\fI*\fR).
+.TP
 \fB\-p\fR \fI<arg>\fR, \fB\-\-package\fR \fI<arg>\fR
 Restrict matching to package or category.
 .TP

diff --git a/quse.c b/quse.c
index c7fbe81..751f767 100644
--- a/quse.c
+++ b/quse.c
@@ -21,17 +21,19 @@
 #include <ctype.h>
 #include <assert.h>
 
+#include "set.h"
 #include "rmspace.h"
 #include "tree.h"
 #include "xarray.h"
 #include "xregex.h"
 
-#define QUSE_FLAGS "eaLDp:R" COMMON_FLAGS
+#define QUSE_FLAGS "eaLDIp:R" COMMON_FLAGS
 static struct option const quse_long_opts[] = {
 	{"exact",     no_argument, NULL, 'e'},
 	{"all",       no_argument, NULL, 'a'},
 	{"license",   no_argument, NULL, 'L'},
 	{"describe",  no_argument, NULL, 'D'},
+	{"installed", no_argument, NULL, 'I'},
 	{"package",    a_argument, NULL, 'p'},
 	{"repo",      no_argument, NULL, 'R'},
 	COMMON_LONG_OPTS
@@ -41,6 +43,7 @@ static const char * const quse_opts_help[] = {
 	"List all ebuilds, don't match anything",
 	"Use the LICENSE vs IUSE",
 	"Describe the USE flag",
+	"Only search installed packages",
 	"Restrict matching to package or category",
 	"Show repository the ebuild originates from",
 	COMMON_OPTS_HELP
@@ -56,6 +59,7 @@ struct quse_state {
 	bool do_regex:1;
 	bool do_describe:1;
 	bool do_licence:1;
+	bool do_installed:1;
 	bool do_list:1;
 	bool do_repo:1;
 	depend_atom *match;
@@ -407,6 +411,7 @@ quse_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 	depend_atom *atom = NULL;  /* pacify compiler */
 	char buf[8192];
 	tree_pkg_meta *meta;
+	set *use = NULL;
 	bool match;
 	char *p;
 	char *q;
@@ -432,16 +437,44 @@ quse_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 		}
 	}
 
-	meta = tree_pkg_read(pkg_ctx);
-	if (meta == NULL)
-		return 0;
+	if (state->overlay != NULL) {
+		meta = tree_pkg_read(pkg_ctx);
+		if (meta == NULL)
+			return 0;
+		if (meta->IUSE == NULL)
+			return 0;
+	} else {
+		size_t dummy;
 
-	if (meta->IUSE == NULL)
-		return 0;
+		meta = xzalloc(sizeof(*meta));
+
+		dummy = 0;
+		if (!tree_pkg_vdb_eat(pkg_ctx, "IUSE", &meta->IUSE, &dummy)) {
+			free(meta);
+			return 0;
+		}
+
+		dummy = 0;
+		tree_pkg_vdb_eat(pkg_ctx, "LICENSE", &meta->LICENSE, &dummy);
+
+		s = NULL;
+		dummy = 0;
+		tree_pkg_vdb_eat(pkg_ctx, "USE", &s, &dummy);
+		p = s;
+		while ((q = strchr(p, (int)' ')) != NULL) {
+			*q++ = '\0';
+			use = add_set(p, use);
+			p = q;
+		}
+		if (*p != '\0')
+			use = add_set(p, use);
+		free(s);
+	}
 
 	if (verbose) {
 		portdirfd = openat(pkg_ctx->cat_ctx->ctx->portroot_fd,
-				state->overlay, O_RDONLY | O_CLOEXEC | O_PATH);
+				state->overlay == NULL ? main_overlay : state->overlay,
+				O_RDONLY | O_CLOEXEC | O_PATH);
 		if (portdirfd == -1)
 			return 0;
 	}
@@ -566,7 +599,9 @@ quse_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 					quse_search_profiles_desc(portdirfd, &us);
 
 			for (i = 0; i < cnt; i++) {
-				printf(" %c%s%s%s%*s  %s\n",
+				match = use != NULL && contains_set(us.argv[i], use);
+				printf("%s%c%s%s%s%*s  %s\n",
+						match ? "*" : " ",
 						us.argv[i][-1],
 						/* selected ? RED : NORM */ MAGENTA,
 						us.argv[i],
@@ -585,7 +620,16 @@ quse_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 		}
 	}
 
-	tree_close_meta(meta);
+	if (state->overlay != NULL) {
+		tree_close_meta(meta);
+	} else {
+		free(meta->IUSE);
+		if (meta->LICENSE != NULL)
+			free(meta->LICENSE);
+		free(meta);
+		if (use != NULL)
+			free_set(use);
+	}
 	if (verbose)
 		close(portdirfd);
 
@@ -603,6 +647,7 @@ int quse_main(int argc, char **argv)
 		.do_regex = true,
 		.do_describe = false,
 		.do_licence = false,
+		.do_installed = false,
 		.do_repo = false,
 		.match = NULL,
 		.overlay = NULL,
@@ -610,12 +655,13 @@ int quse_main(int argc, char **argv)
 
 	while ((i = GETOPT_LONG(QUSE, quse, "")) != -1) {
 		switch (i) {
-		case 'e': state.do_regex = false;   break;
-		case 'a': state.do_all = true;      break;
-		case 'L': state.do_licence = true;  break;
-		case 'D': state.do_describe = true; break;
-		case 'R': state.do_repo = true;     break;
-		case 'p': match = optarg;           break;
+		case 'e': state.do_regex = false;    break;
+		case 'a': state.do_all = true;       break;
+		case 'L': state.do_licence = true;   break;
+		case 'D': state.do_describe = true;  break;
+		case 'I': state.do_installed = true; break;
+		case 'R': state.do_repo = true;      break;
+		case 'p': match = optarg;            break;
 		COMMON_GETOPTS_CASES(quse)
 		}
 	}
@@ -646,6 +692,11 @@ int quse_main(int argc, char **argv)
 	if (state.do_describe) {
 		array_for_each(overlays, n, overlay)
 			quse_describe_flag(portroot, overlay, &state);
+	} else if (state.do_installed) {
+		tree_ctx *t = tree_open_vdb(portroot, portvdb);
+		state.overlay = NULL;
+		tree_foreach_pkg_sorted(t, quse_results_cb, &state);
+		tree_close(t);
 	} else {
 		array_for_each(overlays, n, overlay) {
 			tree_ctx *t = tree_open(portroot, overlay);


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/include/, man/, /
@ 2020-08-14 10:09 Fabian Groffen
  0 siblings, 0 replies; 6+ messages in thread
From: Fabian Groffen @ 2020-08-14 10:09 UTC (permalink / raw
  To: gentoo-commits

commit:     72830c415c6c2050ecf7d90e8c739d2764bc9e09
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Fri Aug 14 10:05:26 2020 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Fri Aug 14 10:05:26 2020 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=72830c41

qlist: add -t (tree) and -m (masks) arguments

-t allow traversing the configured trees
-m apply masks from profiles

E.g. useful to find the latest available non-masked version of a
package:
% qlist -Itvm mypackage

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qlist.optdesc.yaml |  6 ++++
 man/qlist.1                    | 10 +++++-
 qlist.c                        | 70 +++++++++++++++++++++++++++++++++++-------
 qmerge.c                       |  5 +--
 4 files changed, 77 insertions(+), 14 deletions(-)

diff --git a/man/include/qlist.optdesc.yaml b/man/include/qlist.optdesc.yaml
index 30d8446..1145fa9 100644
--- a/man/include/qlist.optdesc.yaml
+++ b/man/include/qlist.optdesc.yaml
@@ -3,6 +3,8 @@ installed: |
     name if the package is currently installed.
 binpkgs: |
     Operate on binary packages instead of installed packges.
+tree: |
+    Used with \fB\-I\fR to list packages available in the tree.
 umap: |
     List USE-flags enabled when the package was installed.  This flag
     implies \fB\-I\fR.
@@ -16,6 +18,10 @@ columns: |
     Like \fB\-Iv\fR, but package name and version are separated by a
     space for easy consumption by e.g.\ shell scripts which can read
     space-separated columns.
+masks: |
+    Filter matches for packages that are masked via the profiles.  In
+    particular useful in combination with \fB\-Itv\fR to find the latest
+    available version of a given package.
 verbose: |
     When used with \fB\-I\fR, print the package version next to name.
     When listing the package contents, \fB\-v\fR displays symlinks with

diff --git a/man/qlist.1 b/man/qlist.1
index 676ee96..db4be0d 100644
--- a/man/qlist.1
+++ b/man/qlist.1
@@ -1,5 +1,5 @@
 .\" generated by mkman.py, please do NOT edit!
-.TH qlist "1" "Nov 2019" "Gentoo Foundation" "qlist"
+.TH qlist "1" "Aug 2020" "Gentoo Foundation" "qlist"
 .SH NAME
 qlist \- list files owned by pkgname
 .SH SYNOPSIS
@@ -22,6 +22,9 @@ name if the package is currently installed.
 \fB\-k\fR, \fB\-\-binpkgs\fR
 Operate on binary packages instead of installed packges.
 .TP
+\fB\-t\fR, \fB\-\-tree\fR
+Used with \fB\-I\fR to list packages available in the tree.
+.TP
 \fB\-S\fR, \fB\-\-slots\fR
 Display installed packages with slots (use twice for subslots).
 .TP
@@ -38,6 +41,11 @@ Like \fB\-Iv\fR, but package name and version are separated by a
 space for easy consumption by e.g.\ shell scripts which can read
 space-separated columns.
 .TP
+\fB\-m\fR, \fB\-\-masks\fR
+Filter matches for packages that are masked via the profiles.  In
+particular useful in combination with \fB\-Itv\fR to find the latest
+available version of a given package.
+.TP
 \fB\-\-showdebug\fR
 Show /usr/lib/debug and /usr/src/debug files.
 .TP

diff --git a/qlist.c b/qlist.c
index cd60083..3652c0a 100644
--- a/qlist.c
+++ b/qlist.c
@@ -22,14 +22,16 @@
 #include "xpak.h"
 #include "xregex.h"
 
-#define QLIST_FLAGS "IkSRUcDedosF:" COMMON_FLAGS
+#define QLIST_FLAGS "IktSRUcmDedosF:" COMMON_FLAGS
 static struct option const qlist_long_opts[] = {
 	{"installed", no_argument, NULL, 'I'},
 	{"binpkgs",   no_argument, NULL, 'k'},
+	{"tree",      no_argument, NULL, 't'},
 	{"slots",     no_argument, NULL, 'S'},
 	{"repo",      no_argument, NULL, 'R'},
 	{"umap",      no_argument, NULL, 'U'},
 	{"columns",   no_argument, NULL, 'c'},
+	{"masks",     no_argument, NULL, 'm'},
 	{"showdebug", no_argument, NULL, 128},
 	{"exact",     no_argument, NULL, 'e'},
 	{"dir",       no_argument, NULL, 'd'},
@@ -42,10 +44,12 @@ static struct option const qlist_long_opts[] = {
 static const char * const qlist_opts_help[] = {
 	"Just show installed package names",
 	"Use binpkgs instead of installed packages",
+	"Use available packages in the tree instead of installed",
 	"Display installed packages with slots (use twice for subslots)",
 	"Display installed packages with repository",
 	"Display installed packages with flags used",
 	"Display column view",
+	"Exclude matches masked by profiles",
 	"Show /usr/lib/debug and /usr/src/debug files",
 	"Exact match (only CAT/PN or PN without PV)",
 	"Only show directories",
@@ -175,13 +179,15 @@ qlist_match(
 		tree_pkg_ctx *pkg_ctx,
 		const char *name,
 		depend_atom **name_atom,
-		bool exact);
+		bool exact,
+		bool applymasks);
 bool
 qlist_match(
 		tree_pkg_ctx *pkg_ctx,
 		const char *name,
 		depend_atom **name_atom,
-		bool exact)
+		bool exact,
+		bool applymasks)
 {
 	char buf[_Q_PATH_MAX];
 	char uslot[32];
@@ -255,6 +261,30 @@ qlist_match(
 			return false;
 	}
 
+	if (applymasks) {
+		DECLARE_ARRAY(masks);
+		depend_atom *matom;
+		char *mask;
+		size_t n;
+		bool match = false;
+
+		array_set(package_masks, masks);
+
+		array_for_each(masks, n, mask) {
+			if ((matom = atom_explode(mask)) == NULL)
+				continue;
+			match = atom_compare(atom, matom) == EQUAL;
+			atom_implode(matom);
+			if (match)
+				break;
+		}
+
+		xarrayfree_int(masks);
+
+		if (match)
+			return false;
+	}
+
 	if (exact) {
 		int i;
 
@@ -311,10 +341,12 @@ struct qlist_opt_state {
 	bool exact:1;
 	bool all:1;
 	bool do_binpkgs:1;
+	bool do_tree:1;
 	bool just_pkgname:1;
 	bool show_dir:1;
 	bool show_obj:1;
 	bool show_sym:1;
+	bool apply_masks:1;
 	bool need_full_atom:1;
 	bool show_umap:1;
 	bool show_dbg:1;
@@ -337,7 +369,8 @@ qlist_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 	if (!state->all) {
 		for (i = optind; i < state->argc; ++i)
 			if (qlist_match(pkg_ctx, state->argv[i],
-						&state->atoms[i - optind], state->exact))
+						&state->atoms[i - optind], state->exact,
+						state->apply_masks))
 				break;
 		if (i == state->argc)
 			return 0;
@@ -415,10 +448,12 @@ int qlist_main(int argc, char **argv)
 		.exact = false,
 		.all = false,
 		.do_binpkgs = false,
+		.do_tree = false,
 		.just_pkgname = false,
 		.show_dir = false,
 		.show_obj = false,
 		.show_sym = false,
+		.apply_masks = false,
 		.need_full_atom = false,
 		.show_umap = false,
 		.show_dbg = false,
@@ -431,6 +466,7 @@ int qlist_main(int argc, char **argv)
 		COMMON_GETOPTS_CASES(qlist)
 		case 'I': state.just_pkgname = true;                    break;
 		case 'k': state.do_binpkgs = true;                      break;
+		case 't': state.do_tree = true;                         break;
 		case 'S': state.just_pkgname = true; show_slots++;      break;
 		case 'R': state.just_pkgname = show_repo = true;        break;
 		case 'U': state.just_pkgname = state.show_umap = true;  break;
@@ -440,6 +476,7 @@ int qlist_main(int argc, char **argv)
 		case 'o': state.show_obj = true;                        break;
 		case 's': state.show_sym = true;                        break;
 		case 'c': do_columns = true;                            break;
+		case 'm': state.apply_masks = true;                     break;
 		case 'F': state.fmt = optarg;                           break;
 		}
 	}
@@ -486,13 +523,24 @@ int qlist_main(int argc, char **argv)
 	state.buf = xmalloc(state.buflen);
 	state.atoms = xcalloc(argc - optind, sizeof(*state.atoms));
 	ret = 1;
-	if (state.do_binpkgs)
-		vdb = tree_open_binpkg(portroot, pkgdir);
-	else
-		vdb = tree_open_vdb(portroot, portvdb);
-	if (vdb != NULL) {
-		ret = tree_foreach_pkg_sorted(vdb, qlist_cb, &state, NULL);
-		tree_close(vdb);
+	if (state.do_tree) {
+		size_t n;
+		const char *overlay;
+
+		array_for_each(overlays, n, overlay) {
+			vdb = tree_open(portroot, overlay);
+			ret |= tree_foreach_pkg_sorted(vdb, qlist_cb, &state, NULL);
+			tree_close(vdb);
+		}
+	} else {
+		if (state.do_binpkgs)
+			vdb = tree_open_binpkg(portroot, pkgdir);
+		else
+			vdb = tree_open_vdb(portroot, portvdb);
+		if (vdb != NULL) {
+			ret = tree_foreach_pkg_sorted(vdb, qlist_cb, &state, NULL);
+			tree_close(vdb);
+		}
 	}
 	free(state.buf);
 	for (i = optind; i < state.argc; ++i)

diff --git a/qmerge.c b/qmerge.c
index f246e57..d407cd7 100644
--- a/qmerge.c
+++ b/qmerge.c
@@ -1781,7 +1781,8 @@ extern bool qlist_match(
 		tree_pkg_ctx *pkg_ctx,
 		const char *name,
 		depend_atom **name_atom,
-		bool exact);
+		bool exact,
+		bool applymasks);
 
 static int
 qmerge_unmerge_cb(tree_pkg_ctx *pkg_ctx, void *priv)
@@ -1798,7 +1799,7 @@ qmerge_unmerge_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 
 	(void)list_set(priv, &todo);
 	for (p = todo; *p != NULL; p++) {
-		if (qlist_match(pkg_ctx, *p, NULL, true))
+		if (qlist_match(pkg_ctx, *p, NULL, true, false))
 			pkg_unmerge(pkg_ctx, NULL, cp_argc, cp_argv, cpm_argc, cpm_argv);
 	}
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [gentoo-commits] proj/portage-utils:master commit in: man/include/, man/, /
@ 2021-01-30 10:37 Fabian Groffen
  0 siblings, 0 replies; 6+ messages in thread
From: Fabian Groffen @ 2021-01-30 10:37 UTC (permalink / raw
  To: gentoo-commits

commit:     3ef45fa46d5a45a3f19806cf62aba8532b4e401f
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sat Jan 30 10:35:55 2021 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Jan 30 10:35:55 2021 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=3ef45fa4

qlop: support -d 0 (or @0)

Allow setting the zero date, to basically have a quick way to list
everything, useful with -E, e.g. -Evd 0 to show the entire emerge
history.

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 man/include/qlop.desc         |  2 +-
 man/include/qlop.optdesc.yaml |  2 +-
 man/qlop.1                    |  6 +++---
 qlop.c                        | 25 +++++++++++++++++--------
 4 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/man/include/qlop.desc b/man/include/qlop.desc
index e39f689..0f7fa7c 100644
--- a/man/include/qlop.desc
+++ b/man/include/qlop.desc
@@ -19,7 +19,7 @@ in further on specific packages.
 .P
 After version \fB0.74\fR of portage-utils, \fIqlop\fR was changed
 considerably to be more consistent and more advanced.  Most notably,
-this has changed default date output and commmand line flags.  Instead
+this has changed default date output and command line flags.  Instead
 of reporting the time the operation finished, \fIqlop\fR now reports the
 time the operation started.  The behaviour of the old \fB-g\fR flag is
 best matched by the new \fB-t\fR flag.  Similar, the old \fB-t\fR flag

diff --git a/man/include/qlop.optdesc.yaml b/man/include/qlop.optdesc.yaml
index c6e0833..fc268d6 100644
--- a/man/include/qlop.optdesc.yaml
+++ b/man/include/qlop.optdesc.yaml
@@ -16,7 +16,7 @@ date: |
     .IP YYYY-MM-DDThh:mm:ss
     As before, but hours, minutes and seconds added.  This is the same
     format qlop prints for timestamps.
-    .IP SSSSSSSSS
+    .IP "SSSSSSSSS or @SSSSSSSSS"
     Seconds since 1970-01-01 00:00:00 +0000 (UTC), the UNIX epoch.
     .IP FORMAT|DATE
     Use \fIFORMAT\fR as input for \fBstrptime\fR(3) to parse \fIDATE\fR.

diff --git a/man/qlop.1 b/man/qlop.1
index 5aafa82..a175332 100644
--- a/man/qlop.1
+++ b/man/qlop.1
@@ -1,5 +1,5 @@
 .\" generated by mkman.py, please do NOT edit!
-.TH qlop "1" "Nov 2020" "Gentoo Foundation" "qlop"
+.TH qlop "1" "Jan 2021" "Gentoo Foundation" "qlop"
 .SH NAME
 qlop \- emerge log analyzer
 .SH SYNOPSIS
@@ -27,7 +27,7 @@ in further on specific packages.
 .P
 After version \fB0.74\fR of portage-utils, \fIqlop\fR was changed
 considerably to be more consistent and more advanced.  Most notably,
-this has changed default date output and commmand line flags.  Instead
+this has changed default date output and command line flags.  Instead
 of reporting the time the operation finished, \fIqlop\fR now reports the
 time the operation started.  The behaviour of the old \fB-g\fR flag is
 best matched by the new \fB-t\fR flag.  Similar, the old \fB-t\fR flag
@@ -110,7 +110,7 @@ year, followed by month and day of month.
 .IP YYYY-MM-DDThh:mm:ss
 As before, but hours, minutes and seconds added.  This is the same
 format qlop prints for timestamps.
-.IP SSSSSSSSS
+.IP "SSSSSSSSS or @SSSSSSSSS"
 Seconds since 1970-01-01 00:00:00 +0000 (UTC), the UNIX epoch.
 .IP FORMAT|DATE
 Use \fIFORMAT\fR as input for \fBstrptime\fR(3) to parse \fIDATE\fR.

diff --git a/qlop.c b/qlop.c
index 5045d17..2d01689 100644
--- a/qlop.c
+++ b/qlop.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2020 Gentoo Foundation
+ * Copyright 2005-2021 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
@@ -116,14 +116,17 @@ parse_date(const char *sdate, time_t *t)
 	} else {
 		/* Handle automatic formats:
 		 * - "12315128"            -> %s
+		 * - "@12315128"            -> %s
 		 * - "2015-12-24"          -> %Y-%m-%d
 		 * - "2019-03-28T13:52:31" -> %Y-%m-%dT%H:%M:%s"
 		 * - human readable format (see below)
 		 */
-		size_t len = strspn(sdate, "0123456789-:T");
+		size_t len = strspn(sdate, "0123456789-:T@");
 		if (sdate[len] == '\0') {
 			const char *fmt;
-			if (strchr(sdate, '-') == NULL) {
+			if (sdate[0] == '@') {
+				fmt = "@%s";
+			} else if (strchr(sdate, '-') == NULL) {
 				fmt = "%s";
 			} else if ((s = strchr(sdate, 'T')) == NULL) {
 				fmt = "%Y-%m-%d";
@@ -1394,8 +1397,8 @@ int qlop_main(int argc, char **argv)
 	DECLARE_ARRAY(atoms);
 	int runningmode = 0;
 
-	start_time = 0;
-	end_time = LONG_MAX;
+	start_time = -1;
+	end_time = -1;
 	m.do_time = 0;
 	m.do_merge = 0;
 	m.do_unmerge = 0;
@@ -1435,10 +1438,10 @@ int qlop_main(int argc, char **argv)
 			case 'l': m.show_lastmerge = 1; break;
 			case 'F': m.fmt = optarg;       break;
 			case 'd':
-				if (start_time == 0) {
+				if (start_time == -1) {
 					if (!parse_date(optarg, &start_time))
 						err("invalid date: %s", optarg);
-				} else if (end_time == LONG_MAX) {
+				} else if (end_time == -1) {
 					if (!parse_date(optarg, &end_time))
 						err("invalid date: %s", optarg);
 				} else
@@ -1539,7 +1542,7 @@ int qlop_main(int argc, char **argv)
 	}
 
 	/* handle -l / -d conflict */
-	if (start_time != 0 && m.show_lastmerge) {
+	if (start_time != -1 && m.show_lastmerge) {
 		if (!m.show_emerge)
 			warn("-l and -d cannot be used together, dropping -l");
 		m.show_lastmerge = 0;
@@ -1563,6 +1566,12 @@ int qlop_main(int argc, char **argv)
 			m.fmt = "%[CATEGORY]%[PN]";
 	}
 
+	/* adjust time ranges when unset */
+	if (start_time == -1)
+		start_time = 0;
+	if (end_time == -1)
+		end_time = LONG_MAX;
+
 	if (m.do_running) {
 		array_t *new_atoms = NULL;
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-01-30 10:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-08-14 10:09 [gentoo-commits] proj/portage-utils:master commit in: man/include/, man/, / Fabian Groffen
  -- strict thread matches above, loose matches on Subject: below --
2021-01-30 10:37 Fabian Groffen
2019-06-12  9:13 Fabian Groffen
2018-05-18 10:15 Fabian Groffen
2018-04-03 13:39 Fabian Groffen
2018-04-03 13:39 Fabian Groffen

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