From owner-freebsd-ports Sat Feb 24 6:57:22 2001 Delivered-To: freebsd-ports@freebsd.org Received: from blizzard.sabbo.net (ns.sabbo.net [193.193.218.18]) by hub.freebsd.org (Postfix) with ESMTP id 848D737B491; Sat, 24 Feb 2001 06:56:59 -0800 (PST) (envelope-from sobomax@FreeBSD.org) Received: from vic.sabbo.net (root@vic.sabbo.net [193.193.218.112]) by blizzard.sabbo.net (8.10.1/8.10.1) with ESMTP id f1OEhZv13682; Sat, 24 Feb 2001 16:43:40 +0200 Received: from FreeBSD.org (big_brother.vega.com [192.168.1.1]) by vic.sabbo.net (8.11.2/8.11.2) with ESMTP id f1OEhkS60048; Sat, 24 Feb 2001 16:43:46 +0200 (EET) (envelope-from sobomax@FreeBSD.org) Message-ID: <3A97C8A1.69510FA4@FreeBSD.org> Date: Sat, 24 Feb 2001 16:43:45 +0200 From: Maxim Sobolev Organization: Vega International Capital X-Mailer: Mozilla 4.76 [en] (WinNT; U) X-Accept-Language: uk,ru,en MIME-Version: 1.0 To: ports@FreeBSD.org, jkh@FreeBSD.org Subject: pkg_delete and wildcards/regexs [patch] Content-Type: multipart/mixed; boundary="------------C9D108B6908515FB86A3C83F" Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org This is a multi-part message in MIME format. --------------C9D108B6908515FB86A3C83F Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 7bit Hi folks, With this message I'm attaching patch that brings recent addition of wildcards/regexs match in pkg_info(1) into pkg_delete(1) as well. The code is almost ready for commit, though I'm planning to add some more error checking and evaluating possibility to move matchinstalled() call one level up, into main(). Nevrtheless, I would like to hear your comments and suggestions regarding proposed change. Thanks! -Maxim --------------C9D108B6908515FB86A3C83F Content-Type: text/plain; charset=koi8-r; name="pkg_delete-regex.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pkg_delete-regex.patch" Index: delete/delete.h =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/delete/delete.h,v retrieving revision 1.5 diff -d -u -r1.5 delete.h --- delete/delete.h 1999/08/28 01:18:00 1.5 +++ delete/delete.h 2001/02/24 14:40:14 @@ -29,5 +29,6 @@ extern Boolean Force; extern char *Directory; extern char *PkgName; +extern match_t MatchType; #endif /* _INST_DELETE_H_INCLUDE */ Index: delete/main.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/delete/main.c,v retrieving revision 1.20 diff -d -u -r1.20 main.c --- delete/main.c 2000/10/22 09:53:25 1.20 +++ delete/main.c 2001/02/24 14:40:14 @@ -30,11 +30,12 @@ #include "lib.h" #include "delete.h" -static char Options[] = "hvDdnfp:"; +static char Options[] = "adDfGhnp:vx"; char *Prefix = NULL; Boolean NoDeInstall = FALSE; Boolean CleanDirs = FALSE; +match_t MatchType = MATCH_GLOB; static void usage __P((void)); @@ -75,6 +76,18 @@ Verbose = TRUE; break; + case 'a': + MatchType = MATCH_ALL; + break; + + case 'G': + MatchType = MATCH_EXACT; + break; + + case 'x': + MatchType = MATCH_REGEX; + break; + case 'h': case '?': default: @@ -87,23 +100,26 @@ /* Get all the remaining package names, if any */ while (*argv) { - while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) { - *pkgs_split++ = '\0'; - /* - * If character after the '/' is alphanumeric, then we've found the - * package name. Otherwise we've come across a trailing '/' and - * need to continue our quest. - */ - if (isalpha(*pkgs_split)) { - *argv = pkgs_split; - break; + /* Don't try to apply heuristics if arguments are regexs */ + if (MatchType != MATCH_REGEX) + while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) { + *pkgs_split++ = '\0'; + /* + * If character after the '/' is alphanumeric, then we've found the + * package name. Otherwise we've come across a trailing '/' and + * need to continue our quest. + */ + if (isalpha(*pkgs_split) || ((MatchType == MATCH_GLOB) && \ + strpbrk(pkgs_split, "*?[]") != NULL)) { + *argv = pkgs_split; + break; + } } - } *pkgs++ = *argv++; } /* If no packages, yelp */ - if (pkgs == start) + if (pkgs == start && MatchType != MATCH_ALL) warnx("missing package name(s)"), usage(); *pkgs = NULL; tmp = getenv(PKG_DBDIR) ? getenv(PKG_DBDIR) : DEF_LOG_DIR; @@ -126,6 +142,8 @@ static void usage() { - fprintf(stderr, "usage: pkg_delete [-vDdnf] [-p prefix] pkg-name ...\n"); + fprintf(stderr, "%s\n%s\n", + "usage: pkg_delete [-dDfGnvx] [-p prefix] pkg-name ...", + " pkg_delete -a [flags]"); exit(1); } Index: delete/perform.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/delete/perform.c,v retrieving revision 1.26 diff -d -u -r1.26 perform.c --- delete/perform.c 2001/02/21 02:01:10 1.26 +++ delete/perform.c 2001/02/24 14:40:14 @@ -37,10 +37,29 @@ int pkg_perform(char **pkgs) { + char **matched; char *tmp; int i, j; int err_cnt = 0; int loop_cnt; + + if (MatchType != MATCH_EXACT) { + matched = matchinstalled(MatchType, pkgs); + if (matched != NULL) + pkgs = matched; + else switch (MatchType) { + case MATCH_GLOB: + break; + case MATCH_ALL: + warnx("no packages installed"); + return 0; + case MATCH_REGEX: + warnx("no packages match pattern(s)"); + return 1; + default: + break; + } + } for (i = 0; pkgs[i]; i++) { /* Index: info/info.h =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/info.h,v retrieving revision 1.17 diff -d -u -r1.17 info.h --- info/info.h 2001/02/08 17:43:59 1.17 +++ info/info.h 2001/02/24 14:40:14 @@ -47,12 +47,6 @@ #define SHOW_ORIGIN 0x2000 #define SHOW_CKSUM 0x4000 -enum _match_t { - MATCH_ALL, MATCH_EXACT, MATCH_GLOB, MATCH_REGEX -}; - -typedef enum _match_t match_t; - extern int Flags; extern Boolean Quiet; extern char *InfoPrefix; Index: info/perform.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/perform.c,v retrieving revision 1.34 diff -d -u -r1.34 perform.c --- info/perform.c 2001/02/08 17:44:00 1.34 +++ info/perform.c 2001/02/24 14:40:14 @@ -28,26 +28,19 @@ #include #include -#include -#include -#include #include -static int fname_cmp(const FTSENT **, const FTSENT **); static int pkg_do(char *); -static int rexs_match(char **, char *); int pkg_perform(char **pkgs) { int i, err_cnt = 0; + char **matched; char *tmp; signal(SIGINT, cleanup); - tmp = getenv(PKG_DBDIR); - if (!tmp) - tmp = DEF_LOG_DIR; /* Overriding action? */ if (CheckPkg) { char buf[FILENAME_MAX]; @@ -56,91 +49,28 @@ return abs(access(buf, R_OK)); /* Not reached */ } - - switch (MatchType) { - case MATCH_ALL: - case MATCH_REGEX: - { - FTS *ftsp; - FTSENT *f; - char *paths[2]; - int errcode; - if (!isdir(tmp)) + if (MatchType != MATCH_EXACT) { + matched = matchinstalled(MatchType, pkgs); + if (matched != NULL) + pkgs = matched; + else switch (MatchType) { + case MATCH_GLOB: + break; + case MATCH_ALL: + warnx("no packages installed"); + return 0; + case MATCH_REGEX: + warnx("no packages match pattern(s)"); return 1; - paths[0] = tmp; - paths[1] = NULL; - ftsp = fts_open(paths, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, - fname_cmp); - if (ftsp != NULL) { - while ((f = fts_read(ftsp)) != NULL) { - if (f->fts_info == FTS_D && f->fts_level == 1) { - fts_set(ftsp, f, FTS_SKIP); - if (MatchType == MATCH_REGEX) { - errcode = rexs_match(pkgs, f->fts_name); - if (errcode == -1) { - err_cnt += 1; - break; - } - else if (errcode == 0) - continue; - } - err_cnt += pkg_do(f->fts_name); - } - } - fts_close(ftsp); - } - } - break; - case MATCH_GLOB: - { - glob_t g; - char *gexpr; - char *cp; - int gflags; - int prev_matchc; - - gflags = GLOB_ERR; - prev_matchc = 0; - for (i = 0; pkgs[i]; i++) { - asprintf(&gexpr, "%s/%s", tmp, pkgs[i]); - - if (glob(gexpr, gflags, NULL, &g) != 0) { - warn("%s: error encountered when matching glob", pkgs[i]); - return 1; - } - - /* - * If glob doesn't match try to use pkgs[i] directly - it - * could be name of the tarball. - */ - if (g.gl_matchc == prev_matchc) - err_cnt += pkg_do(pkgs[i]); - - prev_matchc = g.gl_matchc; - gflags |= GLOB_APPEND; - free(gexpr); - } - - for (i = 0; i < g.gl_matchc; i++) { - cp = strrchr(g.gl_pathv[i], '/'); - if (cp == NULL) - cp = g.gl_pathv[i]; - else - cp++; - - err_cnt += pkg_do(cp); - } - - globfree(&g); + default: + break; } - break; - default: - for (i = 0; pkgs[i]; i++) - err_cnt += pkg_do(pkgs[i]); - break; } + for (i = 0; pkgs[i]; i++) + err_cnt += pkg_do(pkgs[i]); + return err_cnt; } @@ -299,57 +229,3 @@ exit(1); } -static int -fname_cmp(const FTSENT **a, const FTSENT **b) -{ - return strcmp((*a)->fts_name, (*b)->fts_name); -} - -/* - * Returns 1 if specified pkgname matches at least one - * of the RE from patterns. Otherwise return 0 if no - * matches were found or -1 if RE engine reported an - * error (usually invalid syntax). - */ -static int -rexs_match(char **patterns, char *pkgname) -{ - Boolean matched; - char errbuf[128]; - int i; - int errcode; - int retval; - regex_t rex; - - errcode = 0; - retval = 0; - matched = FALSE; - for (i = 0; patterns[i]; i++) { - errcode = regcomp(&rex, patterns[i], REG_BASIC | REG_NOSUB); - if (errcode != 0) - break; - - errcode = regexec(&rex, pkgname, 0, NULL, 0); - if (errcode == 0) { - matched = TRUE; - retval = 1; - break; - } - else if (errcode != REG_NOMATCH) - break; - - regfree(&rex); - errcode = 0; - } - - if (errcode != 0) { - regerror(errcode, &rex, errbuf, sizeof(errbuf)); - warnx("%s: %s", patterns[i], errbuf); - retval = -1; - } - - if ((errcode != 0) || (matched == TRUE)) - regfree(&rex); - - return retval; -} Index: lib/Makefile =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/Makefile,v retrieving revision 1.6 diff -d -u -r1.6 Makefile --- lib/Makefile 1996/06/20 18:33:49 1.6 +++ lib/Makefile 2001/02/24 14:40:14 @@ -1,5 +1,5 @@ LIB= install -SRCS= file.c msg.c plist.c str.c exec.c global.c pen.c +SRCS= file.c msg.c plist.c str.c exec.c global.c pen.c match.c CFLAGS+= ${DEBUG} NOPROFILE= yes NOPIC= yes Index: lib/lib.h =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/lib.h,v retrieving revision 1.31 diff -d -u -r1.31 lib.h --- lib/lib.h 2000/09/18 07:41:48 1.31 +++ lib/lib.h 2001/02/24 14:40:14 @@ -88,6 +88,11 @@ }; typedef enum _plist_t plist_t; +enum _match_t { + MATCH_ALL, MATCH_EXACT, MATCH_GLOB, MATCH_REGEX +}; +typedef enum _match_t match_t; + /* Types */ typedef unsigned int Boolean; @@ -168,6 +173,9 @@ /* For all */ int pkg_perform(char **); + +/* Query installed packages */ +char **matchinstalled(match_t, char **); /* Externs */ extern Boolean Verbose; Index: lib/match.c =================================================================== RCS file: match.c diff -N match.c --- /dev/null Sat Feb 24 06:39:55 2001 +++ match.c Sat Feb 24 06:40:15 2001 @@ -0,0 +1,169 @@ +#ifndef lint +static const char rcsid[] = + "$FreeBSD$"; +#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. + * + * Maxim Sobolev + * 24 February 2001 + * + * Routines used to query installed packages. + * + */ + +#include "lib.h" + +#include +#include +#include +#include + +struct store { + int currlen; + int used; + char **store; +}; + +static int rex_match(char *, char *); +static void storeappend(struct store *, const char *); +static int fname_cmp(const FTSENT **, const FTSENT **); + +char ** +matchinstalled(match_t MatchType, char **patterns) +{ + int i; + char *tmp; + static struct store *store = NULL; + FTS *ftsp; + FTSENT *f; + char *paths[2]; + int matched; + + if (store == NULL) { + store = malloc(sizeof *store); + store->currlen = 0; + store->store = NULL; + } else { + if (store->store != NULL) { + for (i = 0; store->store[i] != NULL; i++) + free(store->store[i]); + } + } + store->used = 0; + + tmp = getenv(PKG_DBDIR); + if (!tmp) + tmp = DEF_LOG_DIR; + if (!isdir(tmp)) + return NULL; + + paths[0] = tmp; + paths[1] = NULL; + ftsp = fts_open(paths, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, fname_cmp); + if (ftsp != NULL) { + while ((f = fts_read(ftsp)) != NULL) { + if (f->fts_info == FTS_D && f->fts_level == 1) { + fts_set(ftsp, f, FTS_SKIP); + if (MatchType == MATCH_ALL) { + storeappend(store, f->fts_name); + continue; + } + for (i = 0; patterns[i]; i++) { + matched = 0; + switch (MatchType) { + case MATCH_REGEX: + if (rex_match(patterns[i], f->fts_name) == 1) { + storeappend(store, f->fts_name); + matched = 1; + } + break; + case MATCH_GLOB: + if (fnmatch(patterns[i], f->fts_name, 0) == 0) { + storeappend(store, f->fts_name); + matched = 1; + } + break; + default: + break; + } + if (matched == 1) + break; + } + } + } + fts_close(ftsp); + } + + if (store->used == 0) + return NULL; + else + return store->store; +} + +/* + * Returns 1 if specified pkgname matches RE pattern. + * Otherwise returns 0 if doesn't match or -1 if RE + * engine reported an error (usually invalid syntax). + */ +static int +rex_match(char *pattern, char *pkgname) +{ + char errbuf[128]; + int errcode; + int retval; + regex_t rex; + + retval = 0; + + errcode = regcomp(&rex, pattern, REG_BASIC | REG_NOSUB); + if (errcode == 0) + errcode = regexec(&rex, pkgname, 0, NULL, 0); + + if (errcode == 0) { + retval = 1; + } else if (errcode != REG_NOMATCH) { + regerror(errcode, &rex, errbuf, sizeof(errbuf)); + warnx("%s: %s", pattern, errbuf); + retval = -1; + } + + regfree(&rex); + + return retval; +} + +static void +storeappend(struct store *store, const char *item) +{ + char **tmp; + + if (store->used + 1 >= store->currlen) { + tmp = store->store; + store->currlen += 16; + store->store = malloc(store->currlen * sizeof(*(store->store))); + memcpy(store->store, tmp, store->used * sizeof(*(store->store))); + free(tmp); + } + + asprintf(&(store->store[store->used]), "%s", item); + store->store[++(store->used)] = NULL; +} + +static int +fname_cmp(const FTSENT **a, const FTSENT **b) +{ + return strcmp((*a)->fts_name, (*b)->fts_name); +} + --------------C9D108B6908515FB86A3C83F-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message