Skip to content

Instantly share code, notes, and snippets.

@jperkin
Created September 8, 2023 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jperkin/6615a3fea7368e353e5c9dd48afce0bc to your computer and use it in GitHub Desktop.
Save jperkin/6615a3fea7368e353e5c9dd48afce0bc to your computer and use it in GitHub Desktop.
pkg_admin check fixes

The current implementation of pkg_admin check has a few issues:

  • It always exits 0 regardless of whether there were errors
  • Errors are printed to stdout
  • By default progress dots are printed, making the output rather unreadable.
  • Even in quiet mode (-q) it prints a summary at the end.

Example:

$ pkg_admin check; echo $?
./opt/pkg/lib/ruby/gems/3.1.0/doc/i18n-1.14.1/ri/I18n/Gettext/Helpers/N_-i.ri fails MD5 checksum
......../opt/pkg/lib/ruby/gems/3.1.0/doc/em-websocket-0.5.3/ri/EventMachine/WebSocket/cdesc-WebSocket.ri fails MD5 checksum
.........................................................../opt/pkg/lib/ruby/gems/3.1.0/doc/kramdown-2.4.0/ri/Kramdown/Converter/HashAST/cdesc-HashAST.ri fails MD5 checksum
............................................................................................................................................/opt/pkg/lib/ruby/gems/3.1.0/doc/http_parser.rb-0.8.0/ri/HTTP/cdesc-HTTP.ri fails MD5 checksum
.................................................../opt/pkg/share/ri/3.1.0/system/Net/HTTPGatewayTimeOut/cdesc-HTTPGatewayTimeOut.ri fails MD5 checksum
/opt/pkg/share/ri/3.1.0/system/Net/HTTPRequestTimeOut/cdesc-HTTPRequestTimeOut.ri fails MD5 checksum
...........
Checked 134888 files from 270 packages.
Done.
0

The following patch fixes all of the above issues.

Index: files/admin/admin.h
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_install/files/admin/admin.h,v
retrieving revision 1.6
diff -u -r1.6 admin.h
--- files/admin/admin.h	2 Feb 2009 12:35:00 -0000	1.6
+++ files/admin/admin.h	8 Sep 2023 10:54:13 -0000
@@ -27,7 +27,7 @@
 extern int quiet;
 extern int verbose;
 
-void 	check(char **);
+int 	check(char **);
 
 void	audit_pkgdb(int, char **);
 void	audit_pkg(int, char **);
Index: files/admin/check.c
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_install/files/admin/check.c,v
retrieving revision 1.12
diff -u -r1.12 check.c
--- files/admin/check.c	2 Dec 2020 10:45:47 -0000	1.12
+++ files/admin/check.c	8 Sep 2023 10:54:13 -0000
@@ -83,12 +83,13 @@
 /*
  * Assumes CWD is in the database directory ($PREFIX/pkgdb/<pkg>)!
  */
-static void 
+static int
 check1pkg(const char *pkgdir, int *filecnt, int *pkgcnt)
 {
 	FILE   *f;
 	plist_t *p;
 	package_t Plist;
+	int	rv = 0;
 	char   *PkgName, *dirp = NULL, *md5file;
 	char    file[MaxPathSize];
 	char   *content;
@@ -120,8 +121,10 @@
 					if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) {
 						if ((md5file = MD5File(file, NULL)) != NULL) {
 							/* Mismatch? */
-							if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0)
-								printf("%s fails MD5 checksum\n", file);
+							if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0) {
+								fprintf(stderr, "%s fails MD5 checksum\n", file);
+								rv = 1;
+							}
 
 							free(md5file);
 						}
@@ -133,11 +136,13 @@
 						if ((cc = readlink(file, &buf[SymlinkHeaderLen],
 							  sizeof(buf) - SymlinkHeaderLen - 1)) < 0) {
 							warnx("can't readlink `%s'", file);
+							rv = 1;
 						} else {
 							buf[SymlinkHeaderLen + cc] = 0x0;
 							if (strcmp(buf, p->next->name) != 0) {
-								printf("symlink (%s) is not same as recorded value, %s: %s\n",
+								fprintf(stderr, "symlink (%s) is not same as recorded value, %s: %s\n",
 								    file, buf, p->next->name);
+								rv = 1;
 							}
 						}
 					}
@@ -146,8 +151,10 @@
 				(*filecnt)++;
 			} else if (isbrokenlink(file)) {
 				warnx("%s: Symlink `%s' exists and is in %s but target does not exist!", PkgName, file, CONTENTS_FNAME);
+				rv = 1;
 			} else {
 				warnx("%s: File `%s' is in %s but not on filesystem!", PkgName, file, CONTENTS_FNAME);
+				rv = 1;
 			}
 			break;
 		case PLIST_CWD:
@@ -181,11 +188,14 @@
 	free_plist(&Plist);
 	fclose(f);
 	(*pkgcnt)++;
+
+	return rv;
 }
 
 struct checkpattern_arg {
 	int filecnt;
 	int pkgcnt;
+	int errcnt;
 	int got_match;
 };
 
@@ -194,16 +204,15 @@
 {
 	struct checkpattern_arg *arg = vp;
 
-	check1pkg(pkg, &arg->filecnt, &arg->pkgcnt);
-	if (!quiet)
-		printf(".");
+	if (check1pkg(pkg, &arg->filecnt, &arg->pkgcnt) != 0)
+		arg->errcnt++;
 
 	arg->got_match = 1;
 
 	return 0;
 }
 
