public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] gentoo-projects commit in portage-utils: qcheck.c
@ 2012-11-10  0:08 Mike Frysinger (vapier)
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Frysinger (vapier) @ 2012-11-10  0:08 UTC (permalink / raw
  To: gentoo-commits

vapier      12/11/10 00:08:46

  Modified:             qcheck.c
  Log:
  qcheck: fix ROOT handling when hashing files

Revision  Changes    Path
1.57                 portage-utils/qcheck.c

file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.57&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.57&content-type=text/plain
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?r1=1.56&r2=1.57

Index: qcheck.c
===================================================================
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -r1.56 -r1.57
--- qcheck.c	28 Oct 2012 04:52:56 -0000	1.56
+++ qcheck.c	10 Nov 2012 00:08:46 -0000	1.57
@@ -1,7 +1,7 @@
 /*
  * Copyright 2005-2011 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.56 2012/10/28 04:52:56 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.57 2012/11/10 00:08:46 vapier Exp $
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
  * Copyright 2005-2011 Mike Frysinger  - <vapier@gentoo.org>
@@ -36,7 +36,7 @@
 	"Undo prelink when calculating checksums",
 	COMMON_OPTS_HELP
 };
-static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.56 2012/10/28 04:52:56 vapier Exp $";
+static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.57 2012/11/10 00:08:46 vapier Exp $";
 #define qcheck_usage(ret) usage(ret, QCHECK_FLAGS, qcheck_long_opts, qcheck_opts_help, lookup_applet_idx("qcheck"))
 
 #define qcprintf(fmt, args...) if (!state->bad_only) printf(_(fmt), ## args)
@@ -173,7 +173,7 @@
 				}
 				continue;
 			}
-			hashed_file = (char*)hash_file_cb(e->name, hash_algo, hash_cb);
+			hashed_file = (char *)hash_file_at_cb(pkg_ctx->cat_ctx->ctx->portroot_fd, e->name + 1, hash_algo, hash_cb);
 			if (!hashed_file) {
 				++num_files_unknown;
 				free(hashed_file);





^ permalink raw reply	[flat|nested] 6+ messages in thread
* [gentoo-commits] gentoo-projects commit in portage-utils: qcheck.c
@ 2012-10-28  4:52 Mike Frysinger (vapier)
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Frysinger (vapier) @ 2012-10-28  4:52 UTC (permalink / raw
  To: gentoo-commits

vapier      12/10/28 04:52:56

  Modified:             qcheck.c
  Log:
  support skipping checking of CONFIG_PROTECT-ed files #330537 by Michał Górny

Revision  Changes    Path
1.56                 portage-utils/qcheck.c

file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.56&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.56&content-type=text/plain
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?r1=1.55&r2=1.56

Index: qcheck.c
===================================================================
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- qcheck.c	19 Dec 2011 04:23:18 -0000	1.55
+++ qcheck.c	28 Oct 2012 04:52:56 -0000	1.56
@@ -1,7 +1,7 @@
 /*
  * Copyright 2005-2011 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.55 2011/12/19 04:23:18 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.56 2012/10/28 04:52:56 vapier Exp $
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
  * Copyright 2005-2011 Mike Frysinger  - <vapier@gentoo.org>
@@ -11,15 +11,16 @@
 
 #define QCHECK_FLAGS "aes:uABHTp" COMMON_FLAGS
 static struct option const qcheck_long_opts[] = {
-	{"all",     no_argument, NULL, 'a'},
-	{"exact",   no_argument, NULL, 'e'},
-	{"skip",     a_argument, NULL, 's'},
-	{"update",  no_argument, NULL, 'u'},
-	{"noafk",   no_argument, NULL, 'A'},
-	{"badonly", no_argument, NULL, 'B'},
-	{"nohash",  no_argument, NULL, 'H'},
-	{"nomtime", no_argument, NULL, 'T'},
-	{"prelink", no_argument, NULL, 'p'},
+	{"all",            no_argument, NULL, 'a'},
+	{"exact",          no_argument, NULL, 'e'},
+	{"skip",            a_argument, NULL, 's'},
+	{"update",         no_argument, NULL, 'u'},
+	{"noafk",          no_argument, NULL, 'A'},
+	{"badonly",        no_argument, NULL, 'B'},
+	{"nohash",         no_argument, NULL, 'H'},
+	{"nomtime",        no_argument, NULL, 'T'},
+	{"skip-protected", no_argument, NULL, 128},
+	{"prelink",        no_argument, NULL, 'p'},
 	COMMON_LONG_OPTS
 };
 static const char * const qcheck_opts_help[] = {
@@ -31,10 +32,11 @@
 	"Only print pkgs containing bad files",
 	"Ignore differing/unknown file chksums",
 	"Ignore differing file mtimes",
+	"Ignore files in CONFIG_PROTECT-ed paths",
 	"Undo prelink when calculating checksums",
 	COMMON_OPTS_HELP
 };
-static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.55 2011/12/19 04:23:18 vapier Exp $";
+static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.56 2012/10/28 04:52:56 vapier Exp $";
 #define qcheck_usage(ret) usage(ret, QCHECK_FLAGS, qcheck_long_opts, qcheck_opts_help, lookup_applet_idx("qcheck"))
 
 #define qcprintf(fmt, args...) if (!state->bad_only) printf(_(fmt), ## args)
@@ -49,6 +51,7 @@
 	bool chk_afk;
 	bool chk_hash;
 	bool chk_mtime;
+	bool chk_config_protect;
 	bool undo_prelink;
 	bool exact;
 };
@@ -63,6 +66,8 @@
 	char *buffer, *line;
 	size_t linelen;
 	struct stat st, cst;
+	int cp_argc, cpm_argc;
+	char **cp_argv, **cpm_argv;
 
 	fpx = NULL;
 
@@ -91,6 +96,11 @@
 		}
 	}
 
+	if (!state->chk_config_protect) {
+		makeargv(config_protect, &cp_argc, &cp_argv);
+		makeargv(config_protect_mask, &cpm_argc, &cpm_argv);
+	}
+
 	buffer = line = NULL;
 	while (getline(&line, &linelen, fp) != -1) {
 		contents_entry *e;
@@ -127,6 +137,21 @@
 			continue;
 		}
 		if (e->digest && S_ISREG(st.st_mode)) {
+			if (!state->chk_config_protect) {
+				/* handle CONFIG_PROTECT-ed files */
+				int i;
+				/* if it's in CONFIG_PROTECT_MASK, check it like normal */
+				for (i = 1; i < cpm_argc; ++i)
+					if (strncmp(cpm_argv[i], e->name, strlen(cpm_argv[i])) == 0)
+						break;
+				if (i == cpm_argc) {
+					/* not explicitly masked, so if it's protected */
+					for (i = 1; i < cp_argc; ++i)
+						if (strncmp(cp_argv[i], e->name, strlen(cp_argv[i])) == 0)
+							goto cfg_protected;
+				}
+			}
+
 			/* validate digest (handles MD5 / SHA1) */
 			uint8_t hash_algo;
 			char *hashed_file;
