Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / pkg_install / info / show.c
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: src/usr.sbin/pkg_install/info/show.c,v 1.14.2.14 2003/06/09 16:59:43 lioux Exp $");
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
32 void
33 show_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
56 void
57 show_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 */
84 void
85 show_plist(const char *title, Package *plist, plist_t type, Boolean showall)
86 {
87     PackingList p;
88     Boolean ign = FALSE;
89
90     if (!Quiet)
91         printf("%s%s", InfoPrefix, title);
92     p = plist->head;
93     while (p) {
94         if (p->type != type && showall != TRUE) {
95             p = p->next;
96             continue;
97         }
98         switch(p->type) {
99         case PLIST_FILE:
100             if (ign) {
101                 printf(Quiet ? "%s\n" : "File: %s (ignored)\n", p->name);
102                 ign = FALSE;
103             }
104             else
105                 printf(Quiet ? "%s\n" : "File: %s\n", p->name);
106             break;
107
108         case PLIST_CWD:
109             printf(Quiet ? "@cwd %s\n" : "\tCWD to %s\n", p->name);
110             break;
111
112         case PLIST_SRC:
113             printf(Quiet ? "@srcdir %s\n" : "\tSRCDIR to %s\n", p->name);
114             break;
115
116         case PLIST_CMD:
117             printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name);
118             break;
119
120         case PLIST_UNEXEC:
121             printf(Quiet ? "@unexec %s\n" : "\tUNEXEC '%s'\n", p->name);
122             break;
123
124         case PLIST_CHMOD:
125             printf(Quiet ? "@chmod %s\n" : "\tCHMOD to %s\n",
126                    p->name ? p->name : "(clear default)");
127             break;
128
129         case PLIST_CHOWN:
130             printf(Quiet ? "@chown %s\n" : "\tCHOWN to %s\n",
131                    p->name ? p->name : "(clear default)");
132             break;
133
134         case PLIST_CHGRP:
135             printf(Quiet ? "@chgrp %s\n" : "\tCHGRP to %s\n",
136                    p->name ? p->name : "(clear default)");
137             break;
138
139         case PLIST_COMMENT:
140             printf(Quiet ? "@comment %s\n" : "\tComment: %s\n", p->name);
141             break;
142
143         case PLIST_IGNORE:
144             ign = TRUE;
145             break;
146
147         case PLIST_IGNORE_INST:
148             printf(Quiet ? "@ignore_inst ??? doesn't belong here.\n" :
149                    "\tIgnore next file installation directive (doesn't belong)\n");
150             ign = TRUE;
151             break;
152
153         case PLIST_NAME:
154             printf(Quiet ? "@name %s\n" : "\tPackage name: %s\n", p->name);
155             break;
156
157         case PLIST_DISPLAY:
158             printf(Quiet ? "@display %s\n" : "\tInstall message file: %s\n", p->name);
159             break;
160
161         case PLIST_PKGDEP:
162             printf(Quiet ? "@pkgdep %s\n" : "Dependency: %s\n", p->name);
163             break;
164
165         case PLIST_DEPORIGIN:
166             printf(Quiet ? "@comment DEPORIGIN:%s\n" :
167                 "\tdependency origin: %s\n", p->name);
168             break;
169
170         case PLIST_MTREE:
171             printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name);
172             break;
173
174         case PLIST_DIR_RM:
175             printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name);
176             break;
177
178         case PLIST_OPTION:
179             printf(Quiet ? "@option %s\n" :
180                 "\tOption \"%s\" controlling package installation behaviour\n",
181                 p->name);
182             break;
183
184         case PLIST_ORIGIN:
185             printf(Quiet ? "@comment ORIGIN:%s\n" :
186                 "\tPackage origin: %s\n", p->name); 
187             break;
188
189         default:
190             cleanup(0);
191             errx(2, "%s: unknown command type %d (%s)",
192                 __func__, p->type, p->name);
193             break;
194         }
195         p = p->next;
196     }
197 }
198
199 /* Show all files in the packing list (except ignored ones) */
200 void
201 show_files(const char *title, Package *plist)
202 {
203     PackingList p;
204     Boolean ign = FALSE;
205     const char *dir = ".";
206
207     if (!Quiet)
208         printf("%s%s", InfoPrefix, title);
209     p = plist->head;
210     while (p) {
211         switch(p->type) {
212         case PLIST_FILE:
213             if (!ign)
214                 printf("%s/%s\n", dir, p->name);
215             ign = FALSE;
216             break;
217
218         case PLIST_CWD:
219             dir = p->name;
220             break;
221
222         case PLIST_IGNORE:
223             ign = TRUE;
224             break;
225
226         /* Silence GCC in the -Wall mode */
227         default:
228             break;
229         }
230         p = p->next;
231     }
232 }
233
234 /* Calculate and show size of all installed package files (except ignored ones) */
235 void
236 show_size(const char *title, Package *plist)
237 {
238     PackingList p;
239     Boolean ign = FALSE;
240     const char *dir = ".";
241     struct stat sb;
242     char tmp[FILENAME_MAX];
243     unsigned long size = 0;
244     long blksize;
245     int headerlen;
246     char *descr;
247
248     descr = getbsize(&headerlen, &blksize);
249     if (!Quiet)
250         printf("%s%s", InfoPrefix, title);
251     for (p = plist->head; p != NULL; p = p->next) {
252         switch (p->type) {
253         case PLIST_FILE:
254             if (!ign) {
255                 snprintf(tmp, FILENAME_MAX, "%s/%s", dir, p->name);
256                 if (!lstat(tmp, &sb)) {
257                     size += sb.st_size;
258                     if (Verbose)
259                         printf("%lu\t%s\n", (unsigned long) howmany(sb.st_size, blksize), tmp);
260                 }
261             }
262             ign = FALSE;
263             break;
264
265         case PLIST_CWD:
266             dir = p->name;
267             break;
268
269         case PLIST_IGNORE:
270             ign = TRUE;
271             break;
272
273         /* Silence GCC in the -Wall mode */         
274         default:
275             break;
276         }
277     }
278     if (!Quiet)
279         printf("%lu\t(%s)\n", howmany(size, blksize), descr);
280     else
281         printf("%lu\n", size);
282 }
283
284 /* Show files that don't match the recorded checksum */
285 void
286 show_cksum(const char *title, Package *plist)
287 {
288     PackingList p;
289     const char *dir = ".";
290     char tmp[FILENAME_MAX];
291
292     if (!Quiet)
293         printf("%s%s", InfoPrefix, title);
294
295     for (p = plist->head; p != NULL; p = p->next)
296         if (p->type == PLIST_CWD) 
297             dir = p->name;
298         else if (p->type == PLIST_FILE) {
299             snprintf(tmp, FILENAME_MAX, "%s/%s", dir, p->name);
300             if (!fexists(tmp))
301                 warnx("%s doesn't exist\n", tmp);
302             else if (p->next && p->next->type == PLIST_COMMENT &&
303                      (strncmp(p->next->name, "MD5:", 4) == 0)) {
304                 char *cp = NULL, buf[33];
305
306                 /*
307                  * For packing lists whose version is 1.1 or greater, the md5
308                  * hash for a symlink is calculated on the string returned
309                  * by readlink().
310                  */
311                 if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) {
312                     int len;
313                     char linkbuf[FILENAME_MAX];
314
315                     if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
316                         cp = MD5Data((unsigned char *)linkbuf, len, buf);
317                 } else if (isfile(tmp) || verscmp(plist, 1, 1) < 0)
318                     cp = MD5File(tmp, buf);
319
320                 if (cp != NULL) {
321                     /* Mismatch? */
322                     if (strcmp(cp, p->next->name + 4))
323                         printf("%s fails the original MD5 checksum\n", tmp);
324                     else if (Verbose)
325                         printf("%s matched the original MD5 checksum\n", tmp);
326                 }
327             }
328         }
329 }
330
331 /* Show an "origin" path (usually category/portname) */
332 void
333 show_origin(const char *title, Package *plist)
334 {
335
336     if (!Quiet)
337         printf("%s%s", InfoPrefix, title);
338     printf("%s\n", plist->origin != NULL ? plist->origin : "");
339 }
340
341 /* Show revision number of the packing list */
342 void
343 show_fmtrev(const char *title, Package *plist)
344 {
345
346     if (!Quiet)
347         printf("%s%s", InfoPrefix, title);
348     printf("%d.%d\n", plist->fmtver_maj, plist->fmtver_mnr);
349 }