-static void
+static int
 check_pkg(const char *pkg, int *filecnt, int *pkgcnt, int allow_unmatched)
 {
 	struct checkpattern_arg arg;
@@ -211,6 +220,7 @@
 
 	arg.filecnt = *filecnt;
 	arg.pkgcnt = *pkgcnt;
+	arg.errcnt = 0;
 	arg.got_match = 0;
 
 	if (match_installed_pkgs(pkg, checkpattern_fn, &arg) == -1)
@@ -218,12 +228,12 @@
 	if (arg.got_match != 0) {
 		*filecnt = arg.filecnt;
 		*pkgcnt = arg.pkgcnt;
-		return;
+		return (arg.errcnt) ? 1 : 0;
 	}
 
 	if (ispkgpattern(pkg)) {
 		if (allow_unmatched)
-			return;
+			return 0;
 		errx(EXIT_FAILURE, "No matching pkg for %s.", pkg);
 	}
 
@@ -238,26 +248,31 @@
 
 	*filecnt = arg.filecnt;
 	*pkgcnt = arg.pkgcnt;
+
+	return (arg.errcnt) ? 1 : 0;
 }
 
-void
+int
 check(char **argv)
 {
-	int filecnt, pkgcnt;
+	int filecnt, pkgcnt, errcnt = 0;
 
 	filecnt = 0;
 	pkgcnt = 0;
 	setbuf(stdout, NULL);
 
 	if (*argv == NULL) {
-		check_pkg("*", &filecnt, &pkgcnt, 1);
+		errcnt += check_pkg("*", &filecnt, &pkgcnt, 1);
 	} else {
 		for (; *argv != NULL; ++argv)
-			check_pkg(*argv, &filecnt, &pkgcnt, 0);
+			errcnt += check_pkg(*argv, &filecnt, &pkgcnt, 0);
+	}
+
+	if (!quiet) {
+		printf("Checked %d file%s from %d package%s.\n",
+		    filecnt, (filecnt == 1) ? "" : "s",
+		    pkgcnt, (pkgcnt == 1) ? "" : "s");
 	}
 
-	printf("\n");
-	printf("Checked %d file%s from %d package%s.\n",
-	    filecnt, (filecnt == 1) ? "" : "s",
-	    pkgcnt, (pkgcnt == 1) ? "" : "s");
+	return (errcnt) ? 1: 0;
 }
Index: files/admin/main.c
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_install/files/admin/main.c,v
retrieving revision 1.69
diff -u -r1.69 main.c
--- files/admin/main.c	2 Dec 2020 10:45:47 -0000	1.69
+++ files/admin/main.c	8 Sep 2023 10:54:13 -0000
@@ -458,7 +458,7 @@
 	char		 lsdir[MaxPathSize];
 	char		 sfx[MaxPathSize];
 	char		*lsdirp = NULL;
-	int		 ch;
+	int		 ch, rv;
 
 	setprogname(argv[0]);
 
@@ -561,12 +561,14 @@
 	} else if (strcasecmp(argv[0], "check") == 0) {
 		argv++;		/* "check" */
 
-		check(argv);
+		rv = check(argv);
 
 		if (!quiet) {
 			printf("Done.\n");
 		}
 
+		return rv;
+
 	} else if (strcasecmp(argv[0], "lsall") == 0) {
 		argv++;		/* "lsall" */
 

Behaviour and testing post-patch:

  • Only errors are printed in quiet mode, no dots, exit status is correct.
$ pkg_admin -q check; echo $?
/opt/pkg/lib/ruby/gems/3.1.0/doc/i18n-1.14.1/ri/I18n/Gettext/Helpers/N_-i.ri fails MD5 checksum
/opt/pkg/lib/ruby/gems/3.1.0/doc/em-websocket-0.5.3/ri/EventMachine/WebSocket/cdesc-WebSocket.ri fails MD5 checksum
/opt/pkg/lib/ruby/gems/3.1.0/doc/kramdown-2.4.0/ri/Kramdown/Converter/HashAST/cdesc-HashAST.ri fails MD5 checksum
/opt/pkg/lib/ruby/gems/3.1.0/doc/http_parser.rb-0.8.0/ri/HTTP/cdesc-HTTP.ri fails MD5 checksum
/opt/pkg/share/ri/3.1.0/system/Net/HTTPGatewayTimeOut/cdesc-HTTPGatewayTimeOut.ri fails MD5 checksum
/opt/pkg/share/ri/3.1.0/system/Net/HTTPRequestTimeOut/cdesc-HTTPRequestTimeOut.ri fails MD5 checksum
1

$ pkg_admin check ruby31-i18n-1.14.1; echo $?
/opt/pkg/lib/ruby/gems/3.1.0/doc/i18n-1.14.1/ri/I18n/Gettext/Helpers/N_-i.ri fails MD5 checksum
Checked 425 files from 1 package.
Done.
1
  • Patterns are correct for matches, non-matches, and non-existent packages:
$ pkg_admin check 'coreutils-[0-9]*'; echo $?
Checked 510 files from 1 package.
Done.
0

$ pkg_admin -q check coreutils; echo $?
0

$ pkg_admin check 'oreutils-[0-9]*'; echo $?
pkg_admin: No matching pkg for oreutils-[0-9]*.
1

$ pkg_admin check oreutils; echo $?
pkg_admin: cannot find package oreutils
1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment