diff options
author | rillig <rillig> | 2007-11-30 00:30:39 +0000 |
---|---|---|
committer | rillig <rillig> | 2007-11-30 00:30:39 +0000 |
commit | 76afcdfc938b6df028d84a2dbaa8ab5ed4db4c19 (patch) | |
tree | cd557dc1bdb1b8554ddf57ab9d36b10d843a926f | |
parent | b0b6a6549c5690b0a7848abc9a57d8b5fd70d575 (diff) | |
download | pkgsrc-76afcdfc938b6df028d84a2dbaa8ab5ed4db4c19.tar.gz |
Do not install a package if some of the installed packages would
conflict with it. This fixes PR 37451.
-rw-r--r-- | pkgtools/pkg_install/files/add/perform.c | 17 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/Makefile.in | 4 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/conflicts.c | 116 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/lib.h | 6 |
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); |