xref: /minix3/external/bsd/pkg_install/dist/admin/check.c (revision a824f5a1008ee67499d167f8c48e64aae26960ca)
1*a824f5a1SJean-Baptiste Boric /*	$NetBSD: check.c,v 1.1.1.4 2010/01/30 21:33:23 joerg Exp $	*/
2*a824f5a1SJean-Baptiste Boric 
3*a824f5a1SJean-Baptiste Boric #if HAVE_CONFIG_H
4*a824f5a1SJean-Baptiste Boric #include "config.h"
5*a824f5a1SJean-Baptiste Boric #endif
6*a824f5a1SJean-Baptiste Boric #include <nbcompat.h>
7*a824f5a1SJean-Baptiste Boric #if HAVE_SYS_CDEFS_H
8*a824f5a1SJean-Baptiste Boric #include <sys/cdefs.h>
9*a824f5a1SJean-Baptiste Boric #endif
10*a824f5a1SJean-Baptiste Boric __RCSID("$NetBSD: check.c,v 1.1.1.4 2010/01/30 21:33:23 joerg Exp $");
11*a824f5a1SJean-Baptiste Boric 
12*a824f5a1SJean-Baptiste Boric /*-
13*a824f5a1SJean-Baptiste Boric  * Copyright (c) 1999-2008 The NetBSD Foundation, Inc.
14*a824f5a1SJean-Baptiste Boric  * All rights reserved.
15*a824f5a1SJean-Baptiste Boric  *
16*a824f5a1SJean-Baptiste Boric  * This code is derived from software contributed to The NetBSD Foundation
17*a824f5a1SJean-Baptiste Boric  * by Hubert Feyrer <hubert@feyrer.de>.
18*a824f5a1SJean-Baptiste Boric  *
19*a824f5a1SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or without
20*a824f5a1SJean-Baptiste Boric  * modification, are permitted provided that the following conditions
21*a824f5a1SJean-Baptiste Boric  * are met:
22*a824f5a1SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
23*a824f5a1SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
24*a824f5a1SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above copyright
25*a824f5a1SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer in the
26*a824f5a1SJean-Baptiste Boric  *    documentation and/or other materials provided with the distribution.
27*a824f5a1SJean-Baptiste Boric  *
28*a824f5a1SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29*a824f5a1SJean-Baptiste Boric  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30*a824f5a1SJean-Baptiste Boric  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31*a824f5a1SJean-Baptiste Boric  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32*a824f5a1SJean-Baptiste Boric  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33*a824f5a1SJean-Baptiste Boric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34*a824f5a1SJean-Baptiste Boric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35*a824f5a1SJean-Baptiste Boric  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36*a824f5a1SJean-Baptiste Boric  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37*a824f5a1SJean-Baptiste Boric  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38*a824f5a1SJean-Baptiste Boric  * POSSIBILITY OF SUCH DAMAGE.
39*a824f5a1SJean-Baptiste Boric  */
40*a824f5a1SJean-Baptiste Boric 
41*a824f5a1SJean-Baptiste Boric #if HAVE_SYS_TYPES_H
42*a824f5a1SJean-Baptiste Boric #include <sys/types.h>
43*a824f5a1SJean-Baptiste Boric #endif
44*a824f5a1SJean-Baptiste Boric #if HAVE_SYS_STAT_H
45*a824f5a1SJean-Baptiste Boric #include <sys/stat.h>
46*a824f5a1SJean-Baptiste Boric #endif
47*a824f5a1SJean-Baptiste Boric #if HAVE_DIRENT_H
48*a824f5a1SJean-Baptiste Boric #include <dirent.h>
49*a824f5a1SJean-Baptiste Boric #endif
50*a824f5a1SJean-Baptiste Boric #if HAVE_ERR_H
51*a824f5a1SJean-Baptiste Boric #include <err.h>
52*a824f5a1SJean-Baptiste Boric #endif
53*a824f5a1SJean-Baptiste Boric #if HAVE_ERRNO_H
54*a824f5a1SJean-Baptiste Boric #include <errno.h>
55*a824f5a1SJean-Baptiste Boric #endif
56*a824f5a1SJean-Baptiste Boric #if HAVE_FCNTL_H
57*a824f5a1SJean-Baptiste Boric #include <fcntl.h>
58*a824f5a1SJean-Baptiste Boric #endif
59*a824f5a1SJean-Baptiste Boric #ifndef NETBSD
60*a824f5a1SJean-Baptiste Boric #include <nbcompat/md5.h>
61*a824f5a1SJean-Baptiste Boric #else
62*a824f5a1SJean-Baptiste Boric #include <md5.h>
63*a824f5a1SJean-Baptiste Boric #endif
64*a824f5a1SJean-Baptiste Boric #if HAVE_LIMITS_H
65*a824f5a1SJean-Baptiste Boric #include <limits.h>
66*a824f5a1SJean-Baptiste Boric #endif
67*a824f5a1SJean-Baptiste Boric #if HAVE_STDIO_H
68*a824f5a1SJean-Baptiste Boric #include <stdio.h>
69*a824f5a1SJean-Baptiste Boric #endif
70*a824f5a1SJean-Baptiste Boric #if HAVE_STRING_H
71*a824f5a1SJean-Baptiste Boric #include <string.h>
72*a824f5a1SJean-Baptiste Boric #endif
73*a824f5a1SJean-Baptiste Boric 
74*a824f5a1SJean-Baptiste Boric #include "admin.h"
75*a824f5a1SJean-Baptiste Boric #include "lib.h"
76*a824f5a1SJean-Baptiste Boric 
77*a824f5a1SJean-Baptiste Boric static int checkpattern_fn(const char *, void *);
78*a824f5a1SJean-Baptiste Boric 
79*a824f5a1SJean-Baptiste Boric /*
80*a824f5a1SJean-Baptiste Boric  * Assumes CWD is in /var/db/pkg/<pkg>!
81*a824f5a1SJean-Baptiste Boric  */
82*a824f5a1SJean-Baptiste Boric static void
check1pkg(const char * pkgdir,int * filecnt,int * pkgcnt)83*a824f5a1SJean-Baptiste Boric check1pkg(const char *pkgdir, int *filecnt, int *pkgcnt)
84*a824f5a1SJean-Baptiste Boric {
85*a824f5a1SJean-Baptiste Boric 	FILE   *f;
86*a824f5a1SJean-Baptiste Boric 	plist_t *p;
87*a824f5a1SJean-Baptiste Boric 	package_t Plist;
88*a824f5a1SJean-Baptiste Boric 	char   *PkgName, *dirp = NULL, *md5file;
89*a824f5a1SJean-Baptiste Boric 	char    file[MaxPathSize];
90*a824f5a1SJean-Baptiste Boric 	char   *content;
91*a824f5a1SJean-Baptiste Boric 
92*a824f5a1SJean-Baptiste Boric 	content = pkgdb_pkg_file(pkgdir, CONTENTS_FNAME);
93*a824f5a1SJean-Baptiste Boric 	f = fopen(content, "r");
94*a824f5a1SJean-Baptiste Boric 	if (f == NULL)
95*a824f5a1SJean-Baptiste Boric 		err(EXIT_FAILURE, "can't open %s", content);
96*a824f5a1SJean-Baptiste Boric 	free(content);
97*a824f5a1SJean-Baptiste Boric 
98*a824f5a1SJean-Baptiste Boric 	read_plist(&Plist, f);
99*a824f5a1SJean-Baptiste Boric 	p = find_plist(&Plist, PLIST_NAME);
100*a824f5a1SJean-Baptiste Boric 	if (p == NULL)
101*a824f5a1SJean-Baptiste Boric 		errx(EXIT_FAILURE, "Package %s has no @name, aborting.",
102*a824f5a1SJean-Baptiste Boric 		    pkgdir);
103*a824f5a1SJean-Baptiste Boric 	PkgName = p->name;
104*a824f5a1SJean-Baptiste Boric 	for (p = Plist.head; p; p = p->next) {
105*a824f5a1SJean-Baptiste Boric 		switch (p->type) {
106*a824f5a1SJean-Baptiste Boric 		case PLIST_FILE:
107*a824f5a1SJean-Baptiste Boric 			if (dirp == NULL) {
108*a824f5a1SJean-Baptiste Boric 				warnx("dirp not initialized, please send-pr!");
109*a824f5a1SJean-Baptiste Boric 				abort();
110*a824f5a1SJean-Baptiste Boric 			}
111*a824f5a1SJean-Baptiste Boric 
112*a824f5a1SJean-Baptiste Boric 			(void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name);
113*a824f5a1SJean-Baptiste Boric 
114*a824f5a1SJean-Baptiste Boric 			if (isfile(file) || islinktodir(file)) {
115*a824f5a1SJean-Baptiste Boric 				if (p->next && p->next->type == PLIST_COMMENT) {
116*a824f5a1SJean-Baptiste Boric 					if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) {
117*a824f5a1SJean-Baptiste Boric 						if ((md5file = MD5File(file, NULL)) != NULL) {
118*a824f5a1SJean-Baptiste Boric 							/* Mismatch? */
119*a824f5a1SJean-Baptiste Boric 							if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0)
120*a824f5a1SJean-Baptiste Boric 								printf("%s fails MD5 checksum\n", file);
121*a824f5a1SJean-Baptiste Boric 
122*a824f5a1SJean-Baptiste Boric 							free(md5file);
123*a824f5a1SJean-Baptiste Boric 						}
124*a824f5a1SJean-Baptiste Boric 					} else if (strncmp(p->next->name, SYMLINK_HEADER, SymlinkHeaderLen) == 0) {
125*a824f5a1SJean-Baptiste Boric 						char	buf[MaxPathSize + SymlinkHeaderLen];
126*a824f5a1SJean-Baptiste Boric 						int	cc;
127*a824f5a1SJean-Baptiste Boric 
128*a824f5a1SJean-Baptiste Boric 						(void) strlcpy(buf, SYMLINK_HEADER, sizeof(buf));
129*a824f5a1SJean-Baptiste Boric 						if ((cc = readlink(file, &buf[SymlinkHeaderLen],
130*a824f5a1SJean-Baptiste Boric 							  sizeof(buf) - SymlinkHeaderLen - 1)) < 0) {
131*a824f5a1SJean-Baptiste Boric 							warnx("can't readlink `%s'", file);
132*a824f5a1SJean-Baptiste Boric 						} else {
133*a824f5a1SJean-Baptiste Boric 							buf[SymlinkHeaderLen + cc] = 0x0;
134*a824f5a1SJean-Baptiste Boric 							if (strcmp(buf, p->next->name) != 0) {
135*a824f5a1SJean-Baptiste Boric 								printf("symlink (%s) is not same as recorded value, %s: %s\n",
136*a824f5a1SJean-Baptiste Boric 								    file, buf, p->next->name);
137*a824f5a1SJean-Baptiste Boric 							}
138*a824f5a1SJean-Baptiste Boric 						}
139*a824f5a1SJean-Baptiste Boric 					}
140*a824f5a1SJean-Baptiste Boric 				}
141*a824f5a1SJean-Baptiste Boric 
142*a824f5a1SJean-Baptiste Boric 				(*filecnt)++;
143*a824f5a1SJean-Baptiste Boric 			} else if (isbrokenlink(file)) {
144*a824f5a1SJean-Baptiste Boric 				warnx("%s: Symlink `%s' exists and is in %s but target does not exist!", PkgName, file, CONTENTS_FNAME);
145*a824f5a1SJean-Baptiste Boric 			} else {
146*a824f5a1SJean-Baptiste Boric 				warnx("%s: File `%s' is in %s but not on filesystem!", PkgName, file, CONTENTS_FNAME);
147*a824f5a1SJean-Baptiste Boric 			}
148*a824f5a1SJean-Baptiste Boric 			break;
149*a824f5a1SJean-Baptiste Boric 		case PLIST_CWD:
150*a824f5a1SJean-Baptiste Boric 			if (strcmp(p->name, ".") != 0)
151*a824f5a1SJean-Baptiste Boric 				dirp = p->name;
152*a824f5a1SJean-Baptiste Boric 			else
153*a824f5a1SJean-Baptiste Boric 				dirp = pkgdb_pkg_dir(pkgdir);
154*a824f5a1SJean-Baptiste Boric 			break;
155*a824f5a1SJean-Baptiste Boric 		case PLIST_IGNORE:
156*a824f5a1SJean-Baptiste Boric 			p = p->next;
157*a824f5a1SJean-Baptiste Boric 			break;
158*a824f5a1SJean-Baptiste Boric 		case PLIST_SHOW_ALL:
159*a824f5a1SJean-Baptiste Boric 		case PLIST_SRC:
160*a824f5a1SJean-Baptiste Boric 		case PLIST_CMD:
161*a824f5a1SJean-Baptiste Boric 		case PLIST_CHMOD:
162*a824f5a1SJean-Baptiste Boric 		case PLIST_CHOWN:
163*a824f5a1SJean-Baptiste Boric 		case PLIST_CHGRP:
164*a824f5a1SJean-Baptiste Boric 		case PLIST_COMMENT:
165*a824f5a1SJean-Baptiste Boric 		case PLIST_NAME:
166*a824f5a1SJean-Baptiste Boric 		case PLIST_UNEXEC:
167*a824f5a1SJean-Baptiste Boric 		case PLIST_DISPLAY:
168*a824f5a1SJean-Baptiste Boric 		case PLIST_PKGDEP:
169*a824f5a1SJean-Baptiste Boric 		case PLIST_DIR_RM:
170*a824f5a1SJean-Baptiste Boric 		case PLIST_OPTION:
171*a824f5a1SJean-Baptiste Boric 		case PLIST_PKGCFL:
172*a824f5a1SJean-Baptiste Boric 		case PLIST_BLDDEP:
173*a824f5a1SJean-Baptiste Boric 		case PLIST_PKGDIR:
174*a824f5a1SJean-Baptiste Boric 			break;
175*a824f5a1SJean-Baptiste Boric 		}
176*a824f5a1SJean-Baptiste Boric 	}
177*a824f5a1SJean-Baptiste Boric 	free_plist(&Plist);
178*a824f5a1SJean-Baptiste Boric 	fclose(f);
179*a824f5a1SJean-Baptiste Boric 	(*pkgcnt)++;
180*a824f5a1SJean-Baptiste Boric }
181*a824f5a1SJean-Baptiste Boric 
182*a824f5a1SJean-Baptiste Boric struct checkpattern_arg {
183*a824f5a1SJean-Baptiste Boric 	int filecnt;
184*a824f5a1SJean-Baptiste Boric 	int pkgcnt;
185*a824f5a1SJean-Baptiste Boric 	int got_match;
186*a824f5a1SJean-Baptiste Boric };
187*a824f5a1SJean-Baptiste Boric 
188*a824f5a1SJean-Baptiste Boric static int
checkpattern_fn(const char * pkg,void * vp)189*a824f5a1SJean-Baptiste Boric checkpattern_fn(const char *pkg, void *vp)
190*a824f5a1SJean-Baptiste Boric {
191*a824f5a1SJean-Baptiste Boric 	struct checkpattern_arg *arg = vp;
192*a824f5a1SJean-Baptiste Boric 
193*a824f5a1SJean-Baptiste Boric 	check1pkg(pkg, &arg->filecnt, &arg->pkgcnt);
194*a824f5a1SJean-Baptiste Boric 	if (!quiet)
195*a824f5a1SJean-Baptiste Boric 		printf(".");
196*a824f5a1SJean-Baptiste Boric 
197*a824f5a1SJean-Baptiste Boric 	arg->got_match = 1;
198*a824f5a1SJean-Baptiste Boric 
199*a824f5a1SJean-Baptiste Boric 	return 0;
200*a824f5a1SJean-Baptiste Boric }
201*a824f5a1SJean-Baptiste Boric 
202*a824f5a1SJean-Baptiste Boric static void
check_pkg(const char * pkg,int * filecnt,int * pkgcnt,int allow_unmatched)203*a824f5a1SJean-Baptiste Boric check_pkg(const char *pkg, int *filecnt, int *pkgcnt, int allow_unmatched)
204*a824f5a1SJean-Baptiste Boric {
205*a824f5a1SJean-Baptiste Boric 	struct checkpattern_arg arg;
206*a824f5a1SJean-Baptiste Boric 	char *pattern;
207*a824f5a1SJean-Baptiste Boric 
208*a824f5a1SJean-Baptiste Boric 	arg.filecnt = *filecnt;
209*a824f5a1SJean-Baptiste Boric 	arg.pkgcnt = *pkgcnt;
210*a824f5a1SJean-Baptiste Boric 	arg.got_match = 0;
211*a824f5a1SJean-Baptiste Boric 
212*a824f5a1SJean-Baptiste Boric 	if (match_installed_pkgs(pkg, checkpattern_fn, &arg) == -1)
213*a824f5a1SJean-Baptiste Boric 		errx(EXIT_FAILURE, "Cannot process pkdbdb");
214*a824f5a1SJean-Baptiste Boric 	if (arg.got_match != 0) {
215*a824f5a1SJean-Baptiste Boric 		*filecnt = arg.filecnt;
216*a824f5a1SJean-Baptiste Boric 		*pkgcnt = arg.pkgcnt;
217*a824f5a1SJean-Baptiste Boric 		return;
218*a824f5a1SJean-Baptiste Boric 	}
219*a824f5a1SJean-Baptiste Boric 
220*a824f5a1SJean-Baptiste Boric 	if (ispkgpattern(pkg)) {
221*a824f5a1SJean-Baptiste Boric 		if (allow_unmatched)
222*a824f5a1SJean-Baptiste Boric 			return;
223*a824f5a1SJean-Baptiste Boric 		errx(EXIT_FAILURE, "No matching pkg for %s.", pkg);
224*a824f5a1SJean-Baptiste Boric 	}
225*a824f5a1SJean-Baptiste Boric 
226*a824f5a1SJean-Baptiste Boric 	pattern = xasprintf("%s-[0-9]*", pkg);
227*a824f5a1SJean-Baptiste Boric 
228*a824f5a1SJean-Baptiste Boric 	if (match_installed_pkgs(pattern, checkpattern_fn, &arg) == -1)
229*a824f5a1SJean-Baptiste Boric 		errx(EXIT_FAILURE, "Cannot process pkdbdb");
230*a824f5a1SJean-Baptiste Boric 
231*a824f5a1SJean-Baptiste Boric 	if (arg.got_match == 0)
232*a824f5a1SJean-Baptiste Boric 		errx(EXIT_FAILURE, "cannot find package %s", pkg);
233*a824f5a1SJean-Baptiste Boric 	free(pattern);
234*a824f5a1SJean-Baptiste Boric 
235*a824f5a1SJean-Baptiste Boric 	*filecnt = arg.filecnt;
236*a824f5a1SJean-Baptiste Boric 	*pkgcnt = arg.pkgcnt;
237*a824f5a1SJean-Baptiste Boric }
238*a824f5a1SJean-Baptiste Boric 
239*a824f5a1SJean-Baptiste Boric void
check(char ** argv)240*a824f5a1SJean-Baptiste Boric check(char **argv)
241*a824f5a1SJean-Baptiste Boric {
242*a824f5a1SJean-Baptiste Boric 	int filecnt, pkgcnt;
243*a824f5a1SJean-Baptiste Boric 
244*a824f5a1SJean-Baptiste Boric 	filecnt = 0;
245*a824f5a1SJean-Baptiste Boric 	pkgcnt = 0;
246*a824f5a1SJean-Baptiste Boric 	setbuf(stdout, NULL);
247*a824f5a1SJean-Baptiste Boric 
248*a824f5a1SJean-Baptiste Boric 	if (*argv == NULL) {
249*a824f5a1SJean-Baptiste Boric 		check_pkg("*", &filecnt, &pkgcnt, 1);
250*a824f5a1SJean-Baptiste Boric 	} else {
251*a824f5a1SJean-Baptiste Boric 		for (; *argv != NULL; ++argv)
252*a824f5a1SJean-Baptiste Boric 			check_pkg(*argv, &filecnt, &pkgcnt, 0);
253*a824f5a1SJean-Baptiste Boric 	}
254*a824f5a1SJean-Baptiste Boric 
255*a824f5a1SJean-Baptiste Boric 	printf("\n");
256*a824f5a1SJean-Baptiste Boric 	printf("Checked %d file%s from %d package%s.\n",
257*a824f5a1SJean-Baptiste Boric 	    filecnt, (filecnt == 1) ? "" : "s",
258*a824f5a1SJean-Baptiste Boric 	    pkgcnt, (pkgcnt == 1) ? "" : "s");
259*a824f5a1SJean-Baptiste Boric }
260