1 /* $NetBSD: perform.c,v 1.1.1.13 2010/02/20 04:41:55 joerg Exp $ */ 2 3 #if HAVE_CONFIG_H 4 #include "config.h" 5 #endif 6 #include <nbcompat.h> 7 #if HAVE_SYS_CDEFS_H 8 #include <sys/cdefs.h> 9 #endif 10 #if HAVE_SYS_QUEUE_H 11 #include <sys/queue.h> 12 #endif 13 #if HAVE_SYS_WAIT_H 14 #include <sys/wait.h> 15 #endif 16 __RCSID("$NetBSD: perform.c,v 1.1.1.13 2010/02/20 04:41:55 joerg Exp $"); 17 18 /*- 19 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. 20 * All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in 30 * the documentation and/or other materials provided with the 31 * distribution. 32 * 33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 34 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 35 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 36 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 37 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 39 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 40 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 41 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 42 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 43 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 * SUCH DAMAGE. 45 */ 46 47 /* 48 * FreeBSD install - a package for the installation and maintainance 49 * of non-core utilities. 50 * 51 * Redistribution and use in source and binary forms, with or without 52 * modification, are permitted provided that the following conditions 53 * are met: 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 60 * Jordan K. Hubbard 61 * 23 Aug 1993 62 * 63 * This is the main body of the info module. 64 * 65 */ 66 67 #include "lib.h" 68 #include "info.h" 69 70 #if HAVE_SYS_TYPES_H 71 #include <sys/types.h> 72 #endif 73 #if HAVE_SYS_STAT_H 74 #include <sys/stat.h> 75 #endif 76 77 #ifndef BOOTSTRAP 78 #include <archive.h> 79 #include <archive_entry.h> 80 #endif 81 #if HAVE_ERR_H 82 #include <err.h> 83 #endif 84 #if HAVE_ERRNO_H 85 #include <errno.h> 86 #endif 87 #if HAVE_FCNTL_H 88 #include <fcntl.h> 89 #endif 90 #if HAVE_SIGNAL_H 91 #include <signal.h> 92 #endif 93 #if HAVE_DIRENT_H 94 #include <dirent.h> 95 #endif 96 #if HAVE_CTYPE_H 97 #include <ctype.h> 98 #endif 99 #include <stddef.h> 100 101 #define LOAD_CONTENTS (1 << 0) 102 #define LOAD_COMMENT (1 << 1) 103 #define LOAD_DESC (1 << 2) 104 #define LOAD_INSTALL (1 << 3) 105 #define LOAD_DEINSTALL (1 << 4) 106 #define LOAD_DISPLAY (1 << 5) 107 #define LOAD_MTREE (1 << 6) 108 #define LOAD_BUILD_VERSION (1 << 7) 109 #define LOAD_BUILD_INFO (1 << 8) 110 #define LOAD_SIZE_PKG (1 << 9) 111 #define LOAD_SIZE_ALL (1 << 10) 112 #define LOAD_PRESERVE (1 << 11) 113 #define LOAD_VIEWS (1 << 12) 114 #define LOAD_REQUIRED_BY (1 << 13) 115 #define LOAD_INSTALLED_INFO (1 << 14) 116 117 static const struct pkg_meta_desc { 118 size_t entry_offset; 119 const char *entry_filename; 120 int entry_mask; 121 int required_file; 122 } pkg_meta_descriptors[] = { 123 { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 124 LOAD_CONTENTS, 1}, 125 { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 126 LOAD_COMMENT, 1 }, 127 { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 128 LOAD_DESC, 1 }, 129 { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 130 LOAD_INSTALL, 0 }, 131 { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 132 LOAD_DEINSTALL, 0 }, 133 { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 134 LOAD_DISPLAY, 0 }, 135 { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 136 LOAD_MTREE, 0 }, 137 { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 138 LOAD_BUILD_VERSION, 0 }, 139 { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 140 LOAD_BUILD_INFO, 0 }, 141 { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 142 LOAD_SIZE_PKG, 0 }, 143 { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 144 LOAD_SIZE_ALL, 0 }, 145 { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 146 LOAD_PRESERVE, 0 }, 147 { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 148 LOAD_VIEWS, 0 }, 149 { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 150 LOAD_REQUIRED_BY, 0 }, 151 { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 152 LOAD_INSTALLED_INFO, 0 }, 153 { 0, NULL, 0, 0 }, 154 }; 155 156 static int desired_meta_data; 157 158 static void 159 free_pkg_meta(struct pkg_meta *meta) 160 { 161 const struct pkg_meta_desc *descr; 162 163 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) 164 free(*(char **)((char *)meta + descr->entry_offset)); 165 166 free(meta); 167 } 168 169 #ifndef BOOTSTRAP 170 static struct pkg_meta * 171 read_meta_data_from_archive(struct archive *archive, 172 struct archive_entry *entry) 173 { 174 struct pkg_meta *meta; 175 const char *fname; 176 const struct pkg_meta_desc *descr, *last_descr; 177 char **target; 178 int64_t size; 179 int r, found_required; 180 181 found_required = 0; 182 183 meta = xcalloc(1, sizeof(*meta)); 184 185 last_descr = 0; 186 if (entry != NULL) { 187 r = ARCHIVE_OK; 188 goto has_entry; 189 } 190 191 while ((r = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) { 192 has_entry: 193 fname = archive_entry_pathname(entry); 194 195 for (descr = pkg_meta_descriptors; descr->entry_filename; 196 ++descr) { 197 if (strcmp(descr->entry_filename, fname) == 0) 198 break; 199 } 200 if (descr->entry_filename == NULL) 201 break; 202 203 if (descr->required_file) 204 ++found_required; 205 206 target = (char **)((char *)meta + descr->entry_offset); 207 if (*target) 208 errx(2, "duplicate entry, package corrupt"); 209 if (descr < last_descr) 210 warnx("misordered package, continuing"); 211 else 212 last_descr = descr; 213 214 if ((descr->entry_mask & desired_meta_data) == 0) { 215 if (archive_read_data_skip(archive)) 216 errx(2, "cannot read package meta data"); 217 continue; 218 } 219 220 size = archive_entry_size(entry); 221 if (size > SSIZE_MAX - 1) 222 errx(2, "package meta data too large to process"); 223 *target = xmalloc(size + 1); 224 if (archive_read_data(archive, *target, size) != size) 225 errx(2, "cannot read package meta data"); 226 (*target)[size] = '\0'; 227 } 228 229 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { 230 if (descr->required_file) 231 --found_required; 232 } 233 234 meta->is_installed = 0; 235 if (found_required != 0 || (r != ARCHIVE_OK && r != ARCHIVE_EOF)) { 236 free_pkg_meta(meta); 237 meta = NULL; 238 } 239 240 return meta; 241 } 242 #endif 243 244 static struct pkg_meta * 245 read_meta_data_from_pkgdb(const char *pkg) 246 { 247 struct pkg_meta *meta; 248 const struct pkg_meta_desc *descr; 249 char **target; 250 char *fname; 251 int fd; 252 struct stat st; 253 254 meta = xcalloc(1, sizeof(*meta)); 255 256 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { 257 if ((descr->entry_mask & desired_meta_data) == 0) 258 continue; 259 260 fname = pkgdb_pkg_file(pkg, descr->entry_filename); 261 fd = open(fname, O_RDONLY, 0); 262 free(fname); 263 if (fd == -1) { 264 if (errno == ENOENT && descr->required_file == 0) 265 continue; 266 err(2, "cannot read meta data file %s of package %s", 267 descr->entry_filename, pkg); 268 } 269 target = (char **)((char *)meta + descr->entry_offset); 270 271 if (fstat(fd, &st) == -1) 272 err(2, "cannot stat meta data"); 273 if ((st.st_mode & S_IFMT) != S_IFREG) 274 errx(1, "meta data is not regular file"); 275 if (st.st_size > SSIZE_MAX - 1) 276 err(2, "meta data file too large to process"); 277 *target = xmalloc(st.st_size + 1); 278 if (read(fd, *target, st.st_size) != st.st_size) 279 err(2, "cannot read meta data"); 280 (*target)[st.st_size] = '\0'; 281 close(fd); 282 } 283 284 meta->is_installed = 1; 285 286 return meta; 287 } 288 289 static void 290 build_full_reqby(lpkg_head_t *reqby, struct pkg_meta *meta, int limit) 291 { 292 char *iter, *eol, *next; 293 lpkg_t *lpp; 294 struct pkg_meta *meta_dep; 295 296 if (limit == 65536) 297 errx(1, "Cycle in the dependency tree, bailing out"); 298 299 if (meta->is_installed == 0 || meta->meta_required_by == NULL) 300 return; 301 302 for (iter = meta->meta_required_by; *iter != '\0'; iter = next) { 303 eol = iter + strcspn(iter, "\n"); 304 if (*eol == '\n') 305 next = eol + 1; 306 else 307 next = eol; 308 if (iter == eol) 309 continue; 310 TAILQ_FOREACH(lpp, reqby, lp_link) { 311 if (strlen(lpp->lp_name) + iter != eol) 312 continue; 313 if (memcmp(lpp->lp_name, iter, eol - iter) == 0) 314 break; 315 } 316 if (lpp != NULL) 317 continue; 318 *eol = '\0'; 319 lpp = alloc_lpkg(iter); 320 if (next != eol) 321 *eol = '\n'; 322 323 meta_dep = read_meta_data_from_pkgdb(lpp->lp_name); 324 if (meta_dep == NULL) 325 continue; 326 build_full_reqby(reqby, meta_dep, limit + 1); 327 free_pkg_meta(meta_dep); 328 329 TAILQ_INSERT_HEAD(reqby, lpp, lp_link); 330 } 331 } 332 333 static lfile_head_t files; 334 335 static int 336 pkg_do(const char *pkg) 337 { 338 struct pkg_meta *meta; 339 int code = 0; 340 const char *binpkgfile = NULL; 341 char *pkgdir; 342 343 if (IS_URL(pkg) || (fexists(pkg) && isfile(pkg))) { 344 #ifdef BOOTSTRAP 345 errx(2, "Binary packages not supported during bootstrap"); 346 #else 347 struct archive *archive; 348 struct archive_entry *entry; 349 char *archive_name, *pkgname; 350 351 archive = open_archive(pkg, &archive_name); 352 if (archive == NULL) { 353 warnx("can't find package `%s', skipped", pkg); 354 return -1; 355 } 356 pkgname = NULL; 357 entry = NULL; 358 pkg_verify_signature(archive_name, &archive, &entry, &pkgname); 359 if (archive == NULL) 360 return -1; 361 free(pkgname); 362 363 meta = read_meta_data_from_archive(archive, entry); 364 archive_read_finish(archive); 365 if (!IS_URL(pkg)) 366 binpkgfile = pkg; 367 #endif 368 } else { 369 /* 370 * It's not an uninstalled package, try and find it among the 371 * installed 372 */ 373 pkgdir = pkgdb_pkg_dir(pkg); 374 if (!fexists(pkgdir) || !(isdir(pkgdir) || islinktodir(pkgdir))) { 375 switch (add_installed_pkgs_by_basename(pkg, &pkgs)) { 376 case 1: 377 return 0; 378 case 0: 379 /* No match */ 380 warnx("can't find package `%s'", pkg); 381 return 1; 382 case -1: 383 errx(EXIT_FAILURE, "Error during search in pkgdb for %s", pkg); 384 } 385 } 386 free(pkgdir); 387 meta = read_meta_data_from_pkgdb(pkg); 388 } 389 390 if (meta == NULL) { 391 warnx("invalid package `%s' skipped", pkg); 392 return 1; 393 } 394 395 /* 396 * Index is special info type that has to override all others to make 397 * any sense. 398 */ 399 if (Flags & SHOW_INDEX) { 400 char tmp[MaxPathSize]; 401 402 (void) snprintf(tmp, sizeof(tmp), "%-19s ", pkg); 403 show_index(meta->meta_comment, tmp); 404 } else if (Flags & SHOW_BI_VAR) { 405 if (strcspn(BuildInfoVariable, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") 406 == strlen(BuildInfoVariable)) { 407 if (meta->meta_installed_info) 408 show_var(meta->meta_installed_info, BuildInfoVariable); 409 } else { 410 if (meta->meta_build_info) 411 show_var(meta->meta_build_info, BuildInfoVariable); 412 else 413 warnx("Build information missing"); 414 } 415 } else { 416 package_t plist; 417 418 /* Read the contents list */ 419 parse_plist(&plist, meta->meta_contents); 420 421 /* Start showing the package contents */ 422 if (!Quiet && !(Flags & SHOW_SUMMARY)) { 423 printf("%sInformation for %s:\n\n", InfoPrefix, pkg); 424 if (meta->meta_preserve) { 425 printf("*** PACKAGE MAY NOT BE DELETED ***\n"); 426 } 427 } 428 if (Flags & SHOW_SUMMARY) { 429 show_summary(meta, &plist, binpkgfile); 430 } 431 if (Flags & SHOW_COMMENT) { 432 show_file(meta->meta_comment, "Comment:\n", TRUE); 433 } 434 if (Flags & SHOW_DEPENDS) { 435 show_depends("Requires:\n", &plist); 436 } 437 if (Flags & SHOW_BLD_DEPENDS) { 438 show_bld_depends("Built using:\n", &plist); 439 } 440 if ((Flags & SHOW_REQBY) && meta->meta_required_by) { 441 show_file(meta->meta_required_by, "Required by:\n", TRUE); 442 } 443 if ((Flags & SHOW_FULL_REQBY) && meta->is_installed) { 444 lpkg_head_t reqby; 445 TAILQ_INIT(&reqby); 446 build_full_reqby(&reqby, meta, 0); 447 show_list(&reqby, "Full required by list:\n"); 448 } 449 if (Flags & SHOW_DESC) { 450 show_file(meta->meta_desc, "Description:\n", TRUE); 451 } 452 if ((Flags & SHOW_DISPLAY) && meta->meta_display) { 453 show_file(meta->meta_display, "Install notice:\n", 454 TRUE); 455 } 456 if (Flags & SHOW_PLIST) { 457 show_plist("Packing list:\n", &plist, PLIST_SHOW_ALL); 458 } 459 if ((Flags & SHOW_INSTALL) && meta->meta_install) { 460 show_file(meta->meta_install, "Install script:\n", 461 TRUE); 462 } 463 if ((Flags & SHOW_DEINSTALL) && meta->meta_deinstall) { 464 show_file(meta->meta_deinstall, "De-Install script:\n", 465 TRUE); 466 } 467 if ((Flags & SHOW_MTREE) && meta->meta_mtree) { 468 show_file(meta->meta_mtree, "mtree file:\n", TRUE); 469 } 470 if (Flags & SHOW_PREFIX) { 471 show_plist("Prefix(s):\n", &plist, PLIST_CWD); 472 } 473 if (Flags & SHOW_FILES) { 474 show_files("Files:\n", &plist); 475 } 476 if ((Flags & SHOW_BUILD_VERSION) && meta->meta_build_version) { 477 show_file(meta->meta_build_version, "Build version:\n", 478 TRUE); 479 } 480 if (Flags & SHOW_BUILD_INFO) { 481 if (meta->meta_build_info) { 482 show_file(meta->meta_build_info, "Build information:\n", 483 TRUE); 484 } 485 if (meta->meta_installed_info) { 486 show_file(meta->meta_installed_info, "Installed information:\n", 487 TRUE); 488 } 489 } 490 if ((Flags & SHOW_PKG_SIZE) && meta->meta_size_pkg) { 491 show_file(meta->meta_size_pkg, "Size of this package in bytes: ", 492 TRUE); 493 } 494 if ((Flags & SHOW_ALL_SIZE) && meta->meta_size_all) { 495 show_file(meta->meta_size_all, "Size in bytes including required pkgs: ", 496 TRUE); 497 } 498 if (!Quiet && !(Flags & SHOW_SUMMARY)) { 499 if (meta->meta_preserve) { 500 printf("*** PACKAGE MAY NOT BE DELETED ***\n\n"); 501 } 502 puts(InfoPrefix); 503 } 504 free_plist(&plist); 505 } 506 free_pkg_meta(meta); 507 return code; 508 } 509 510 struct print_matching_arg { 511 const char *pattern; 512 int got_match; 513 }; 514 515 static int 516 print_matching_pkg(const char *pkgname, void *cookie) 517 { 518 struct print_matching_arg *arg= cookie; 519 520 if (pkg_match(arg->pattern, pkgname)) { 521 if (!Quiet) 522 puts(pkgname); 523 arg->got_match = 1; 524 } 525 526 return 0; 527 } 528 529 /* 530 * Returns 0 if at least one package matching pkgname. 531 * Returns 1 otherwise. 532 * 533 * If -q was not specified, print all matching packages to stdout. 534 */ 535 int 536 CheckForPkg(const char *pkgname) 537 { 538 struct print_matching_arg arg; 539 540 arg.pattern = pkgname; 541 arg.got_match = 0; 542 543 if (iterate_pkg_db(print_matching_pkg, &arg) == -1) { 544 warnx("cannot iterate pkgdb"); 545 return 1; 546 } 547 548 if (arg.got_match == 0 && !ispkgpattern(pkgname)) { 549 char *pattern; 550 551 pattern = xasprintf("%s-[0-9]*", pkgname); 552 553 arg.pattern = pattern; 554 arg.got_match = 0; 555 556 if (iterate_pkg_db(print_matching_pkg, &arg) == -1) { 557 free(pattern); 558 warnx("cannot iterate pkgdb"); 559 return 1; 560 } 561 free(pattern); 562 } 563 564 if (arg.got_match) 565 return 0; 566 else 567 return 1; 568 } 569 570 /* 571 * Returns 0 if at least one package matching pkgname. 572 * Returns 1 otherwise. 573 * 574 * If -q was not specified, print best match to stdout. 575 */ 576 int 577 CheckForBestPkg(const char *pkgname) 578 { 579 char *pattern, *best_match; 580 581 best_match = find_best_matching_installed_pkg(pkgname); 582 if (best_match == NULL) { 583 if (ispkgpattern(pkgname)) 584 return 1; 585 586 pattern = xasprintf("%s-[0-9]*", pkgname); 587 best_match = find_best_matching_installed_pkg(pattern); 588 free(pattern); 589 } 590 591 if (best_match == NULL) 592 return 1; 593 if (!Quiet) 594 puts(best_match); 595 free(best_match); 596 return 0; 597 } 598 599 static int 600 perform_single_pkg(const char *pkg, void *cookie) 601 { 602 int *err_cnt = cookie; 603 604 if (Which == WHICH_ALL || !is_automatic_installed(pkg)) 605 *err_cnt += pkg_do(pkg); 606 607 return 0; 608 } 609 610 int 611 pkg_perform(lpkg_head_t *pkghead) 612 { 613 int err_cnt = 0; 614 615 TAILQ_INIT(&files); 616 617 desired_meta_data = 0; 618 if ((Flags & (SHOW_INDEX | SHOW_BI_VAR)) == 0) 619 desired_meta_data |= LOAD_PRESERVE; 620 if ((Flags & (SHOW_INDEX | SHOW_BI_VAR)) == 0) 621 desired_meta_data |= LOAD_CONTENTS; 622 if (Flags & (SHOW_COMMENT | SHOW_INDEX | SHOW_SUMMARY)) 623 desired_meta_data |= LOAD_COMMENT; 624 if (Flags & (SHOW_BI_VAR | SHOW_BUILD_INFO | SHOW_SUMMARY)) 625 desired_meta_data |= LOAD_BUILD_INFO | LOAD_INSTALLED_INFO; 626 if (Flags & (SHOW_SUMMARY | SHOW_PKG_SIZE)) 627 desired_meta_data |= LOAD_SIZE_PKG; 628 if (Flags & SHOW_ALL_SIZE) 629 desired_meta_data |= LOAD_SIZE_ALL; 630 if (Flags & (SHOW_SUMMARY | SHOW_DESC)) 631 desired_meta_data |= LOAD_DESC; 632 if (Flags & (SHOW_REQBY | SHOW_FULL_REQBY)) 633 desired_meta_data |= LOAD_REQUIRED_BY; 634 if (Flags & SHOW_DISPLAY) 635 desired_meta_data |= LOAD_DISPLAY; 636 if (Flags & SHOW_INSTALL) 637 desired_meta_data |= LOAD_INSTALL; 638 if (Flags & SHOW_DEINSTALL) 639 desired_meta_data |= LOAD_DEINSTALL; 640 if (Flags & SHOW_MTREE) 641 desired_meta_data |= LOAD_MTREE; 642 if (Flags & SHOW_BUILD_VERSION) 643 desired_meta_data |= LOAD_BUILD_VERSION; 644 645 if (Which != WHICH_LIST) { 646 if (File2Pkg) { 647 /* Show all files with the package they belong to */ 648 if (pkgdb_dump() == -1) 649 err_cnt = 1; 650 } else { 651 if (iterate_pkg_db(perform_single_pkg, &err_cnt) == -1) 652 err_cnt = 1; 653 } 654 } else { 655 /* Show info on individual pkg(s) */ 656 lpkg_t *lpp; 657 658 while ((lpp = TAILQ_FIRST(pkghead)) != NULL) { 659 TAILQ_REMOVE(pkghead, lpp, lp_link); 660 err_cnt += pkg_do(lpp->lp_name); 661 free_lpkg(lpp); 662 } 663 } 664 return err_cnt; 665 } 666