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