@@ -225,12 +250,18 @@
 			if (state->qc_update)
 				fputs(buffer, fpx);
 		}
+ cfg_protected:
 		++num_files_ok;
 	}
 	free(line);
 	free(buffer);
 	fclose(fp);
 
+	if (!state->chk_config_protect) {
+		freeargv(cp_argc, cp_argv);
+		freeargv(cpm_argc, cpm_argv);
+	}
+
 	if (state->qc_update) {
 		if (fchown(fd, cst.st_uid, cst.st_gid)) {
 			/* meh */;
@@ -338,6 +369,7 @@
 		.chk_afk = true,
 		.chk_hash = true,
 		.chk_mtime = true,
+		.chk_config_protect = true,
 		.undo_prelink = false,
 		.exact = false,
 	};
@@ -361,6 +393,7 @@
 		case 'B': state.bad_only = true; break;
 		case 'H': state.chk_hash = false; break;
 		case 'T': state.chk_mtime = false; break;
+		case 128: state.chk_config_protect = false; break;
 		case 'p': state.undo_prelink = prelink_available(); break;
 		}
 	}





^ permalink raw reply	[flat|nested] 6+ messages in thread
* [gentoo-commits] gentoo-projects commit in portage-utils: qcheck.c
@ 2011-12-18  7:58 Mike Frysinger (vapier)
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Frysinger (vapier) @ 2011-12-18  7:58 UTC (permalink / raw
  To: gentoo-commits

vapier      11/12/18 07:58:40

  Modified:             qcheck.c
  Log:
  push down "exact" from global scope to per-applet state

Revision  Changes    Path
1.53                 portage-utils/qcheck.c

file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.53&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.53&content-type=text/plain
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?r1=1.52&r2=1.53

Index: qcheck.c
===================================================================
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -r1.52 -r1.53
--- qcheck.c	18 Dec 2011 01:17:14 -0000	1.52
+++ qcheck.c	18 Dec 2011 07:58:40 -0000	1.53
@@ -1,7 +1,7 @@
 /*
  * Copyright 2005-2011 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.52 2011/12/18 01:17:14 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.53 2011/12/18 07:58:40 vapier Exp $
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
  * Copyright 2005-2011 Mike Frysinger  - <vapier@gentoo.org>
@@ -34,7 +34,7 @@
 	"Undo prelink when calculating checksums",
 	COMMON_OPTS_HELP
 };
-static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.52 2011/12/18 01:17:14 vapier Exp $";
+static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.53 2011/12/18 07:58:40 vapier Exp $";
 #define qcheck_usage(ret) usage(ret, QCHECK_FLAGS, qcheck_long_opts, qcheck_opts_help, lookup_applet_idx("qcheck"))
 
 #define qcprintf(fmt, args...) if (!state->bad_only) printf(_(fmt), ## args)
@@ -50,6 +50,7 @@
 	bool chk_hash;
 	bool chk_mtime;
 	bool undo_prelink;
+	bool exact;
 };
 
 static int qcheck_process_contents(q_vdb_pkg_ctx *pkg_ctx, struct qcheck_opt_state *state)
@@ -290,7 +291,7 @@
 		for (i = optind; i < state->argc; ++i) {
 			free(buf);
 			xasprintf(&buf, "%s/%s", catname, pkgname);
-			if (!exact) {
+			if (!state->exact) {
 				if (rematch(state->argv[i], buf, REG_EXTENDED) == 0)
 					break;
 				if (rematch(state->argv[i], pkgname, REG_EXTENDED) == 0)
@@ -336,6 +337,7 @@
 		.chk_hash = true,
 		.chk_mtime = true,
 		.undo_prelink = false,
+		.exact = false,
 	};
 
 	DBG("argc=%d argv[0]=%s argv[1]=%s",
@@ -345,7 +347,7 @@
 		switch (i) {
 		COMMON_GETOPTS_CASES(qcheck)
 		case 'a': state.search_all = true; break;
-		case 'e': exact = 1; break;
+		case 'e': state.exact = true; break;
 		case 's': {
 			regex_t regex;
 			xregcomp(&regex, optarg, REG_EXTENDED|REG_NOSUB);






^ permalink raw reply	[flat|nested] 6+ messages in thread
* [gentoo-commits] gentoo-projects commit in portage-utils: qcheck.c
@ 2011-10-03  3:18 Mike Frysinger (vapier)
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Frysinger (vapier) @ 2011-10-03  3:18 UTC (permalink / raw
  To: gentoo-commits

vapier      11/10/03 03:18:11

  Modified:             qcheck.c
  Log:
  rewrite qcheck to use *at style funcs

Revision  Changes    Path
1.50                 portage-utils/qcheck.c

file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.50&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.50&content-type=text/plain
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?r1=1.49&r2=1.50

Index: qcheck.c
===================================================================
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- qcheck.c	3 Oct 2011 01:25:54 -0000	1.49
+++ qcheck.c	3 Oct 2011 03:18:10 -0000	1.50
@@ -1,7 +1,7 @@
 /*
  * Copyright 2005-2010 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.49 2011/10/03 01:25:54 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.50 2011/10/03 03:18:10 vapier Exp $
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
  * Copyright 2005-2010 Mike Frysinger  - <vapier@gentoo.org>
@@ -34,11 +34,11 @@
 	"Undo prelink when calculating checksums",
 	COMMON_OPTS_HELP
 };
-static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.49 2011/10/03 01:25:54 vapier Exp $";
+static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.50 2011/10/03 03:18:10 vapier Exp $";
 #define qcheck_usage(ret) usage(ret, QCHECK_FLAGS, qcheck_long_opts, qcheck_opts_help, lookup_applet_idx("qcheck"))
 
-short bad_only = 0;
-#define qcprintf(fmt, args...) if (!bad_only) printf( _( fmt ), ## args)
+static bool bad_only = false;
+#define qcprintf(fmt, args...) if (!bad_only) printf(_(fmt), ## args)
 
 static void qcheck_cleanup(regex_t **regex_head, const size_t regex_count)
 {
@@ -54,21 +54,242 @@
 	free(regex_head);
 }
 
+static int qcheck_process_contents(int portroot_fd, int pkg_fd,
+	const char *catname, const char *pkgname, regex_t **regex_head,
+	size_t regex_count, bool qc_update, bool chk_afk,
+	bool chk_hash, bool chk_mtime, bool undo_prelink)
+{
+	int fd;
+	FILE *fp, *fpx;
+	size_t num_files, num_files_ok, num_files_unknown, num_files_ignored;
+	char *buffer, *line;
+	size_t linelen;
+	struct stat st, cst;
+
+	fpx = NULL;
+
+	fd = openat(pkg_fd, "CONTENTS", O_RDONLY|O_CLOEXEC);
+	if (fd == -1)
+		return EXIT_SUCCESS;
+	if (fstat(fd, &cst)) {
+		close(fd);
+		return EXIT_SUCCESS;
+	}
+	if ((fp = fdopen(fd, "r")) == NULL) {
+		close(fd);
+		return EXIT_SUCCESS;
+	}
+
+	num_files = num_files_ok = num_files_unknown = num_files_ignored = 0;
+	qcprintf("%sing %s%s/%s%s ...\n",
+		(qc_update ? "Updat" : "Check"),
+		GREEN, catname, pkgname, NORM);
+	if (qc_update) {
+		fd = openat(pkg_fd, "CONTENTS~", O_RDWR|O_CLOEXEC|O_CREAT|O_TRUNC, 0644);
+		if (fd == -1 || (fpx = fdopen(fd, "w")) == NULL) {
+			fclose(fp);
+			warnp("unable to fopen(%s/%s, w)", pkgname, "CONTENTS~");
+			return EXIT_FAILURE;
+		}
+	}
+
+	buffer = line = NULL;
+	while (getline(&line, &linelen, fp) != -1) {
+		contents_entry *e;
+		free(buffer);
+		buffer = xstrdup(line);
+		e = contents_parse_line(line);
+		if (!e)
+			continue;
+
+		/* run our little checks */
+		++num_files;
+		if (regex_count) {
+			size_t j;
+			for (j = 0; j < regex_count; ++j)
+				if (!regexec(regex_head[j], e->name, 0, NULL, 0))
+					break;
+			if (j < regex_count) {
+				--num_files;
+				++num_files_ignored;
+				continue;
+			}
+		}
+		if (fstatat(portroot_fd, e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) {
+			/* make sure file exists */
+			if (chk_afk) {
+				qcprintf(" %sAFK%s: %s\n", RED, NORM, e->name);
+			} else {
+				--num_files;
+				++num_files_ignored;
+				if (qc_update)
+					fputs(buffer, fpx);
+			}
+			continue;
+		}
+		if (e->digest && S_ISREG(st.st_mode)) {
+			/* validate digest (handles MD5 / SHA1) */
+			uint8_t hash_algo;
+			char *hashed_file;
+			hash_cb_t hash_cb = undo_prelink ? hash_cb_prelink_undo : hash_cb_default;
+			switch (strlen(e->digest)) {
+				case 32: hash_algo = HASH_MD5; break;
+				case 40: hash_algo = HASH_SHA1; break;
+				default: hash_algo = 0; break;
+			}
+			if (!hash_algo) {
+				if (chk_hash) {
+					qcprintf(" %sUNKNOWN DIGEST%s: '%s' for '%s'\n", RED, NORM, e->digest, e->name);
+					++num_files_unknown;
+				} else {
+					--num_files;
+					++num_files_ignored;
+					if (qc_update)
+						fputs(buffer, fpx);
+				}
+				continue;
+			}
+			hashed_file = (char*)hash_file_cb(e->name, hash_algo, hash_cb);
+			if (!hashed_file) {
+				++num_files_unknown;
+				free(hashed_file);
+				if (qc_update) {
+					fputs(buffer, fpx);
+					if (!verbose)
+						continue;
+				}
+				qcprintf(" %sPERM %4o%s: %s\n", RED, (unsigned int)(st.st_mode & 07777), NORM, e->name);
+				continue;
+			} else if (strcmp(e->digest, hashed_file)) {
+				if (chk_hash) {
+					const char *digest_disp;
+					if (qc_update)
+						fprintf(fpx, "obj %s %s %lu\n", e->name, hashed_file, st.st_mtime);
+					switch (hash_algo) {
+						case HASH_MD5:  digest_disp = "MD5"; break;
+						case HASH_SHA1: digest_disp = "SHA1"; break;
+						default:        digest_disp = "UNK"; break;
+					}
+					qcprintf(" %s%s-DIGEST%s: %s", RED, digest_disp, NORM, e->name);
+					if (verbose)
+						qcprintf(" (recorded '%s' != actual '%s')", e->digest, hashed_file);
+					qcprintf("\n");
+				} else {
+					--num_files;
+					++num_files_ignored;
+					if (qc_update)
+						fputs(buffer, fpx);
+				}
+				free(hashed_file);
+				continue;
+			} else if (e->mtime && e->mtime != st.st_mtime) {
+				if (chk_mtime) {
+					qcprintf(" %sMTIME%s: %s", RED, NORM, e->name);
+					if (verbose)
+						qcprintf(" (recorded '%lu' != actual '%lu')", e->mtime, (unsigned long)st.st_mtime);
+					qcprintf("\n");
+
+					/* This can only be an obj, dir and sym have no digest */
+					if (qc_update)
+						fprintf(fpx, "obj %s %s %lu\n", e->name, e->digest, st.st_mtime);
+				} else {
+					--num_files;
+					++num_files_ignored;
+					if (qc_update)
+						fputs(buffer, fpx);
+				}
+				free(hashed_file);
+				continue;
+			} else {
+				if (qc_update)
+					fputs(buffer, fpx);
+				free(hashed_file);
+			}
+		} else if (e->mtime && e->mtime != st.st_mtime) {
+			if (chk_mtime) {
+				qcprintf(" %sMTIME%s: %s", RED, NORM, e->name);
+				if (verbose)
+					qcprintf(" (recorded '%lu' != actual '%lu')", e->mtime, (unsigned long)st.st_mtime);
+				qcprintf("\n");
+
+				/* This can only be a sym */
+				if (qc_update)
+					fprintf(fpx, "sym %s -> %s %lu\n", e->name, e->sym_target, st.st_mtime);
+			} else {
+				--num_files;
+				++num_files_ignored;
+				if (qc_update)
+					fputs(buffer, fpx);
+			}
+			continue;
+		} else {
+			if (qc_update)
+				fputs(buffer, fpx);
+		}
+		++num_files_ok;
+	}
+	free(line);
+	free(buffer);
+	fclose(fp);
+
+	if (qc_update) {
+		if (fchown(fd, cst.st_uid, cst.st_gid))
+			/* meh */;
+		if (fchmod(fd, cst.st_mode))
+			/* meh */;
+		fclose(fpx);
+		if (renameat(pkg_fd, "CONTENTS~", pkg_fd, "CONTENTS"))
+			unlinkat(pkg_fd, "CONTENTS~", 0);
+		if (!verbose)
+			return EXIT_SUCCESS;
+	}
+	if (bad_only && num_files_ok != num_files) {
+		if (verbose)
+			printf("%s/%s\n", catname, pkgname);
+		else {
+			depend_atom *atom = NULL;
+			char *buf;
+			xasprintf(&buf, "%s/%s", catname, pkgname);
+			if ((atom = atom_explode(buf)) != NULL) {
+				printf("%s/%s\n", catname, atom->PN);
+				atom_implode(atom);
+			} else  {
+				printf("%s/%s\n", catname, pkgname);
+			}
+			free(buf);
+		}
+	}
+	qcprintf("  %2$s*%1$s %3$s%4$zu%1$s out of %3$s%5$zu%1$s file%6$s are good",
+		NORM, BOLD, BLUE, num_files_ok, num_files,
+		(num_files > 1 ? "s" : ""));
+	if (num_files_unknown)
+		qcprintf(" (Unable to digest %2$s%3$zu%1$s file%4$s)",
+			NORM, BLUE, num_files_unknown,
+			(num_files_unknown > 1 ? "s" : ""));
+	if (num_files_ignored)
+		qcprintf(" (%2$s%3$zu%1$s file%4$s ignored)",
+			NORM, BLUE, num_files_ignored,
+			(num_files_ignored > 1 ? "s were" : " was"));
+	qcprintf("\n");
+
+	if (num_files_ok != num_files)
+		return EXIT_FAILURE;
+	else
+		return EXIT_SUCCESS;
+}
+
 int qcheck_main(int argc, char **argv)
 {
 	DIR *dir, *dirp;
 	int i, ret;
+	int portroot_fd, vdb_fd, cat_fd, pkg_fd;
 	struct dirent *dentry, *de;
-	char search_all = 0;
-	char qc_update = 0;
-	char chk_afk = 1;
-	char chk_hash = 1;
-	char chk_mtime = 1;
+	bool search_all = 0;
+	bool qc_update = false;
+	bool chk_afk = true;
+	bool chk_hash = true;
+	bool chk_mtime = true;
 	bool undo_prelink = false;
-	struct stat st;
-	size_t num_files, num_files_ok, num_files_unknown, num_files_ignored;
-	char buf[_Q_PATH_MAX], filename[_Q_PATH_MAX];
-	char buffer[_Q_PATH_MAX];
 	regex_t **regex_head = NULL;
 	size_t regex_count = 0;
 
@@ -78,7 +299,7 @@
 	while ((i = GETOPT_LONG(QCHECK, qcheck, "")) != -1) {
 		switch (i) {
 		COMMON_GETOPTS_CASES(qcheck)
-		case 'a': search_all = 1; break;
+		case 'a': search_all = true; break;
 		case 'e': exact = 1; break;
 		case 's': {
 				regex_head = xrealloc(regex_head, (regex_count + 1) * sizeof(*regex_head));
@@ -87,42 +308,47 @@
 				++regex_count;
 			}
 			break;
-		case 'u': qc_update = 1; break;
-		case 'A': chk_afk = 0; break;
-		case 'B': bad_only = 1; break;
-		case 'H': chk_hash = 0; break;
-		case 'T': chk_mtime = 0; break;
+		case 'u': qc_update = true; break;
+		case 'A': chk_afk = false; break;
+		case 'B': bad_only = true; break;
+		case 'H': chk_hash = false; break;
+		case 'T': chk_mtime = false; break;
 		case 'p': undo_prelink = prelink_available(); break;
 		}
 	}
 	if ((argc == optind) && !search_all)
 		qcheck_usage(EXIT_FAILURE);
 
-	snprintf(buf, sizeof(buf), "%s/%s", portroot, portvdb);
-	xchdir(buf);
-	if ((dir = opendir(".")) == NULL)
-		errp("unable to read '.' !?");
+	portroot_fd = open(portroot, O_RDONLY|O_CLOEXEC);
+	if (portroot_fd == -1)
+		errp("unable to read %s !?", portroot);
+	vdb_fd = openat(portroot_fd, portvdb + 1, O_RDONLY|O_CLOEXEC);
+	if (vdb_fd == -1 || (dir = fdopendir(vdb_fd)) == NULL)
+		errp("unable to read %s !?", portvdb);
 
 	ret = EXIT_SUCCESS;
 
 	/* open /var/db/pkg */
 	while ((dentry = q_vdb_get_next_dir(dir))) {
-		if (chdir(dentry->d_name) != 0)
+		cat_fd = openat(vdb_fd, dentry->d_name, O_RDONLY|O_CLOEXEC);
+		if (cat_fd == -1)
 			continue;
-		if ((dirp = opendir(".")) == NULL)
+		if ((dirp = fdopendir(cat_fd)) == NULL) {
+			close(cat_fd);
 			continue;
+		}
 
 		/* open the cateogry */
 		while ((de = readdir(dirp)) != NULL) {
-			FILE *fp, *fpx;
 			if (*de->d_name == '.')
 				continue;
-			fp = fpx = NULL;
 
 			/* see if this cat/pkg is requested */
 			if (!search_all) {
+				char *buf = NULL;
 				for (i = optind; i < argc; ++i) {
-					snprintf(buf, sizeof(buf), "%s/%s", dentry->d_name, de->d_name);
+					free(buf);
+					xasprintf(&buf, "%s/%s", dentry->d_name, de->d_name);
 					if (!exact) {
 						if (rematch(argv[i], buf, REG_EXTENDED) == 0)
 							break;
@@ -141,211 +367,27 @@
 							break;
 						if ((strcmp(argv[i], strstr(swap, "/") + 1) == 0) || (strcmp(argv[i], strstr(buf, "/") + 1) == 0))
 							break;
-						}
+					}
 				}
+				free(buf);
 				if (i == argc)
 					continue;
 			}
 
-			snprintf(buf, sizeof(buf), "%s%s/%s/%s/CONTENTS", portroot, portvdb, dentry->d_name, de->d_name);
-			if ((fp = fopen(buf, "re")) == NULL)
+			pkg_fd = openat(cat_fd, de->d_name, O_RDONLY|O_CLOEXEC);
+			if (pkg_fd == -1)
 				continue;
-			strncat(buf, "~", sizeof(buf)-strlen(buf)-1);
-			num_files = num_files_ok = num_files_unknown = num_files_ignored = 0;
-			qcprintf("%sing %s%s/%s%s ...\n",
-				(qc_update ? "Updat" : "Check"),
-				GREEN, dentry->d_name, de->d_name, NORM);
-			if (qc_update) {
-				if ((fpx = fopen(buf, "we")) == NULL) {
-					fclose(fp);
-					warnp("unable to fopen(%s, w)", buf);
-					continue;
-				}
-			}
-			while ((fgets(buf, sizeof(buf), fp)) != NULL) {
-				contents_entry *e;
-				/* safe. buf and buffer are the same size.. */
-				strcpy(buffer, buf);
-				e = contents_parse_line(buf);
-				if (!e)
-					continue;
-				if (strcmp(portroot, "/") != 0) {
-					snprintf(filename, sizeof(filename), "%s%s", portroot, e->name);
-					e->name = filename;
-				}
-
-				/* run our little checks */
-				++num_files;
-				if (regex_count) {
-					size_t j;
-					for (j = 0; j < regex_count; ++j)
-						if (!regexec(regex_head[j], e->name, 0, NULL, 0))
-							break;
-					if (j < regex_count) {
-						--num_files;
-						++num_files_ignored;
-						continue;
-					}
-				}
-				if (lstat(e->name, &st)) {
-					/* make sure file exists */
-					if (chk_afk) {
-						qcprintf(" %sAFK%s: %s\n", RED, NORM, e->name);
-					} else {
-						--num_files;
-						++num_files_ignored;
-						if (qc_update)
-							fputs(buffer, fpx);
-					}
-					continue;
-				}
-				if (e->digest && S_ISREG(st.st_mode)) {
-					/* validate digest (handles MD5 / SHA1) */
-					uint8_t hash_algo;
-					char *hashed_file;
-					hash_cb_t hash_cb = undo_prelink ? hash_cb_prelink_undo : hash_cb_default;
-					switch (strlen(e->digest)) {
-						case 32: hash_algo = HASH_MD5; break;
-						case 40: hash_algo = HASH_SHA1; break;
-						default: hash_algo = 0; break;
-					}
-					if (!hash_algo) {
-						if (chk_hash) {
-							qcprintf(" %sUNKNOWN DIGEST%s: '%s' for '%s'\n", RED, NORM, e->digest, e->name);
-							++num_files_unknown;
-						} else {
-							--num_files;
-							++num_files_ignored;
-							if (qc_update)
-								fputs(buffer, fpx);
-						}
-						continue;
-					}
-					hashed_file = (char*)hash_file_cb(e->name, hash_algo, hash_cb);
-					if (!hashed_file) {
-						++num_files_unknown;
-						free(hashed_file);
-						if (qc_update) {
-							fputs(buffer, fpx);
-							if (!verbose)
-								continue;
-						}
-						qcprintf(" %sPERM %4o%s: %s\n", RED, (unsigned int)(st.st_mode & 07777), NORM, e->name);
-						continue;
-					} else if (strcmp(e->digest, hashed_file)) {
-						if (chk_hash) {
-							const char *digest_disp;
-							if (qc_update)
-								fprintf(fpx, "obj %s %s %lu\n", e->name, hashed_file, st.st_mtime);
-							switch (hash_algo) {
-								case HASH_MD5:  digest_disp = "MD5"; break;
-								case HASH_SHA1: digest_disp = "SHA1"; break;
-								default:        digest_disp = "UNK"; break;
-							}
-							qcprintf(" %s%s-DIGEST%s: %s", RED, digest_disp, NORM, e->name);
-							if (verbose)
-								qcprintf(" (recorded '%s' != actual '%s')", e->digest, hashed_file);
-							qcprintf("\n");
-						} else {
-							--num_files;
-							++num_files_ignored;
-							if (qc_update)
-								fputs(buffer, fpx);
-						}
-						free(hashed_file);
-						continue;
-					} else if (e->mtime && e->mtime != st.st_mtime) {
-						if (chk_mtime) {
-							qcprintf(" %sMTIME%s: %s", RED, NORM, e->name);
-							if (verbose)
-								qcprintf(" (recorded '%lu' != actual '%lu')", e->mtime, (unsigned long)st.st_mtime);
-							qcprintf("\n");
-
-							/* This can only be an obj, dir and sym have no digest */
-							if (qc_update)
-								fprintf(fpx, "obj %s %s %lu\n", e->name, e->digest, st.st_mtime);
-						} else {
-							--num_files;
-							++num_files_ignored;
-							if (qc_update)
-								fputs(buffer, fpx);
-						}
-						free(hashed_file);
-						continue;
-					} else {
-						if (qc_update)
-							fputs(buffer, fpx);
-						free(hashed_file);
-					}
-				} else if (e->mtime && e->mtime != st.st_mtime) {
-					if (chk_mtime) {
-						qcprintf(" %sMTIME%s: %s", RED, NORM, e->name);
-						if (verbose)
-							qcprintf(" (recorded '%lu' != actual '%lu')", e->mtime, (unsigned long)st.st_mtime);
-						qcprintf("\n");
-
-						/* This can only be a sym */
-						if (qc_update)
-							fprintf(fpx, "sym %s -> %s %lu\n", e->name, e->sym_target, st.st_mtime);
-					} else {
-						--num_files;
-						++num_files_ignored;
-						if (qc_update)
-							fputs(buffer, fpx);
-					}
-					continue;
-				} else {
-					if (qc_update)
-						fputs(buffer, fpx);
-				}
-				++num_files_ok;
-			}
-			fclose(fp);
-			if (qc_update) {
-				fclose(fpx);
-				snprintf(buf, sizeof(buf), "%s%s/%s/%s/CONTENTS", portroot, portvdb,
-					dentry->d_name, de->d_name);
-				strcpy(buffer, buf);
-				strncat(buffer, "~", sizeof(buffer)-strlen(buf)-1);
-				rename(buffer, buf);
-				if (!verbose)
-					continue;
-			}
-			if (bad_only && num_files_ok != num_files) {
-				if (verbose)
-					printf("%s/%s\n", dentry->d_name, de->d_name);
-				else {
-					depend_atom *atom = NULL;
-					snprintf(buf, sizeof(buf), "%s/%s", dentry->d_name, de->d_name);
-					if ((atom = atom_explode(buf)) != NULL) {
-						printf("%s/%s\n", dentry->d_name, atom->PN);
-						atom_implode(atom);
-					} else  {
-						printf("%s/%s\n", dentry->d_name, de->d_name);
-					}
-				}
-			}
-			qcprintf("  %2$s*%1$s %3$s%4$zu%1$s out of %3$s%5$zu%1$s file%6$s are good",
-			       NORM, BOLD, BLUE, num_files_ok, num_files,
-			       (num_files > 1 ? "s" : ""));
-			if (num_files_unknown)
-				qcprintf(" (Unable to digest %2$s%3$zu%1$s file%4$s)",
-				       NORM, BLUE, num_files_unknown,
-				       (num_files_unknown > 1 ? "s" : ""));
-			if (num_files_ignored)
-				qcprintf(" (%2$s%3$zu%1$s file%4$s ignored)",
-				       NORM, BLUE, num_files_ignored,
-				       (num_files_ignored > 1 ? "s were" : " was"));
-			qcprintf("\n");
 
-			if (num_files_ok != num_files)
-				ret = EXIT_FAILURE;
+			ret = qcheck_process_contents(portroot_fd, pkg_fd,
+				dentry->d_name, de->d_name, regex_head, regex_count,
+				qc_update, chk_afk, chk_hash, chk_mtime, undo_prelink);
+			close(pkg_fd);
 		}
 		closedir(dirp);
-		xchdir("..");
 	}
 
 	qcheck_cleanup(regex_head, regex_count);
