diff options
-rw-r--r-- | pkgtools/pkgconflict/Makefile | 30 | ||||
-rw-r--r-- | pkgtools/pkgconflict/files/Makefile | 11 | ||||
-rw-r--r-- | pkgtools/pkgconflict/files/dewey_cmp.c | 273 | ||||
-rwxr-xr-x | pkgtools/pkgconflict/files/pkgconflict | 151 | ||||
-rw-r--r-- | pkgtools/pkgconflict/pkg/DESCR | 12 | ||||
-rw-r--r-- | pkgtools/pkgconflict/pkg/PLIST | 3 |
6 files changed, 480 insertions, 0 deletions
diff --git a/pkgtools/pkgconflict/Makefile b/pkgtools/pkgconflict/Makefile new file mode 100644 index 00000000000..4bd51a6c99b --- /dev/null +++ b/pkgtools/pkgconflict/Makefile @@ -0,0 +1,30 @@ +# $NetBSD: Makefile,v 1.1.1.1 2001/04/02 18:04:03 wennmach Exp $ +# + +DISTNAME= pkgconflict-0.1 +CATEGORIES= pkgtools +MASTER_SITES= # empty +DISTFILES= # empty + +MAINTAINER= wennmach@netbsd.org +COMMENT= Script to find conflicting packages in pkgsrc + +DEPENDS+= postgresql>=7.0:../../databases/postgresql + +NO_WRKSUBDIR= yes +NO_CHECKSUM= yes +NO_PATCH= yes +NO_CONFIGURE= yes + +post-extract: + @for FILE in Makefile dewey_cmp.c pkgconflict \ + ; do \ + ${SED} -e 's|@PREFIX@|${PREFIX}|' ${FILESDIR}/$$FILE \ + >${WRKSRC}/$$FILE; \ + done + +do-install: + ${INSTALL_SCRIPT} ${WRKSRC}/dewey_cmp.so ${PREFIX}/lib + ${INSTALL_SCRIPT} ${WRKSRC}/pkgconflict ${PREFIX}/bin + +.include "../../mk/bsd.pkg.mk" diff --git a/pkgtools/pkgconflict/files/Makefile b/pkgtools/pkgconflict/files/Makefile new file mode 100644 index 00000000000..388a8e72b78 --- /dev/null +++ b/pkgtools/pkgconflict/files/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.1.1.1 2001/04/02 18:04:04 wennmach Exp $ + +PGINCLUDE=@PREFIX@/include/pgsql + +.c.o: + cc -I${PGINCLUDE} -Wall -fpic -c $< + +all: dewey_cmp.so + +dewey_cmp.so: dewey_cmp.o + cc -shared -o dewey_cmp.so dewey_cmp.o diff --git a/pkgtools/pkgconflict/files/dewey_cmp.c b/pkgtools/pkgconflict/files/dewey_cmp.c new file mode 100644 index 00000000000..f23c520977f --- /dev/null +++ b/pkgtools/pkgconflict/files/dewey_cmp.c @@ -0,0 +1,273 @@ +/* $NetBSD: dewey_cmp.c,v 1.1.1.1 2001/04/02 18:04:04 wennmach Exp $ */ + +/* + * Implement the comparision of a package name with a dewey pattern + * for use with PostgreSQL. + * + * Author: Lex Wennmacher, + * almost entirely based on the dewey routines written by: Hubert Feyrer + * (taken from: basesrc/usr.sbin/pkg_install/lib/str.c, version 1.28 + */ + +#include <sys/cdefs.h> +#if 0 +static const char *rcsid = "Id: str.c,v 1.5 1997/10/08 07:48:21 charnier Exp"; +#else +__RCSID("$NetBSD: dewey_cmp.c,v 1.1.1.1 2001/04/02 18:04:04 wennmach Exp $"); +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Miscellaneous string utilities. + * + */ + +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/queue.h> + +#include <ctype.h> +#include <dirent.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> + +#include <assert.h> +#include <err.h> +#include <fnmatch.h> + +int pmatch(const char *, const char *); + +typedef enum deweyop_t { + GT, + GE, + LT, + LE +} deweyop_t; + +/* + * Compare two dewey decimal numbers + */ +static int +deweycmp(char *a, deweyop_t op, char *b) +{ + int ad; + int bd; + char *a_nb; + char *b_nb; + int in_nb = 0; + int cmp; + + assert(a != NULL); + assert(b != NULL); + + /* Null out 'n' in any "nb" suffixes for initial pass */ + if ((a_nb = strstr(a, "nb"))) + *a_nb = 0; + if ((b_nb = strstr(b, "nb"))) + *b_nb = 0; + + for (;;) { + if (*a == 0 && *b == 0) { + if (!in_nb && (a_nb || b_nb)) { + /* + * If exact match on first pass, test + * "nb<X>" suffixes in second pass + */ + in_nb = 1; + if (a_nb) + a = a_nb + 2; /* Skip "nb" suffix */ + if (b_nb) + b = b_nb + 2; /* Skip "nb" suffix */ + } else { + cmp = 0; + break; + } + } + + ad = bd = 0; + for (; *a && *a != '.'; a++) { + ad = (ad * 10) + (*a - '0'); + } + for (; *b && *b != '.'; b++) { + bd = (bd * 10) + (*b - '0'); + } + if ((cmp = ad - bd) != 0) { + break; + } + if (*a == '.') + ++a; + if (*b == '.') + ++b; + } + /* Replace any nulled 'n' */ + if (a_nb) + *a_nb = 'n'; + if (b_nb) + *b_nb = 'n'; + return (op == GE) ? cmp >= 0 : (op == GT) ? cmp > 0 : + (op == LE) ? cmp <= 0 : cmp < 0; +} + +/* + * Perform alternate match on "pkg" against "pattern", + * calling pmatch (recursively) to resolve any other patterns. + * Return 1 on match, 0 otherwise + */ +static int +alternate_match(const char *pattern, const char *pkg) +{ + char *sep; + char buf[FILENAME_MAX]; + char *last; + char *alt; + char *cp; + int cnt; + int found; + + if ((sep = strchr(pattern, '{')) == (char *) NULL) { + errx(1, "alternate_match(): '{' expected in `%s'", pattern); + } + (void)strncpy(buf, pattern, (size_t) (sep - pattern)); + alt = &buf[sep - pattern]; + last = (char *) NULL; + for (cnt = 0, cp = sep; *cp && last == (char *) NULL; cp++) { + if (*cp == '{') { + cnt++; + } else if (*cp == '}' && --cnt == 0 && last == (char *) NULL) { + last = cp + 1; + } + } + if (cnt != 0) { + errx(1, "Malformed alternate `%s'", pattern); + } + for (found = 0, cp = sep + 1; *sep != '}'; cp = sep + 1) { + for (cnt = 0, sep = cp; cnt > 0 || (cnt == 0 && *sep != '}' && + *sep != ','); sep++) { + if (*sep == '{') { + cnt++; + } else if (*sep == '}') { + cnt--; + } + } + (void)snprintf(alt, sizeof(buf) - (alt - buf), "%.*s%s", + (int)(sep - cp), cp, last); + if (pmatch(buf, pkg) == 1) { + found = 1; + } + } + return found; +} + +/* + * Perform dewey match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +dewey_match(const char *pattern, const char *pkg) +{ + deweyop_t op; + char *cp; + char *sep; + char *ver; + char name[FILENAME_MAX]; + int n; + + if ((sep = strpbrk(pattern, "<>")) == NULL) { + errx(1, "dewey_match(): '<' or '>' expected in `%s'", pattern); + } + (void)snprintf(name, sizeof(name), "%.*s", (int)(sep - pattern), + pattern); + op = (*sep == '>') ? (*(sep + 1) == '=') ? GE : GT : (*(sep + 1) == '=') + ? LE : LT; + ver = (op == GE || op == LE) ? sep + 2 : sep + 1; + n = (int) (sep - pattern); + if ((cp = strrchr(pkg, '-')) != (char *) NULL) { + if (strncmp(pkg, name, (size_t)(cp - pkg)) == 0 && + n == cp - pkg) { + if (deweycmp(cp + 1, op, ver)) { + return 1; + } + } + } + return 0; +} + +/* + * Perform glob match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +glob_match(const char *pattern, const char *pkg) +{ + return fnmatch(pattern, pkg, FNM_PERIOD) == 0; +} + +/* + * Perform simple match on "pkg" against "pattern". + * Return 1 on match, 0 otherwise + */ +static int +simple_match(const char *pattern, const char *pkg) +{ + return strcmp(pattern, pkg) == 0; +} + +/* + * Match pkg against pattern, return 1 if matching, 0 else + */ +int +pmatch(const char *pattern, const char *pkg) +{ + if (strchr(pattern, '{') != (char *) NULL) { + /* emulate csh-type alternates */ + return alternate_match(pattern, pkg); + } + if (strpbrk(pattern, "<>") != (char *) NULL) { + /* perform relational dewey match on version number */ + return dewey_match(pattern, pkg); + } + if (strpbrk(pattern, "*?[]") != (char *) NULL) { + /* glob match */ + return glob_match(pattern, pkg); + } + + /* no alternate, dewey or glob match -> simple compare */ + return simple_match(pattern, pkg); +} + + +/* pkg_cmp is used to implement the ~~~ operator in PostgreSQL */ +#include <postgres.h> + +bool +pkg_cmp(text *pkg, text *pattern) +{ + +/* Make sure that the strings are \0 terminated */ + pkg->vl_dat[pkg->vl_len] = '\0'; + pattern->vl_dat[pattern->vl_len] = '\0'; + + if (pmatch((const char *)&(pattern->vl_dat), + (const char *)&(pkg->vl_dat)) == 1) + return true; + + return false; +} diff --git a/pkgtools/pkgconflict/files/pkgconflict b/pkgtools/pkgconflict/files/pkgconflict new file mode 100755 index 00000000000..e8bd539394d --- /dev/null +++ b/pkgtools/pkgconflict/files/pkgconflict @@ -0,0 +1,151 @@ +#!/bin/csh -f +# $NetBSD: pkgconflict,v 1.1.1.1 2001/04/02 18:04:04 wennmach Exp $ +# +# pkgconflict: A script to find conflicting packages in pkgsrc +# Author: Lex Wennmacher <wennmach@netbsd.org> +# + +set PREFIX=@PREFIX@ + +if ($#argv > 1) then + echo Usage: pkgconflict [BASEDIR] + exit -1 +endif + +# BASEDIR is the directory where the packages databases live +# The default location in /var/db/pkg, but can be changed to +# a different directory, e. g. to the place where the bulk builds +# saved the packages databases +if ($#argv == 1) then + set BASEDIR=$1 +else + set BASEDIR="/var/db/pkg" +endif + +if (! -d $BASEDIR) then + echo pkgconflict: error: BASEDIR, $BASEDIR, does not exist. + exit -1 +endif + +psql -l >& /dev/null +if ($status != 0) then + echo pkgconflict: error: PostgreSQL must be installed and configured." + exit -1 +endif + +if (! -x $PREFIX/lib/dewey_cmp.so) then + echo pkgconflict: error: no executable $PREFIX/lib/dewey_cmp.so + exit -1 +endif + +set testfile=.test.$$ +rm -f $testfile +touch $testfile +if (! -e $testfile) then +# XXX if (! -w .) should be simpler, but I'm not sure if it really works + echo pkgconflict: error: local directory must be writable. + exit -1 +endif +rm -f $testfile + +echo pkgconflict: started `date` +echo " " + +if (! -d RCS) mkdir RCS + +rm -f pkgfiles +touch pkgfiles + +rm -f registered_conflicts +touch registered_conflicts + +foreach dir ($BASEDIR/*) + if (-d $dir) then + set basename=$dir:t + echo processig $basename + set contents=$dir/+CONTENTS + if (-e $contents) then + setenv BASENAME $basename + setenv BASEDIR `grep "^@cwd" $contents | awk '{print $2}'` +# do not break the following line + awk '/^[^@].*$/ {print ENVIRON["BASENAME"] "\t" ENVIRON["BASEDIR"] "/" $1}' \ + $contents >> pkgfiles + grep "^@pkgcfl" $contents \ + | awk '{print ENVIRON["BASENAME"] "\t" $2}' \ + >> registered_conflicts + endif + endif +end + +echo " " + +if (-e CFL-big) ci -l -t-version0 -m"script-based checkin" CFL-big +rm -f CFL-big + +if (-e CFL-small) ci -l -t-version0 -m"script-based checkin" CFL-small +rm -f CFL-small + +echo " " +echo pkgconflict: Done processing packages `date` +echo pkgconflict: Invoking PostgreSQL to generate database summaries. +echo " " + +set DATABASE=tmp.$$ +createdb $DATABASE +psql $DATABASE << --EOI-- +create function + pkg_cmp(varchar, varchar) + returns bool + as '$PREFIX/lib/dewey_cmp.so' + language 'C'; +create operator ~~~ ( + leftarg = varchar, + rightarg = varchar, + procedure = pkg_cmp); +create table pkgfiles ( + pkg varchar(40), file varchar(120)); +copy pkgfiles from '`pwd`/pkgfiles'; +create table registered_conflicts ( + pkg varchar(40), pkgpat varchar(40)); +copy registered_conflicts from '`pwd`/registered_conflicts'; +\o CFL-big +\qecho 'CFL-big table generated `date`' +\qecho 'This table contains:' +\qecho ' a pair of conflicting packages (first 2 columns)' +\qecho ' name of the common file (third column)' +\qecho ' ' +select + p1.pkg, p2.pkg, p1.file + from pkgfiles p1, pkgfiles p2, registered_conflicts r + where (p1.pkg <> p2.pkg) + and (p1.file = p2.file) + and (p1.pkg = r.pkg) + and not (p1.pkg ~~~ r.pkgpat) + order by 1 asc; +\o CFL-small +\qecho 'CFL-small table generated `date`' +\qecho 'This table contains:' +\qecho ' a pair of conflicting packages (unique) (first 2 columns)' +\qecho ' the number of conflicting files (third column)' +\qecho ' ' +select + distinct on (p1.pkg, p2.pkg) + p1.pkg, p2.pkg, count(p1.file) + from pkgfiles p1, pkgfiles p2, registered_conflicts r + where (p1.pkg <> p2.pkg) + and (p1.file = p2.file) + and (p1.pkg = r.pkg) + and not (p1.pkg ~~~ r.pkgpat) + group by p1.pkg, p2.pkg + order by 1 asc; +\o null +drop table pkgfiles; +drop table registered_conflicts; +\q +--EOI-- +dropdb $DATABASE +rm -f null pkgfiles registered_conflicts + +echo " " +echo pkgconflict: Done `date`. +exit diff --git a/pkgtools/pkgconflict/pkg/DESCR b/pkgtools/pkgconflict/pkg/DESCR new file mode 100644 index 00000000000..5a70ac207fe --- /dev/null +++ b/pkgtools/pkgconflict/pkg/DESCR @@ -0,0 +1,12 @@ +$NetBSD: DESCR,v 1.1.1.1 2001/04/02 18:04:04 wennmach Exp $ + +pkgconflict is a script that searches for conflicting packages. + +In a first step it gathers the package and file names of all known +packages. The source for this step is either the contents of +/var/db/pkg, or a directory where the builk builds savet the +package databases. + +In a second step, it calls a database system, PostgreSQL, to +determine which packages have common file names. Packages with +registered CONFLICT lines are filtered out. diff --git a/pkgtools/pkgconflict/pkg/PLIST b/pkgtools/pkgconflict/pkg/PLIST new file mode 100644 index 00000000000..4966818d7e8 --- /dev/null +++ b/pkgtools/pkgconflict/pkg/PLIST @@ -0,0 +1,3 @@ +@comment $NetBSD: PLIST,v 1.1.1.1 2001/04/02 18:04:04 wennmach Exp $ +lib/dewey_cmp.so +bin/pkgconflict |