1 /* $NetBSD: perform.c,v 1.59 2009/08/02 17:56:45 joerg Exp $ */
11 #include <sys/queue.h>
16 __RCSID("$NetBSD: perform.c,v 1.59 2009/08/02 17:56:45 joerg Exp $");
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
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
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
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
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.
63 * This is the main body of the info module.
71 #include <sys/types.h>
79 #include <archive_entry.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
{
119 const char *entry_filename
;
122 } pkg_meta_descriptors
[] = {
123 { offsetof(struct pkg_meta
, meta_contents
), CONTENTS_FNAME
,
125 { offsetof(struct pkg_meta
, meta_comment
), COMMENT_FNAME
,
127 { offsetof(struct pkg_meta
, meta_desc
), DESC_FNAME
,
129 { offsetof(struct pkg_meta
, meta_install
), INSTALL_FNAME
,
131 { offsetof(struct pkg_meta
, meta_deinstall
), DEINSTALL_FNAME
,
133 { offsetof(struct pkg_meta
, meta_display
), DISPLAY_FNAME
,
135 { offsetof(struct pkg_meta
, meta_mtree
), MTREE_FNAME
,
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
,
143 { offsetof(struct pkg_meta
, meta_size_all
), SIZE_ALL_FNAME
,
145 { offsetof(struct pkg_meta
, meta_preserve
), PRESERVE_FNAME
,
147 { offsetof(struct pkg_meta
, meta_views
), VIEWS_FNAME
,
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 },
156 static int desired_meta_data
;
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
));
170 static struct pkg_meta
*
171 read_meta_data_from_archive(struct archive
*archive
,
172 struct archive_entry
*entry
)
174 struct pkg_meta
*meta
;
176 const struct pkg_meta_desc
*descr
, *last_descr
;
179 int r
, found_required
;
183 meta
= xcalloc(1, sizeof(*meta
));
191 while ((r
= archive_read_next_header(archive
, &entry
)) == ARCHIVE_OK
) {
193 fname
= archive_entry_pathname(entry
);
195 for (descr
= pkg_meta_descriptors
; descr
->entry_filename
;
197 if (strcmp(descr
->entry_filename
, fname
) == 0)
200 if (descr
->entry_filename
== NULL
)
203 if (descr
->required_file
)
206 target
= (char **)((char *)meta
+ descr
->entry_offset
);
208 errx(2, "duplicate entry, package corrupt");
209 if (descr
< last_descr
)
210 warnx("misordered package, continuing");
214 if ((descr
->entry_mask
& desired_meta_data
) == 0) {
215 if (archive_read_data_skip(archive
))
216 errx(2, "cannot read package meta data");
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
)
234 meta
->is_installed
= 0;
235 if (found_required
!= 0 || (r
!= ARCHIVE_OK
&& r
!= ARCHIVE_EOF
)) {
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
;
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)
260 fname
= pkgdb_pkg_file(pkg
, descr
->entry_filename
);
261 fd
= open(fname
, O_RDONLY
, 0);
264 if (errno
== ENOENT
&& descr
->required_file
== 0)
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';
284 meta
->is_installed
= 1;
290 build_full_reqby(lpkg_head_t
*reqby
, struct pkg_meta
*meta
, int limit
)
292 char *iter
, *eol
, *next
;
294 struct pkg_meta
*meta_dep
;
297 errx(1, "Cycle in the dependency tree, bailing out");
299 if (meta
->is_installed
== 0 || meta
->meta_required_by
== NULL
)
302 for (iter
= meta
->meta_required_by
; *iter
!= '\0'; iter
= next
) {
303 eol
= iter
+ strcspn(iter
, "\n");
310 TAILQ_FOREACH(lpp
, reqby
, lp_link
) {
311 if (strlen(lpp
->lp_name
) + iter
!= eol
)
313 if (memcmp(lpp
->lp_name
, iter
, eol
- iter
) == 0)
319 lpp
= alloc_lpkg(iter
);
323 meta_dep
= read_meta_data_from_pkgdb(lpp
->lp_name
);
324 if (meta_dep
== NULL
)
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
;
336 pkg_do(const char *pkg
)
338 struct pkg_meta
*meta
;
339 char log_dir
[MaxPathSize
];
341 const char *binpkgfile
= NULL
;
343 if (IS_URL(pkg
) || (fexists(pkg
) && isfile(pkg
))) {
345 errx(2, "Binary packages not supported during bootstrap");
347 struct archive
*archive
;
348 struct archive_entry
*entry
;
351 archive
= open_archive(pkg
);
352 if (archive
== NULL
) {
353 warnx("can't find package `%s', skipped", pkg
);
358 pkg_verify_signature(&archive
, &entry
, &pkgname
);
363 meta
= read_meta_data_from_archive(archive
, entry
);
364 archive_read_finish(archive
);
370 * It's not an uninstalled package, try and find it among the
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
)) {
381 warnx("can't find package `%s'", pkg
);
384 errx(EXIT_FAILURE
, "Error during search in pkgdb for %s", pkg
);
387 meta
= read_meta_data_from_pkgdb(pkg
);
391 warnx("invalid package `%s' skipped", pkg
);
396 * Index is special info type that has to override all others to make
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
);
410 if (meta
->meta_build_info
)
411 show_var(meta
->meta_build_info
, BuildInfoVariable
);
413 warnx("Build information missing");
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
) {
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",
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",
463 if ((Flags
& SHOW_DEINSTALL
) && meta
->meta_deinstall
) {
464 show_file(meta
->meta_deinstall
, "De-Install script:\n",
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",
480 if (Flags
& SHOW_BUILD_INFO
) {
481 if (meta
->meta_build_info
) {
482 show_file(meta
->meta_build_info
, "Build information:\n",
485 if (meta
->meta_installed_info
) {
486 show_file(meta
->meta_installed_info
, "Installed information:\n",
490 if ((Flags
& SHOW_PKG_SIZE
) && meta
->meta_size_pkg
) {
491 show_file(meta
->meta_size_pkg
, "Size of this package in bytes: ",
494 if ((Flags
& SHOW_ALL_SIZE
) && meta
->meta_size_all
) {
495 show_file(meta
->meta_size_all
, "Size in bytes including required pkgs: ",
498 if (!Quiet
&& !(Flags
& SHOW_SUMMARY
)) {
499 if (meta
->meta_preserve
) {
500 printf("*** PACKAGE MAY NOT BE DELETED ***\n\n");
510 struct print_matching_arg
{
516 print_matching_pkg(const char *pkgname
, void *cookie
)
518 struct print_matching_arg
*arg
= cookie
;
520 if (pkg_match(arg
->pattern
, pkgname
)) {
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
;
543 if (iterate_pkg_db(print_matching_pkg
, &arg
) == -1) {
544 warnx("cannot iterate pkgdb");
548 if (arg
.got_match
== 0 && !ispkgpattern(pkgname
)) {
551 pattern
= xasprintf("%s-[0-9]*", pkgname
);
553 arg
.pattern
= pattern
;
556 if (iterate_pkg_db(print_matching_pkg
, &arg
) == -1) {
558 warnx("cannot iterate pkgdb");
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
))
586 pattern
= xasprintf("%s-[0-9]*", pkgname
);
587 best_match
= find_best_matching_installed_pkg(pattern
);
591 if (best_match
== NULL
)
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
);
611 pkg_perform(lpkg_head_t
*pkghead
)
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
) {
647 /* Show all files with the package they belong to */
648 if (pkgdb_dump() == -1)
651 if (iterate_pkg_db(perform_single_pkg
, &err_cnt
) == -1)
655 /* Show info on individual pkg(s) */
658 while ((lpp
= TAILQ_FIRST(pkghead
)) != NULL
) {
659 TAILQ_REMOVE(pkghead
, lpp
, lp_link
);
660 err_cnt
+= pkg_do(lpp
->lp_name
);