1 /* $NetBSD: conflicts.c,v 1.1.1.4 2010/01/30 21:33:43 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * XXX: Reading the +CONTENTS files of all installed packages is 34 * rather slow. Since this check is necessary to avoid conflicting 35 * packages, it should not be removed. 36 * 37 * TODO: Put all the information that is currently in the +CONTENTS 38 * files into one large file or another database. 39 */ 40 41 #if HAVE_CONFIG_H 42 #include "config.h" 43 #endif 44 45 #include <nbcompat.h> 46 47 #if HAVE_SYS_CDEFS_H 48 #include <sys/cdefs.h> 49 #endif 50 51 __RCSID("$NetBSD: conflicts.c,v 1.1.1.4 2010/01/30 21:33:43 joerg Exp $"); 52 53 #if HAVE_ERR_H 54 #include <err.h> 55 #endif 56 57 #include "dewey.h" 58 #include "lib.h" 59 60 /** 61 * Data structure to keep the intermediate result of the conflict 62 * search. ''pkgname'' is the package in question. The first 63 * installed package that conflicts is filled into 64 * ''conflicting_pkgname''. The pattern that leads to the conflict is 65 * also filled in to help the user in deciding what to do with the 66 * conflict. 67 */ 68 struct package_conflict { 69 const char *pkgname; 70 const char *skip_pkgname; 71 char **conflicting_pkgname; 72 char **conflicting_pattern; 73 }; 74 75 static FILE * 76 fopen_contents(const char *pkgname, const char *mode) 77 { 78 char *fname; 79 FILE *f; 80 81 fname = pkgdb_pkg_file(pkgname, CONTENTS_FNAME); 82 f = fopen(fname, mode); 83 if (f == NULL) { 84 err(EXIT_FAILURE, "%s", fname); 85 /* NOTREACHED */ 86 } 87 free(fname); 88 return f; 89 } 90 91 92 static int 93 check_package_conflict(const char *pkgname, void *v) 94 { 95 struct package_conflict *conflict = v; 96 package_t pkg; 97 plist_t *p; 98 FILE *f; 99 int rv; 100 101 if (conflict->skip_pkgname != NULL && 102 strcmp(conflict->skip_pkgname, pkgname) == 0) 103 return 0; 104 105 rv = 0; 106 107 f = fopen_contents(pkgname, "r"); 108 read_plist(&pkg, f); 109 (void)fclose(f); 110 111 for (p = pkg.head; p; p = p->next) { 112 if (p->type != PLIST_PKGCFL) 113 continue; 114 115 if (pkg_match(p->name, conflict->pkgname) == 1) { 116 *(conflict->conflicting_pkgname) = xstrdup(pkgname); 117 *(conflict->conflicting_pattern) = xstrdup(p->name); 118 rv = 1 /* nonzero, stop iterating */; 119 break; 120 } 121 } 122 123 free_plist(&pkg); 124 return rv; 125 } 126 127 /** 128 * Checks if some installed package has a pkgcfl entry that matches 129 * PkgName. If such an entry is found, the package name is returned in 130 * inst_pkgname, the matching pattern in inst_pattern, and the function 131 * returns a non-zero value. Otherwise, zero is returned and the result 132 * variables are set to NULL. 133 */ 134 int 135 some_installed_package_conflicts_with(const char *pkgname, 136 const char *skip_pkgname, char **inst_pkgname, char **inst_pattern) 137 { 138 struct package_conflict cfl; 139 int rv; 140 141 cfl.pkgname = pkgname; 142 cfl.skip_pkgname = skip_pkgname; 143 *inst_pkgname = NULL; 144 *inst_pattern = NULL; 145 cfl.conflicting_pkgname = inst_pkgname; 146 cfl.conflicting_pattern = inst_pattern; 147 rv = iterate_pkg_db(check_package_conflict, &cfl); 148 if (rv == -1) { 149 errx(EXIT_FAILURE, "Couldn't read list of installed packages."); 150 /* NOTREACHED */ 151 } 152 return *inst_pkgname != NULL; 153 } 154 155 #if 0 156 int main(int argc, char **argv) 157 { 158 char *pkg, *patt; 159 160 if (some_installed_package_conflicts_with(argv[1], &pkg, &patt)) 161 printf("yes: package %s conflicts with %s, pattern %s\n", pkg, argv[1], patt); 162 else 163 printf("no\n"); 164 return 0; 165 } 166 #endif 167