+	close(portroot_fd);
 	return ret;
 }
 






^ permalink raw reply	[flat|nested] 6+ messages in thread
* [gentoo-commits] gentoo-projects commit in portage-utils: qcheck.c
@ 2010-06-08  5:38 Mike Frysinger (vapier)
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Frysinger (vapier) @ 2010-06-08  5:38 UTC (permalink / raw
  To: gentoo-commits

vapier      10/06/08 05:38:17

  Modified:             qcheck.c
  Log:
  qcheck: exit(0) only when all files are good to aid in scripting as suggested by Elias Probst #282647

Revision  Changes    Path
1.45                 portage-utils/qcheck.c

file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.45&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.45&content-type=text/plain
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?r1=1.44&r2=1.45

Index: qcheck.c
===================================================================
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- qcheck.c	8 Jun 2010 05:24:14 -0000	1.44
+++ qcheck.c	8 Jun 2010 05:38:17 -0000	1.45
@@ -1,7 +1,7 @@
 /*
  * Copyright 2005-2010 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.44 2010/06/08 05:24:14 vapier Exp $
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.45 2010/06/08 05:38:17 vapier Exp $
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
  * Copyright 2005-2010 Mike Frysinger  - <vapier@gentoo.org>
@@ -32,7 +32,7 @@
 	"Ignore differing file mtimes",
 	COMMON_OPTS_HELP
 };
-static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.44 2010/06/08 05:24:14 vapier Exp $";
+static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.45 2010/06/08 05:38:17 vapier Exp $";
 #define qcheck_usage(ret) usage(ret, QCHECK_FLAGS, qcheck_long_opts, qcheck_opts_help, lookup_applet_idx("qcheck"))
 
 short bad_only = 0;
@@ -55,7 +55,7 @@
 int qcheck_main(int argc, char **argv)
 {
 	DIR *dir, *dirp;
-	int i;
+	int i, ret;
 	struct dirent *dentry, *de;
 	char search_all = 0;
 	char qc_update = 0;
@@ -103,7 +103,9 @@
 	xchdir(portroot);
 	xchdir(portvdb);
 	if ((dir = opendir(".")) == NULL)
-		return EXIT_FAILURE;
+		errp("unable to read '.' !?");
+
+	ret = EXIT_SUCCESS;
 
 	/* open /var/db/pkg */
 	while ((dentry = q_vdb_get_next_dir(dir))) {
@@ -336,13 +338,16 @@
 				       NORM, BLUE, num_files_ignored,
 				       (num_files_ignored > 1 ? "s were" : " was"));
 			qcprintf("\n");
+
+			if (num_files_ok != num_files)
+				ret = EXIT_FAILURE;
 		}
 		closedir(dirp);
 		xchdir("..");
 	}
 
 	qcheck_cleanup(regex_head, regex_count);
