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