show.c revision 207113
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 207113 2010-04-23 11:07:43Z flz $");
23
24#include <pkg.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 == (FILE *) NULL)
43	printf("ERROR: show_file: Can't open '%s' for reading!\n", fname);
44    else {
45	int append_nl = 0;
46	while ((n = fread(line, 1, 1024, fp)) != 0)
47	    fwrite(line, 1, n, stdout);
48	fclose(fp);
49	append_nl = (line[n - 1] != '\n');	/* Do we have a trailing \n ? */
50	if (append_nl)
51	   printf("\n");
52    }
53    printf("\n");	/* just in case */
54}
55
56void
57show_index(const char *title, const char *fname)
58{
59    FILE *fp;
60    char line[MAXINDEXSIZE+2];
61
62    strlcpy(line, "???\n", sizeof(line));
63
64    if (!Quiet)
65        printf("%s%s", InfoPrefix, title);
66    fp = fopen(fname, "r");
67    if (fp == (FILE *) NULL) {
68        warnx("show_file: can't open '%s' for reading", fname);
69    } else {
70    	if(fgets(line, MAXINDEXSIZE + 1, fp)) {
71		size_t line_length = strlen(line);
72
73		if (line[line_length - 1] != '\n') {	/* Do we have a trailing \n ? */
74			line[line_length] = '\n';	/* Add a trailing \n */
75			line[line_length + 1] = '\0';	/* Terminate string */
76		}
77	}
78	fclose(fp);
79    }
80    fputs(line, stdout);
81}
82
83/* Show a packing list item type.  If showall is TRUE, show all */
84void
85show_plist(const char *title, Package *plist, plist_t type, Boolean showall)
86{
87    PackingList p;
88    Boolean ign = FALSE;
89    char *prefix = NULL;
90
91    if (!Quiet)
92	printf("%s%s", InfoPrefix, title);
93    p = plist->head;
94    while (p) {
95	if (p->type != type && showall != TRUE) {
96	    p = p->next;
97	    continue;
98	}
99	switch(p->type) {
100	case PLIST_FILE:
101	    if (ign) {
102		printf(Quiet ? "%s\n" : "File: %s (ignored)\n", p->name);
103		ign = FALSE;
104	    }
105	    else
106		printf(Quiet ? "%s\n" : "File: %s\n", p->name);
107	    break;
108
109	case PLIST_CWD:
110	    if (!prefix)
111		prefix = p->name;
112	    printf(Quiet ? "@cwd %s\n" : "\tCWD to %s\n", (p->name == NULL) ? prefix : p->name);
113	    break;
114
115	case PLIST_SRC:
116	    printf(Quiet ? "@srcdir %s\n" : "\tSRCDIR to %s\n", p->name);
117	    break;
118
119	case PLIST_CMD:
120	    printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name);
121	    break;
122
123	case PLIST_UNEXEC:
124	    printf(Quiet ? "@unexec %s\n" : "\tUNEXEC '%s'\n", p->name);
125	    break;
126
127	case PLIST_CHMOD:
128	    printf(Quiet ? "@chmod %s\n" : "\tCHMOD to %s\n",
129		   p->name ? p->name : "(clear default)");
130	    break;
131
132	case PLIST_CHOWN:
133	    printf(Quiet ? "@chown %s\n" : "\tCHOWN to %s\n",
134		   p->name ? p->name : "(clear default)");
135	    break;
136
137	case PLIST_CHGRP:
138	    printf(Quiet ? "@chgrp %s\n" : "\tCHGRP to %s\n",
139		   p->name ? p->name : "(clear default)");
140	    break;
141
142	case PLIST_COMMENT:
143	    printf(Quiet ? "@comment %s\n" : "\tComment: %s\n", p->name);
144	    break;
145
146	case PLIST_NOINST:
147	    printf(Quiet ? "@noinst %s\n" : "\tNot installed: %s\n", p->name);
148	    break;
149
150	case PLIST_IGNORE:
151	    ign = TRUE;
152	    break;
153
154	case PLIST_IGNORE_INST:
155	    printf(Quiet ? "@ignore_inst ??? doesn't belong here.\n" :
156		   "\tIgnore next file installation directive (doesn't belong)\n");
157	    ign = TRUE;
158	    break;
159
160	case PLIST_NAME:
161	    printf(Quiet ? "@name %s\n" : "\tPackage name: %s\n", p->name);
162	    break;
163
164	case PLIST_DISPLAY:
165	    printf(Quiet ? "@display %s\n" : "\tInstall message file: %s\n", p->name);
166	    break;
167
168	case PLIST_PKGDEP:
169	    printf(Quiet ? "@pkgdep %s\n" : "Dependency: %s\n", p->name);
170	    break;
171
172	case PLIST_DEPORIGIN:
173	    printf(Quiet ? "@comment DEPORIGIN:%s\n" :
174		"\tdependency origin: %s\n", p->name);
175	    break;
176
177	case PLIST_CONFLICTS:
178	    printf(Quiet ? "@conflicts %s\n" : "Conflicts: %s\n", p->name);
179	    break;
180
181	case PLIST_MTREE:
182	    printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name);
183	    break;
184
185	case PLIST_DIR_RM:
186	    printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name);
187	    break;
188
189	case PLIST_OPTION:
190	    printf(Quiet ? "@option %s\n" :
191		"\tOption \"%s\" controlling package installation behaviour\n",
192		p->name);
193	    break;
194
195	case PLIST_ORIGIN:
196	    printf(Quiet ? "@comment ORIGIN:%s\n" :
197		"\tPackage origin: %s\n", p->name);
198	    break;
199
200	default:
201	    cleanup(0);
202	    errx(2, "%s: unknown command type %d (%s)",
203		__func__, p->type, p->name);
204	    break;
205	}
206	p = p->next;
207    }
208}
209
210/* Show all files in the packing list (except ignored ones) */
211void
212show_files(const char *title, Package *plist)
213{
214    PackingList p;
215    Boolean ign = FALSE;
216    char *prefix = NULL;
217    const char *dir = ".";
218
219    if (!Quiet)
220	printf("%s%s", InfoPrefix, title);
221    p = plist->head;
222    while (p) {
223	switch(p->type) {
224	case PLIST_FILE:
225	    if (!ign)
226		printf("%s/%s\n", dir, p->name);
227	    ign = FALSE;
228	    break;
229
230	case PLIST_CWD:
231	    if (!prefix)
232		prefix = p->name;
233	    if (p->name == NULL)
234		dir = prefix;
235	    else
236		dir = p->name;
237	    break;
238
239	case PLIST_IGNORE:
240	    ign = TRUE;
241	    break;
242
243        /* Silence GCC in the -Wall mode */
244	default:
245	    break;
246	}
247	p = p->next;
248    }
249}
250
251/* Calculate and show size of all installed package files (except ignored ones) */
252void
253show_size(const char *title, Package *plist)
254{
255    PackingList p;
256    Boolean ign = FALSE;
257    const char *dir = ".";
258    struct stat sb;
259    char tmp[FILENAME_MAX];
260    unsigned long size = 0;
261    long blksize;
262    int headerlen;
263    char *descr;
264    char *prefix = NULL;
265
266    descr = getbsize(&headerlen, &blksize);
267    if (!Quiet)
268	printf("%s%s", InfoPrefix, title);
269    for (p = plist->head; p != NULL; p = p->next) {
270	switch (p->type) {
271	case PLIST_FILE:
272	    if (!ign) {
273		snprintf(tmp, FILENAME_MAX, "%s/%s", dir, p->name);
274		if (!lstat(tmp, &sb)) {
275		    size += sb.st_size;
276		    if (Verbose)
277			printf("%lu\t%s\n", (unsigned long) howmany(sb.st_size, blksize), tmp);
278		}
279	    }
280	    ign = FALSE;
281	    break;
282
283	case PLIST_CWD:
284	    if (!prefix)
285		prefix = p->name;
286	    if (p->name == NULL)
287		dir = prefix;
288	    else
289		dir = p->name;
290	    break;
291
292	case PLIST_IGNORE:
293	    ign = TRUE;
294	    break;
295
296	/* Silence GCC in the -Wall mode */
297	default:
298	    break;
299	}
300    }
301    if (!Quiet)
302	printf("%lu\t(%s)\n", howmany(size, blksize), descr);
303    else
304	if (UseBlkSz)
305		printf("%lu\n", howmany(size, blksize));
306	else
307		printf("%lu\n", size);
308}
309
310/* Show files that don't match the recorded checksum */
311void
312show_cksum(const char *title, Package *plist)
313{
314    PackingList p;
315    const char *dir = ".";
316    char *prefix = NULL;
317    char tmp[FILENAME_MAX];
318
319    if (!Quiet)
320	printf("%s%s", InfoPrefix, title);
321
322    for (p = plist->head; p != NULL; p = p->next)
323	if (p->type == PLIST_CWD) {
324	    if (!prefix)
325		prefix = p->name;
326	    if (p->name == NULL)
327		dir = prefix;
328	    else
329		dir = p->name;
330	} else if (p->type == PLIST_FILE) {
331	    snprintf(tmp, FILENAME_MAX, "%s/%s", dir, p->name);
332	    if (!fexists(tmp))
333		warnx("%s doesn't exist", tmp);
334	    else if (p->next && p->next->type == PLIST_COMMENT &&
335	             (strncmp(p->next->name, "MD5:", 4) == 0)) {
336		char *cp = NULL, buf[33];
337
338		/*
339		 * For packing lists whose version is 1.1 or greater, the md5
340		 * hash for a symlink is calculated on the string returned
341		 * by readlink().
342		 */
343		if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) {
344		    int len;
345		    char linkbuf[FILENAME_MAX];
346
347		    if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
348			cp = MD5Data((unsigned char *)linkbuf, len, buf);
349		} else if (isfile(tmp) || verscmp(plist, 1, 1) < 0)
350		    cp = MD5File(tmp, buf);
351
352		if (cp != NULL) {
353		    /* Mismatch? */
354		    if (strcmp(cp, p->next->name + 4))
355			printf("%s fails the original MD5 checksum\n", tmp);
356		    else if (Verbose)
357			printf("%s matched the original MD5 checksum\n", tmp);
358		}
359	    }
360	}
361}
362
363/* Show an "origin" path (usually category/portname) */
364void
365show_origin(const char *title, Package *plist)
366{
367
368    if (!Quiet)
369	printf("%s%s", InfoPrefix, title);
370    printf("%s\n", plist->origin != NULL ? plist->origin : "");
371}
372
373/* Show revision number of the packing list */
374void
375show_fmtrev(const char *title, Package *plist)
376{
377
378    if (!Quiet)
379	printf("%s%s", InfoPrefix, title);
380    printf("%d.%d\n", plist->fmtver_maj, plist->fmtver_mnr);
381}
382