Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / pkg_install / dist / info / perform.c
blob5bda21d1c96ea83a2dee85649ff44818c2dc414a
1 /* $NetBSD: perform.c,v 1.59 2009/08/02 17:56:45 joerg Exp $ */
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.59 2009/08/02 17:56:45 joerg Exp $");
18 /*-
19 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
20 * All rights reserved.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
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.
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.
48 * FreeBSD install - a package for the installation and maintainance
49 * of non-core utilities.
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.
60 * Jordan K. Hubbard
61 * 23 Aug 1993
63 * This is the main body of the info module.
67 #include "lib.h"
68 #include "info.h"
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
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>
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)
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 },
156 static int desired_meta_data;
158 static void
159 free_pkg_meta(struct pkg_meta *meta)
161 const struct pkg_meta_desc *descr;
163 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr)
164 free(*(char **)((char *)meta + descr->entry_offset));
166 free(meta);
169 #ifndef BOOTSTRAP
170 static struct pkg_meta *
171 read_meta_data_from_archive(struct archive *archive,
172 struct archive_entry *entry)
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;
181 found_required = 0;
183 meta = xcalloc(1, sizeof(*meta));
185 last_descr = 0;
186 if (entry != NULL) {
187 r = ARCHIVE_OK;
188 goto has_entry;
191 while ((r = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) {
192 has_entry:
193 fname = archive_entry_pathname(entry);
195 for (descr = pkg_meta_descriptors; descr->entry_filename;
196 ++descr) {
197 if (strcmp(descr->entry_filename, fname) == 0)
198 break;
200 if (descr->entry_filename == NULL)
201 break;
203 if (descr->required_file)
204 ++found_required;
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;
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;
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';
229 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
230 if (descr->required_file)
231 --found_required;
234 meta->is_installed = 0;
235 if (found_required != 0 || (r != ARCHIVE_OK && r != ARCHIVE_EOF)) {
236 free_pkg_meta(meta);
237 meta = NULL;
240 return meta;
242 #endif
244 static struct pkg_meta *
245 read_meta_data_from_pkgdb(const char *pkg)
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;
254 meta = xcalloc(1, sizeof(*meta));
256 for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
257 if ((descr->entry_mask & desired_meta_data) == 0)
258 continue;
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);
269 target = (char **)((char *)meta + descr->entry_offset);
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);
284 meta->is_installed = 1;
286 return meta;
289 static void
290 build_full_reqby(lpkg_head_t *reqby, struct pkg_meta *meta, int limit)
292 char *iter, *eol, *next;
293 lpkg_t *lpp;
294 struct pkg_meta *meta_dep;
296 if (limit == 65536)
297 errx(1, "Cycle in the dependency tree, bailing out");
299 if (meta->is_installed == 0 || meta->meta_required_by == NULL)
300 return;
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;
316 if (lpp != NULL)
317 continue;
318 *eol = '\0';
319 lpp = alloc_lpkg(iter);
320 if (next != eol)
321 *eol = '\n';
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);
329 TAILQ_INSERT_HEAD(reqby, lpp, lp_link);
333 static lfile_head_t files;
335 static int
336 pkg_do(const char *pkg)
338 struct pkg_meta *meta;
339 char log_dir[MaxPathSize];
340 int code = 0;
341 const char *binpkgfile = NULL;
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 *pkgname;
351 archive = open_archive(pkg);
352 if (archive == NULL) {
353 warnx("can't find package `%s', skipped", pkg);
354 return -1;
356 pkgname = NULL;
357 entry = NULL;
358 pkg_verify_signature(&archive, &entry, &pkgname);
359 if (archive == NULL)
360 return -1;
361 free(pkgname);
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 {
370 * It's not an uninstalled package, try and find it among the
371 * installed
373 (void) snprintf(log_dir, sizeof(log_dir), "%s/%s",
374 _pkgdb_getPKGDB_DIR(), pkg);
375 if (!fexists(log_dir) || !(isdir(log_dir) || islinktodir(log_dir))) {
376 switch (add_installed_pkgs_by_basename(pkg, &pkgs)) {
377 case 1:
378 return 0;
379 case 0:
380 /* No match */
381 warnx("can't find package `%s'", pkg);
382 return 1;
383 case -1:
384 errx(EXIT_FAILURE, "Error during search in pkgdb for %s", pkg);
387 meta = read_meta_data_from_pkgdb(pkg);
390 if (meta == NULL) {
391 warnx("invalid package `%s' skipped", pkg);
392 return 1;
396 * Index is special info type that has to override all others to make
397 * any sense.
399 if (Flags & SHOW_INDEX) {
400 char tmp[MaxPathSize];
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");
415 } else {
416 package_t plist;
418 /* Read the contents list */
419 parse_plist(&plist, meta->meta_contents);
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");
428 if (Flags & SHOW_SUMMARY) {
429 show_summary(meta, &plist, binpkgfile);
431 if (Flags & SHOW_COMMENT) {
432 show_file(meta->meta_comment, "Comment:\n", TRUE);
434 if (Flags & SHOW_DEPENDS) {
435 show_depends("Requires:\n", &plist);
437 if (Flags & SHOW_BLD_DEPENDS) {
438 show_bld_depends("Built using:\n", &plist);
440 if ((Flags & SHOW_REQBY) && meta->meta_required_by) {
441 show_file(meta->meta_required_by, "Required by:\n", TRUE);
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");
449 if (Flags & SHOW_DESC) {
450 show_file(meta->meta_desc, "Description:\n", TRUE);
452 if ((Flags & SHOW_DISPLAY) && meta->meta_display) {
453 show_file(meta->meta_display, "Install notice:\n",
454 TRUE);
456 if (Flags & SHOW_PLIST) {
457 show_plist("Packing list:\n", &plist, PLIST_SHOW_ALL);
459 if ((Flags & SHOW_INSTALL) && meta->meta_install) {
460 show_file(meta->meta_install, "Install script:\n",
461 TRUE);
463 if ((Flags & SHOW_DEINSTALL) && meta->meta_deinstall) {
464 show_file(meta->meta_deinstall, "De-Install script:\n",
465 TRUE);
467 if ((Flags & SHOW_MTREE) && meta->meta_mtree) {
468 show_file(meta->meta_mtree, "mtree file:\n", TRUE);
470 if (Flags & SHOW_PREFIX) {
471 show_plist("Prefix(s):\n", &plist, PLIST_CWD);
473 if (Flags & SHOW_FILES) {
474 show_files("Files:\n", &plist);
476 if ((Flags & SHOW_BUILD_VERSION) && meta->meta_build_version) {
477 show_file(meta->meta_build_version, "Build version:\n",
478 TRUE);
480 if (Flags & SHOW_BUILD_INFO) {
481 if (meta->meta_build_info) {
482 show_file(meta->meta_build_info, "Build information:\n",
483 TRUE);
485 if (meta->meta_installed_info) {
486 show_file(meta->meta_installed_info, "Installed information:\n",
487 TRUE);
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);
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);
498 if (!Quiet && !(Flags & SHOW_SUMMARY)) {
499 if (meta->meta_preserve) {
500 printf("*** PACKAGE MAY NOT BE DELETED ***\n\n");
502 puts(InfoPrefix);
504 free_plist(&plist);
506 free_pkg_meta(meta);
507 return code;
510 struct print_matching_arg {
511 const char *pattern;
512 int got_match;
515 static int
516 print_matching_pkg(const char *pkgname, void *cookie)
518 struct print_matching_arg *arg= cookie;
520 if (pkg_match(arg->pattern, pkgname)) {
521 if (!Quiet)
522 puts(pkgname);
523 arg->got_match = 1;
526 return 0;
530 * Returns 0 if at least one package matching pkgname.
531 * Returns 1 otherwise.
533 * If -q was not specified, print all matching packages to stdout.
536 CheckForPkg(const char *pkgname)
538 struct print_matching_arg arg;
540 arg.pattern = pkgname;
541 arg.got_match = 0;
543 if (iterate_pkg_db(print_matching_pkg, &arg) == -1) {
544 warnx("cannot iterate pkgdb");
545 return 1;
548 if (arg.got_match == 0 && !ispkgpattern(pkgname)) {
549 char *pattern;
551 pattern = xasprintf("%s-[0-9]*", pkgname);
553 arg.pattern = pattern;
554 arg.got_match = 0;
556 if (iterate_pkg_db(print_matching_pkg, &arg) == -1) {
557 free(pattern);
558 warnx("cannot iterate pkgdb");
559 return 1;
561 free(pattern);
564 if (arg.got_match)
565 return 0;
566 else
567 return 1;
571 * Returns 0 if at least one package matching pkgname.
572 * Returns 1 otherwise.
574 * If -q was not specified, print best match to stdout.
577 CheckForBestPkg(const char *pkgname)
579 char *pattern, *best_match;
581 best_match = find_best_matching_installed_pkg(pkgname);
582 if (best_match == NULL) {
583 if (ispkgpattern(pkgname))
584 return 1;
586 pattern = xasprintf("%s-[0-9]*", pkgname);
587 best_match = find_best_matching_installed_pkg(pattern);
588 free(pattern);
591 if (best_match == NULL)
592 return 1;
593 if (!Quiet)
594 puts(best_match);
595 free(best_match);
596 return 0;
599 static int
600 perform_single_pkg(const char *pkg, void *cookie)
602 int *err_cnt = cookie;
604 if (Which == WHICH_ALL || !is_automatic_installed(pkg))
605 *err_cnt += pkg_do(pkg);
607 return 0;
611 pkg_perform(lpkg_head_t *pkghead)
613 int err_cnt = 0;
615 TAILQ_INIT(&files);
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;
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;
654 } else {
655 /* Show info on individual pkg(s) */
656 lpkg_t *lpp;
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);
664 return err_cnt;