show.c revision 96392
1/*
2 * FreeBSD install - a package for the installation and maintainance
3 * of non-core utilities.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * Jordan K. Hubbard
15 * 23 Aug 1993
16 *
17 * Various display routines for the info module.
18 *
19 */
20
21#include <sys/cdefs.h>
22__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/info/show.c 96392 2002-05-11 04:17:55Z alfred $");
23
24#include "lib.h"
25#include "info.h"
26#include <err.h>
27#include <stdlib.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <md5.h>
31
32void
33show_file(const char *title, const char *fname)
34{
35    FILE *fp;
36    char line[1024];
37    int n;
38
39    if (!Quiet)
40	printf("%s%s", InfoPrefix, title);
41    fp = fopen(fname, "r");
42    if (!fp)
43	printf("ERROR: show_file: Can't open '%s' for reading!\n", fname);
44    else {
45	while ((n = fread(line, 1, 1024, fp)) != 0)
46	    fwrite(line, 1, n, stdout);
47	fclose(fp);
48    }
49    printf("\n");	/* just in case */
50}
51
52void
53show_index(const char *title, const char *fname)
54{
55    FILE *fp;
56    char line[MAXINDEXSIZE+2];
57
58    if (!Quiet)
59        printf("%s%s", InfoPrefix, title);
60    fp = fopen(fname, "r");
61    if (!fp) {
62        warnx("show_file: can't open '%s' for reading", fname);
63        return;
64    }
65    if(fgets(line, MAXINDEXSIZE+1, fp)) {
66	if(line[MAXINDEXSIZE-1] != '\n')
67          line[MAXINDEXSIZE] = '\n';
68	line[MAXINDEXSIZE+1] = 0;
69	fputs(line, stdout);
70    }
71    fclose(fp);
72}
73
74/* Show a packing list item type.  If showall is TRUE, show all */
75void
76show_plist(const char *title, Package *plist, plist_t type, Boolean showall)
77{
78    PackingList p;
79    Boolean ign = FALSE;
80
81    if (!Quiet)
82	printf("%s%s", InfoPrefix, title);
83    p = plist->head;
84    while (p) {
85	if (p->type != type && showall != TRUE) {
86	    p = p->next;
87	    continue;
88	}
89	switch(p->type) {
90	case PLIST_FILE:
91	    if (ign) {
92		printf(Quiet ? "%s\n" : "File: %s (ignored)\n", p->name);
93		ign = FALSE;
94	    }
95	    else
96		printf(Quiet ? "%s\n" : "File: %s\n", p->name);
97	    break;
98
99	case PLIST_CWD:
100	    printf(Quiet ? "@cwd %s\n" : "\tCWD to %s\n", p->name);
101	    break;
102
103	case PLIST_SRC:
104	    printf(Quiet ? "@srcdir %s\n" : "\tSRCDIR to %s\n", p->name);
105	    break;
106
107	case PLIST_CMD:
108	    printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name);
109	    break;
110
111	case PLIST_UNEXEC:
112	    printf(Quiet ? "@unexec %s\n" : "\tUNEXEC '%s'\n", p->name);
113	    break;
114
115	case PLIST_CHMOD:
116	    printf(Quiet ? "@chmod %s\n" : "\tCHMOD to %s\n",
117		   p->name ? p->name : "(clear default)");
118	    break;
119
120	case PLIST_CHOWN:
121	    printf(Quiet ? "@chown %s\n" : "\tCHOWN to %s\n",
122		   p->name ? p->name : "(clear default)");
123	    break;
124
125	case PLIST_CHGRP:
126	    printf(Quiet ? "@chgrp %s\n" : "\tCHGRP to %s\n",
127		   p->name ? p->name : "(clear default)");
128	    break;
129
130	case PLIST_COMMENT:
131	    printf(Quiet ? "@comment %s\n" : "\tComment: %s\n", p->name);
132	    break;
133
134	case PLIST_IGNORE:
135	    ign = TRUE;
136	    break;
137
138	case PLIST_IGNORE_INST:
139	    printf(Quiet ? "@ignore_inst ??? doesn't belong here.\n" :
140		   "\tIgnore next file installation directive (doesn't belong)\n");
141	    ign = TRUE;
142	    break;
143
144	case PLIST_NAME:
145	    printf(Quiet ? "@name %s\n" : "\tPackage name: %s\n", p->name);
146	    break;
147
148	case PLIST_DISPLAY:
149	    printf(Quiet ? "@display %s\n" : "\tInstall message file: %s\n", p->name);
150	    break;
151
152	case PLIST_PKGDEP:
153	    printf(Quiet ? "@pkgdep %s\n" : "Dependency: %s\n", p->name);
154	    break;
155
156	case PLIST_DEPORIGIN:
157	    printf(Quiet ? "@comment DEPORIGIN:%s\n" :
158		"\tdependency origin: %s\n", p->name);
159	    break;
160
161	case PLIST_MTREE:
162	    printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name);
163	    break;
164
165	case PLIST_DIR_RM:
166	    printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name);
167	    break;
168
169	case PLIST_OPTION:
170	    printf(Quiet ? "@option %s\n" :
171		"\tOption \"%s\" controlling package installation behaviour\n",
172		p->name);
173	    break;
174
175	case PLIST_ORIGIN:
176	    printf(Quiet ? "@comment ORIGIN:%s\n" :
177		"\tPackage origin: %s\n", p->name);
178	    break;
179
180	default:
181	    cleanup(0);
182	    errx(2, "%s: unknown command type %d (%s)",
183		__func__, p->type, p->name);
184	    break;
185	}
186	p = p->next;
187    }
188}
189
190/* Show all files in the packing list (except ignored ones) */
191void
192show_files(const char *title, Package *plist)
193{
194    PackingList p;
195    Boolean ign = FALSE;
196    const char *dir = ".";
197
198    if (!Quiet)
199	printf("%s%s", InfoPrefix, title);
200    p = plist->head;
201    while (p) {
202	switch(p->type) {
203	case PLIST_FILE:
204	    if (!ign)
205		printf("%s/%s\n", dir, p->name);
206	    ign = FALSE;
207	    break;
208
209	case PLIST_CWD:
210	    dir = p->name;
211	    break;
212
213	case PLIST_IGNORE:
214	    ign = TRUE;
215	    break;
216
217        /* Silence GCC in the -Wall mode */
218	default:
219	    break;
220	}
221	p = p->next;
222    }
223}
224
225/* Calculate and show size of all installed package files (except ignored ones) */
226void
227show_size(const char *title, Package *plist)
228{
229    PackingList p;
230    Boolean ign = FALSE;
231    const char *dir = ".";
232    struct stat sb;
233    char tmp[FILENAME_MAX];
234    unsigned long size = 0;
235    long blksize;
236    int headerlen;
237    char *descr;
238
239    descr = getbsize(&headerlen, &blksize);
240    if (!Quiet)
241	printf("%s%s", InfoPrefix, title);
242    for (p = plist->head; p != NULL; p = p->next) {
243	switch (p->type) {
244	case PLIST_FILE:
245	    if (!ign) {
246		snprintf(tmp, FILENAME_MAX, "%s/%s", dir, p->name);
247		if (!lstat(tmp, &sb)) {
248		    size += sb.st_size;
249		    if (Verbose)
250			printf("%lu\t%s\n", (unsigned long) howmany(sb.st_size, blksize), tmp);
251		}
252	    }
253	    ign = FALSE;
254	    break;
255
256	case PLIST_CWD:
257	    dir = p->name;
258	    break;
259
260	case PLIST_IGNORE:
261	    ign = TRUE;
262	    break;
263
264	/* Silence GCC in the -Wall mode */
265	default:
266	    break;
267	}
268    }
269    if (!Quiet)
270	printf("%lu\t(%s)\n", howmany(size, blksize), descr);
271    else
272	printf("%lu\n", size);
273}
274
275/* Show files that don't match the recorded checksum */
276void
277show_cksum(const char *title, Package *plist)
278{
279    PackingList p;
280    const char *dir = ".";
281    char tmp[FILENAME_MAX];
282
283    if (!Quiet)
284	printf("%s%s", InfoPrefix, title);
285
286    for (p = plist->head; p != NULL; p = p->next)
287	if (p->type == PLIST_CWD)
288	    dir = p->name;
289	else if (p->type == PLIST_FILE) {
290	    snprintf(tmp, FILENAME_MAX, "%s/%s", dir, p->name);
291	    if (!fexists(tmp))
292		warnx("%s doesn't exist\n", tmp);
293	    else if (p->next && p->next->type == PLIST_COMMENT &&
294	             (strncmp(p->next->name, "MD5:", 4) == 0)) {
295		char *cp = NULL, buf[33];
296
297		/*
298		 * For packing lists whose version is 1.1 or greater, the md5
299		 * hash for a symlink is calculated on the string returned
300		 * by readlink().
301		 */
302		if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) {
303		    int len;
304		    char linkbuf[FILENAME_MAX];
305
306		    if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
307			cp = MD5Data((unsigned char *)linkbuf, len, buf);
308		} else if (isfile(tmp) || verscmp(plist, 1, 1) < 0)
309		    cp = MD5File(tmp, buf);
310
311		if (cp != NULL) {
312		    /* Mismatch? */
313		    if (strcmp(cp, p->next->name + 4))
314			printf("%s fails the original MD5 checksum\n", tmp);
315		    else if (Verbose)
316			printf("%s matched the original MD5 checksum\n", tmp);
317		}
318	    }
319	}
320}
321
322/* Show an "origin" path (usually category/portname) */
323void
324show_origin(const char *title, Package *plist)
325{
326
327    if (!Quiet)
328	printf("%s%s", InfoPrefix, title);
329    printf("%s\n", plist->origin != NULL ? plist->origin : "");
330}
331
332/* Show revision number of the packing list */
333void
334show_fmtrev(const char *title, Package *plist)
335{
336
337    if (!Quiet)
338	printf("%s%s", InfoPrefix, title);
339    printf("%d.%d\n", plist->fmtver_maj, plist->fmtver_mnr);
340}
341