show.c revision 228990
1/* 2 * FreeBSD install - a package for the installation and maintenance 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 228990 2011-12-30 10:58:14Z uqs $"); 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 == (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 210static const char * 211elide_root(const char *dir) 212{ 213 if (strcmp(dir, "/") == 0) 214 return ""; 215 return dir; 216} 217 218/* Show all files in the packing list (except ignored ones) */ 219void 220show_files(const char *title, Package *plist) 221{ 222 PackingList p; 223 Boolean ign = FALSE; 224 char *prefix = NULL; 225 const char *dir = "."; 226 227 if (!Quiet) 228 printf("%s%s", InfoPrefix, title); 229 p = plist->head; 230 while (p) { 231 switch(p->type) { 232 case PLIST_FILE: 233 if (!ign) 234 printf("%s/%s\n", elide_root(dir), p->name); 235 ign = FALSE; 236 break; 237 238 case PLIST_CWD: 239 if (!prefix) 240 prefix = p->name; 241 if (p->name == NULL) 242 dir = prefix; 243 else 244 dir = p->name; 245 break; 246 247 case PLIST_IGNORE: 248 ign = TRUE; 249 break; 250 251 /* Silence GCC in the -Wall mode */ 252 default: 253 break; 254 } 255 p = p->next; 256 } 257} 258 259/* Calculate and show size of all installed package files (except ignored ones) */ 260void 261show_size(const char *title, Package *plist) 262{ 263 PackingList p; 264 Boolean ign = FALSE; 265 const char *dir = "."; 266 struct stat sb; 267 char tmp[FILENAME_MAX]; 268 unsigned long size = 0; 269 long blksize; 270 int headerlen; 271 char *descr; 272 char *prefix = NULL; 273 274 descr = getbsize(&headerlen, &blksize); 275 if (!Quiet) 276 printf("%s%s", InfoPrefix, title); 277 for (p = plist->head; p != NULL; p = p->next) { 278 switch (p->type) { 279 case PLIST_FILE: 280 if (!ign) { 281 snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name); 282 if (!lstat(tmp, &sb)) { 283 size += sb.st_size; 284 if (Verbose) 285 printf("%lu\t%s\n", (unsigned long) howmany(sb.st_size, blksize), tmp); 286 } 287 } 288 ign = FALSE; 289 break; 290 291 case PLIST_CWD: 292 if (!prefix) 293 prefix = p->name; 294 if (p->name == NULL) 295 dir = prefix; 296 else 297 dir = p->name; 298 break; 299 300 case PLIST_IGNORE: 301 ign = TRUE; 302 break; 303 304 /* Silence GCC in the -Wall mode */ 305 default: 306 break; 307 } 308 } 309 if (!Quiet) 310 printf("%lu\t(%s)\n", howmany(size, blksize), descr); 311 else 312 if (UseBlkSz) 313 printf("%lu\n", howmany(size, blksize)); 314 else 315 printf("%lu\n", size); 316} 317 318/* Show files that don't match the recorded checksum */ 319void 320show_cksum(const char *title, Package *plist) 321{ 322 PackingList p; 323 const char *dir = "."; 324 char *prefix = NULL; 325 char tmp[FILENAME_MAX]; 326 327 if (!Quiet) 328 printf("%s%s", InfoPrefix, title); 329 330 for (p = plist->head; p != NULL; p = p->next) 331 if (p->type == PLIST_CWD) { 332 if (!prefix) 333 prefix = p->name; 334 if (p->name == NULL) 335 dir = prefix; 336 else 337 dir = p->name; 338 } else if (p->type == PLIST_FILE) { 339 snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name); 340 if (!fexists(tmp)) 341 warnx("%s doesn't exist", tmp); 342 else if (p->next && p->next->type == PLIST_COMMENT && 343 (strncmp(p->next->name, "MD5:", 4) == 0)) { 344 char *cp = NULL, buf[33]; 345 346 /* 347 * For packing lists whose version is 1.1 or greater, the md5 348 * hash for a symlink is calculated on the string returned 349 * by readlink(). 350 */ 351 if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) { 352 int len; 353 char linkbuf[FILENAME_MAX]; 354 355 if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0) 356 cp = MD5Data((unsigned char *)linkbuf, len, buf); 357 } else if (isfile(tmp) || verscmp(plist, 1, 1) < 0) 358 cp = MD5File(tmp, buf); 359 360 if (cp != NULL) { 361 /* Mismatch? */ 362 if (strcmp(cp, p->next->name + 4)) 363 printf("%s fails the original MD5 checksum\n", tmp); 364 else if (Verbose) 365 printf("%s matched the original MD5 checksum\n", tmp); 366 } 367 } 368 } 369} 370 371/* Show an "origin" path (usually category/portname) */ 372void 373show_origin(const char *title, Package *plist) 374{ 375 376 if (!Quiet) 377 printf("%s%s", InfoPrefix, title); 378 printf("%s\n", plist->origin != NULL ? plist->origin : ""); 379} 380 381/* Show revision number of the packing list */ 382void 383show_fmtrev(const char *title, Package *plist) 384{ 385 386 if (!Quiet) 387 printf("%s%s", InfoPrefix, title); 388 printf("%d.%d\n", plist->fmtver_maj, plist->fmtver_mnr); 389} 390