summaryrefslogtreecommitdiff
path: root/pkgtools
diff options
context:
space:
mode:
authorrillig <rillig@pkgsrc.org>2007-11-30 00:30:39 +0000
committerrillig <rillig@pkgsrc.org>2007-11-30 00:30:39 +0000
commitbae1429f341ffb49c4f2f7c728979375da227189 (patch)
treecd557dc1bdb1b8554ddf57ab9d36b10d843a926f /pkgtools
parentb161625cc51ba3defd88d8d7f11784da25faf22a (diff)
downloadpkgsrc-bae1429f341ffb49c4f2f7c728979375da227189.tar.gz
Do not install a package if some of the installed packages would
conflict with it. This fixes PR 37451.
Diffstat (limited to 'pkgtools')
-rw-r--r--pkgtools/pkg_install/files/add/perform.c17
-rw-r--r--pkgtools/pkg_install/files/lib/Makefile.in4
-rw-r--r--pkgtools/pkg_install/files/lib/conflicts.c116
-rw-r--r--pkgtools/pkg_install/files/lib/lib.h6
4 files changed, 138 insertions, 5 deletions
diff --git a/pkgtools/pkg_install/files/add/perform.c b/pkgtools/pkg_install/files/add/perform.c
index a514ce710f8..ac1867955d0 100644
--- a/pkgtools/pkg_install/files/add/perform.c
+++ b/pkgtools/pkg_install/files/add/perform.c
@@ -1,4 +1,4 @@
-/* $NetBSD: perform.c,v 1.67 2007/11/13 19:53:11 rillig Exp $ */
+/* $NetBSD: perform.c,v 1.68 2007/11/30 00:30:39 rillig Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -14,7 +14,7 @@
#if 0
static const char *rcsid = "from FreeBSD Id: perform.c,v 1.44 1997/10/13 15:03:46 jkh Exp";
#else
-__RCSID("$NetBSD: perform.c,v 1.67 2007/11/13 19:53:11 rillig Exp $");
+__RCSID("$NetBSD: perform.c,v 1.68 2007/11/30 00:30:39 rillig Exp $");
#endif
#endif
@@ -670,6 +670,19 @@ pkg_do(const char *pkg, lpkg_head_t *pkgs)
}
}
+ /* See if any of the installed packages conflicts with this one. */
+ {
+ char *inst_pkgname, *inst_pattern;
+
+ if (some_installed_package_conflicts_with(PkgName, &inst_pkgname, &inst_pattern)) {
+ warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.",
+ inst_pkgname, inst_pattern, PkgName);
+ free(inst_pkgname);
+ free(inst_pattern);
+ errc++;
+ }
+ }
+
/* Quick pre-check if any conflicting dependencies are installed
* (e.g. version X is installed, but version Y is required)
*/
diff --git a/pkgtools/pkg_install/files/lib/Makefile.in b/pkgtools/pkg_install/files/lib/Makefile.in
index 173be0d7407..4474e69b5ab 100644
--- a/pkgtools/pkg_install/files/lib/Makefile.in
+++ b/pkgtools/pkg_install/files/lib/Makefile.in
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.in,v 1.16 2007/08/08 22:33:39 joerg Exp $
+# $NetBSD: Makefile.in,v 1.17 2007/11/30 00:30:40 rillig Exp $
srcdir= @srcdir@
@@ -24,7 +24,7 @@ INSTALL= @INSTALL@
LIB= libinstall.a
-OBJS= automatic.o dewey.o fexec.o file.o ftpio.o global.o iterate.o \
+OBJS= automatic.o conflicts.o dewey.o fexec.o file.o ftpio.o global.o iterate.o \
lpkg.o opattern.o path.o pen.o pexec.o pkgdb.o plist.o \
str.o var.o version.o
diff --git a/pkgtools/pkg_install/files/lib/conflicts.c b/pkgtools/pkg_install/files/lib/conflicts.c
new file mode 100644
index 00000000000..e8761905dcf
--- /dev/null
+++ b/pkgtools/pkg_install/files/lib/conflicts.c
@@ -0,0 +1,116 @@
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <nbcompat.h>
+
+#if HAVE_ERR_H
+#include <err.h>
+#endif
+
+#include "dewey.h"
+#include "lib.h"
+
+struct package_conflict {
+ const char *pkgname;
+ char **conflicting_pkgname;
+ char **conflicting_pattern;
+};
+
+static void *
+nonnull(void *p) {
+
+ if (p == NULL) {
+ err(EXIT_FAILURE, "NullPointerException");
+ /* NOTREACHED */
+ }
+ return p;
+}
+
+static FILE *
+fopen_contents(const char *pkgname, const char *mode)
+{
+ char fname[MaxPathSize];
+ FILE *f;
+
+ snprintf(fname, sizeof(fname), "%s/%s/%s", _pkgdb_getPKGDB_DIR(), pkgname, CONTENTS_FNAME);
+ f = fopen(fname, mode);
+ if (f == NULL) {
+ err(EXIT_FAILURE, "%s", fname);
+ /* NOTREACHED */
+ }
+ return f;
+}
+
+
+static int
+check_package_conflict(const char *pkgname, void *v) {
+ struct package_conflict *conflict = v;
+ package_t pkg;
+ plist_t *p;
+ FILE *f;
+ int rv;
+
+ rv = 0;
+ pkg.head = NULL;
+ pkg.tail = NULL;
+
+ f = fopen_contents(pkgname, "r");
+ read_plist(&pkg, f);
+ (void)fclose(f);
+
+ for (p = pkg.head; p; p = p->next) {
+ if (p->type != PLIST_PKGCFL)
+ continue;
+
+ if (pkg_match(p->name, conflict->pkgname) == 1) {
+ *(conflict->conflicting_pkgname) = nonnull(strdup(pkgname));
+ *(conflict->conflicting_pattern) = nonnull(strdup(p->name));
+ rv = 1 /* nonzero, stop iterating */;
+ break;
+ }
+ }
+
+ free_plist(&pkg);
+ return rv;
+}
+
+/**
+ * Checks if some installed package has a pkgcfl entry that matches
+ * PkgName. If such an entry is found, the package name is returned in
+ * inst_pkgname, the matching pattern in inst_pattern, and the function
+ * returns a non-zero value. Otherwise, zero is returned and the result
+ * variables are set to NULL.
+ */
+int
+some_installed_package_conflicts_with(const char *pkgname, char **inst_pkgname, char **inst_pattern)
+{
+ struct package_conflict cfl;
+ int rv;
+
+ cfl.pkgname = pkgname;
+ *inst_pkgname = NULL;
+ *inst_pattern = NULL;
+ cfl.conflicting_pkgname = inst_pkgname;
+ cfl.conflicting_pattern = inst_pattern;
+ rv = iterate_pkg_db(check_package_conflict, &cfl);
+ if (rv == -1) {
+ errx(EXIT_FAILURE, "Couldn't read list of installed packages.");
+ /* NOTREACHED */
+ }
+ return *inst_pkgname != NULL;
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+ char *pkg, *patt;
+
+ if (some_installed_package_conflicts_with(argv[1], &pkg, &patt))
+ printf("yes: package %s conflicts with %s, pattern %s\n", pkg, argv[1], patt);
+ else
+ printf("no\n");
+ return 0;
+}
+void cleanup(int i) {}
+#endif
diff --git a/pkgtools/pkg_install/files/lib/lib.h b/pkgtools/pkg_install/files/lib/lib.h
index 951a3976b7d..693db9f5391 100644
--- a/pkgtools/pkg_install/files/lib/lib.h
+++ b/pkgtools/pkg_install/files/lib/lib.h
@@ -1,4 +1,4 @@
-/* $NetBSD: lib.h,v 1.37 2007/08/29 15:42:39 jlam Exp $ */
+/* $NetBSD: lib.h,v 1.38 2007/11/30 00:30:40 rillig Exp $ */
/* from FreeBSD Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp */
@@ -288,6 +288,10 @@ typedef struct {
#define IS_STDIN(str) ((str) != NULL && !strcmp((str), "-"))
#define IS_FULLPATH(str) ((str) != NULL && (str)[0] == '/')
+/* Conflict handling (conflicts.c) */
+int some_installed_package_conflicts_with(const char *, char **, char **);
+
+
/* Prototypes */
/* Misc */
void cleanup(int);