-	return EXIT_SUCCESS;
+	return ret;
 }
 
 #else






^ permalink raw reply	[flat|nested] 6+ messages in thread
* [gentoo-commits] gentoo-projects commit in portage-utils: qcheck.c
@ 2010-06-08  5:24 Mike Frysinger (vapier)
  0 siblings, 0 replies; 6+ messages in thread
From: Mike Frysinger (vapier) @ 2010-06-08  5:24 UTC (permalink / raw
  To: gentoo-commits

vapier      10/06/08 05:24:14

  Modified:             qcheck.c
  Log:
  qcheck: add support by Darren Smith for ignoring files via regex #301360

Revision  Changes    Path
1.44                 portage-utils/qcheck.c

file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.44&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?rev=1.44&content-type=text/plain
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qcheck.c?r1=1.43&r2=1.44

Index: qcheck.c
===================================================================
RCS file: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -r1.43 -r1.44
--- qcheck.c	7 Apr 2010 05:58:16 -0000	1.43
+++ qcheck.c	8 Jun 2010 05:24:14 -0000	1.44
@@ -1,7 +1,7 @@
 /*
  * Copyright 2005-2010 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.43 2010/04/07 05:58:16 solar Exp $
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/qcheck.c,v 1.44 2010/06/08 05:24:14 vapier Exp $
  *
  * Copyright 2005-2010 Ned Ludd        - <solar@gentoo.org>
  * Copyright 2005-2010 Mike Frysinger  - <vapier@gentoo.org>
@@ -9,33 +9,49 @@
 
 #ifdef APPLET_qcheck
 
-#define QCHECK_FLAGS "eauAHTB" COMMON_FLAGS
+#define QCHECK_FLAGS "aes:uABHT" COMMON_FLAGS
 static struct option const qcheck_long_opts[] = {
-	{"exact",   no_argument, NULL, 'e'},
 	{"all",     no_argument, NULL, 'a'},
+	{"exact",   no_argument, NULL, 'e'},
+	{"skip",     a_argument, NULL, 's'},
 	{"update",  no_argument, NULL, 'u'},
 	{"noafk",   no_argument, NULL, 'A'},
+	{"badonly", no_argument, NULL, 'B'},
 	{"nohash",  no_argument, NULL, 'H'},
 	{"nomtime", no_argument, NULL, 'T'},
-	{"badonly", no_argument, NULL, 'B'},
 	COMMON_LONG_OPTS
 };
 static const char *qcheck_opts_help[] = {
-	"Exact match (only CAT/PN or PN without PV)",
 	"List all packages",
+	"Exact match (only CAT/PN or PN without PV)",
+	"Ignore files matching the regular expression <arg>",
 	"Update missing files, chksum and mtimes for packages",
 	"Ignore missing files",
+	"Only print pkgs containing bad files",
 	"Ignore differing/unknown file chksums",
 	"Ignore differing file mtimes",
-	"Only print pkgs containing bad files excluding /etc.",
 	COMMON_OPTS_HELP
 };
-static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.43 2010/04/07 05:58:16 solar Exp $";
+static const char qcheck_rcsid[] = "$Id: qcheck.c,v 1.44 2010/06/08 05:24:14 vapier Exp $";
 #define qcheck_usage(ret) usage(ret, QCHECK_FLAGS, qcheck_long_opts, qcheck_opts_help, lookup_applet_idx("qcheck"))
 
 short bad_only = 0;
 #define qcprintf(fmt, args...) if (!bad_only) printf( _( fmt ), ## args)
 
+static void qcheck_cleanup(regex_t **regex_head, const size_t regex_count)
+{
+	size_t i;
+
+	if (regex_head == NULL)
+		return;
+
+	for (i = 0; i < regex_count; ++i) {
+		regfree(regex_head[i]);
+		free(regex_head[i]);
+	}
+	free(regex_head);
+}
+
 int qcheck_main(int argc, char **argv)
 {
 	DIR *dir, *dirp;
@@ -50,6 +66,8 @@
 	size_t num_files, num_files_ok, num_files_unknown, num_files_ignored;
 	char buf[_Q_PATH_MAX], filename[_Q_PATH_MAX];
 	char buffer[_Q_PATH_MAX];
+	regex_t **regex_head = NULL;
+	size_t regex_count = 0;
 
 	DBG("argc=%d argv[0]=%s argv[1]=%s",
 	    argc, argv[0], argc > 1 ? argv[1] : "NULL?");
@@ -57,13 +75,26 @@
 	while ((i = GETOPT_LONG(QCHECK, qcheck, "")) != -1) {
 		switch (i) {
 		COMMON_GETOPTS_CASES(qcheck)
-		case 'e': exact = 1; break;
 		case 'a': search_all = 1; break;
+		case 'e': exact = 1; break;
+		case 's': {
+				int regex_val;
+				regex_head = xrealloc(regex_head, (regex_count + 1) * sizeof(*regex_head));
+				regex_head[regex_count] = xmalloc(sizeof(*regex_head[0]));
+				regex_val = regcomp(regex_head[regex_count], optarg, REG_EXTENDED|REG_NOSUB);
+				if (regex_val != 0) {
+					char errbuf[256];
+					regerror(regex_val, regex_head[regex_count], errbuf, sizeof(errbuf));
+					err("Invalid regexp: %s -- %s\n", optarg, errbuf);
+				}
+				++regex_count;
+			}
+			break;
 		case 'u': qc_update = 1; break;
 		case 'A': chk_afk = 0; break;
+		case 'B': bad_only = 1; break;
 		case 'H': chk_hash = 0; break;
 		case 'T': chk_mtime = 0; break;
-		case 'B': bad_only = 1; break;
 		}
 	}
 	if ((argc == optind) && !search_all)
@@ -138,9 +169,6 @@
 				e = contents_parse_line(buf);
 				if (!e)
 					continue;
-				if (bad_only && strncmp(e->name, "/etc", 4) == 0) {
-					continue;
-				}
 				if (strcmp(portroot, "/") != 0) {
 					snprintf(filename, sizeof(filename), "%s%s", portroot, e->name);
 					e->name = filename;
@@ -148,6 +176,17 @@
 
 				/* run our little checks */
 				++num_files;
+				if (regex_count) {
+					size_t j;
+					for (j = 0; j < regex_count; ++j)
+						if (!regexec(regex_head[j], e->name, 0, NULL, 0))
+							break;
+					if (j < regex_count) {
+						--num_files;
+						++num_files_ignored;
+						continue;
+					}
+				}
 				if (lstat(e->name, &st)) {
 					/* make sure file exists */
 					if (chk_afk) {
@@ -302,6 +341,7 @@
 		xchdir("..");
 	}
 
+	qcheck_cleanup(regex_head, regex_count);
 	return EXIT_SUCCESS;
 }
 






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

end of thread, other threads:[~2012-11-10  0:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-10  0:08 [gentoo-commits] gentoo-projects commit in portage-utils: qcheck.c Mike Frysinger (vapier)
  -- strict thread matches above, loose matches on Subject: below --
2012-10-28  4:52 Mike Frysinger (vapier)
2011-12-18  7:58 Mike Frysinger (vapier)
2011-10-03  3:18 Mike Frysinger (vapier)
2010-06-08  5:38 Mike Frysinger (vapier)
2010-06-08  5:24 Mike Frysinger (vapier)

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