From owner-freebsd-ports Fri Mar 23 10:27:57 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 BD6E137B71B; Fri, 23 Mar 2001 10:26:58 -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 f2NIQnX10512; Fri, 23 Mar 2001 20:26:50 +0200 Received: from FreeBSD.org (big_brother.vega.com [192.168.1.1]) by vic.sabbo.net (8.11.3/8.11.2) with ESMTP id f2NIQr923065; Fri, 23 Mar 2001 20:26:53 +0200 (EET) (envelope-from sobomax@FreeBSD.org) Message-ID: <3ABB9565.F5F0C22@FreeBSD.org> Date: Fri, 23 Mar 2001 20:26: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: Garrett Rooney , ports@FreeBSD.org, jhk@FreeBSD.org, gad@FreeBSD.org Subject: Re: [patch] which package functionality for pkg_info References: <20010301145950.B90945@electricjellyfish.net> <200103012014.f21KESc59992@vic.sabbo.net> <20010322183141.B23846@electricjellyfish.net> <3ABB17E8.A5558BDD@FreeBSD.org> Content-Type: multipart/mixed; boundary="------------7349CF11425C4E83F4187DF6" Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org This is a multi-part message in MIME format. --------------7349CF11425C4E83F4187DF6 Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 7bit Maxim Sobolev wrote: > Garrett Rooney wrote: > > > Well, it's been about 3 weeks since Maxim said he'd take a look at commiting > > this patch, and i guess he hasn't had time yet (which is understandable, what > > with the 4.3 release comming up and all). > > > > In the meantime though, one change to /usr/src/usr.sbin.pkg_info/lib/match.c > > actually broke the patch. Here's an updated version, which fixes > > matchinstalled() to work as advertised in the comments. It was dumping core > > if you passed it NULL as its second parameter, even though the comment > > specifically says you can do that. > > > > Regardless of whether my other changes go in, that should probably be fixed. > > > > In any event, here's an updated patch, if someone would take a look and > > (assuming there aren't any problems we missed in the last round of debugging) > > possibly commit it, i'd appreciate it. > > Thank you for your reminder. I have several other comments regarding your > patchset, which I hopefully will submit to you later today. Please hold on. Ok with this message I'm attaching final version of the patch in question. Following fixes/cleanups have been made: - comments formatted to match style(9); - popen(3) return value check added; - cmp_path() function simplified; - error messages slighly ajusted to follow usual format; - includes reordered to be consistent across the source; - etc. If you agree with this patch, please let me know and I'll commit it shortly. -Maxim --------------7349CF11425C4E83F4187DF6 Content-Type: text/plain; charset=koi8-r; name="pi.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pi.diff" Index: info/info.h =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/info.h,v retrieving revision 1.18 diff -d -u -r1.18 info.h --- info/info.h 2001/02/27 09:00:18 1.18 +++ info/info.h 2001/03/23 18:18:44 @@ -23,6 +23,8 @@ #ifndef _INST_INFO_H_INCLUDE #define _INST_INFO_H_INCLUDE +#include + #ifndef MAXINDEXSIZE #define MAXINDEXSIZE 59 #endif @@ -47,12 +49,21 @@ #define SHOW_ORIGIN 0x2000 #define SHOW_CKSUM 0x4000 +struct which_entry { + TAILQ_ENTRY(which_entry) next; + char file[PATH_MAX]; + char package[PATH_MAX]; + Boolean skip; +}; +TAILQ_HEAD(which_head, which_entry); + extern int Flags; extern Boolean Quiet; extern char *InfoPrefix; extern char PlayPen[]; extern char *CheckPkg; extern match_t MatchType; +extern struct which_head *whead; extern void show_file(char *, char *); extern void show_plist(char *, Package *, plist_t); Index: info/main.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/main.c,v retrieving revision 1.30 diff -d -u -r1.30 main.c --- info/main.c 2001/02/24 14:10:31 1.30 +++ info/main.c 2001/03/23 18:18:44 @@ -19,16 +19,16 @@ * */ -#include #include "lib.h" #include "info.h" +#include #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif -static char Options[] = "acdDe:fgGhiIkl:LmopqrRst:vx"; +static char Options[] = "acdDe:fgGhiIkl:LmopqrRst:vW:x"; int Flags = 0; match_t MatchType = MATCH_GLOB; @@ -36,6 +36,7 @@ char *InfoPrefix = ""; char PlayPen[FILENAME_MAX]; char *CheckPkg = NULL; +struct which_head *whead; static void usage __P((void)); @@ -46,6 +47,11 @@ char **pkgs, **start; char *pkgs_split; + whead = malloc(sizeof(struct which_head)); + if (whead == NULL) + err(2, NULL); + TAILQ_INIT(whead); + pkgs = start = argv; if (argc == 1) { MatchType = MATCH_ALL; @@ -148,6 +154,20 @@ CheckPkg = optarg; break; + case 'W': + { + struct which_entry *entp; + + entp = calloc(1, sizeof(struct which_entry)); + if (entp == NULL) + err(2, NULL); + + strlcpy(entp->file, optarg, PATH_MAX); + entp->skip = FALSE; + TAILQ_INSERT_TAIL(whead, entp, next); + break; + } + case 'h': case '?': default: @@ -185,7 +205,8 @@ } /* If no packages, yelp */ - if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg) + if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg && + TAILQ_EMPTY(whead)) warnx("missing package name(s)"), usage(); *pkgs = NULL; return pkg_perform(start); @@ -196,7 +217,7 @@ { fprintf(stderr, "%s\n%s\n%s\n", "usage: pkg_info [-cdDfGiIkLmopqrRsvx] [-e package] [-l prefix]", - " [-t template] [pkg-name ...]", + " [-t template] [-W filename] [pkg-name ...]", " pkg_info -a [flags]"); exit(1); } Index: info/perform.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/perform.c,v retrieving revision 1.36 diff -d -u -r1.36 perform.c --- info/perform.c 2001/03/01 13:08:07 1.36 +++ info/perform.c 2001/03/23 18:18:44 @@ -25,12 +25,12 @@ #include "lib.h" #include "info.h" - -#include #include #include static int pkg_do(char *); +static int find_pkg(char *, struct which_head *); +static int cmp_path(const char *, const char *, const char *); int pkg_perform(char **pkgs) @@ -42,16 +42,19 @@ signal(SIGINT, cleanup); + tmp = getenv(PKG_DBDIR); + if (!tmp) + tmp = DEF_LOG_DIR; + /* Overriding action? */ if (CheckPkg) { char buf[FILENAME_MAX]; - tmp = getenv(PKG_DBDIR); - if (!tmp) - tmp = DEF_LOG_DIR; snprintf(buf, FILENAME_MAX, "%s/%s", tmp, CheckPkg); return abs(access(buf, R_OK)); /* Not reached */ + } else if (!TAILQ_EMPTY(whead)) { + return find_pkg(tmp, whead); } if (MatchType != MATCH_EXACT) { @@ -239,3 +242,150 @@ exit(1); } +/* + * Comparison to see if the path we're on matches the + * one we are looking for. + */ +static int +cmp_path(const char *target, const char *current, const char *cwd) +{ + char *loc, *temp; + int rval; + + asprintf(&temp, "%s/%s", cwd, current); + if (temp == NULL) + errx(2, NULL); + + /* + * Make sure there's no multiple /'s, since some plists + * seem to have them and it could screw up our strncmp. + */ + while ((loc = strstr(temp, "//")) != NULL) + strcpy(loc, loc + 1); + + if (strcmp(target, temp) == 0) + rval = 1; + else + rval = 0; + + free(temp); + return rval; +} + +/* + * Look through package dbs in db_dir and find which + * packages installed the files in which_list. + */ +static int +find_pkg(char *db_dir, struct which_head *which_list) +{ + char **installed; + int errcode, i; + struct which_entry *wp; + + TAILQ_FOREACH(wp, which_list, next) { + /* If it's not a file, we'll see if it's an executable. */ + if (isfile(wp->file) == FALSE) { + if (strchr(wp->file, '/') == NULL) { + char *tmp; + tmp = vpipe("/usr/bin/which %s", wp->file); + if (tmp == NULL) { + warnx("%s: file is not in PATH", wp->file); + wp->skip = TRUE; + } else + strlcpy(wp->file, tmp, PATH_MAX); + free(tmp); + } else { + warnx("%s: file cannot be found", wp->file); + wp->skip = TRUE; + } + } else if (wp->file[0] != '/') { + /* + * If it is a file, and it doesn't start with a /, then it's a + * relative path. in order to give us some chance of getting a + * successful match, tack the current working directory on the + * beginning. this won't work for filenames that include .. or . + * or extra /'s, but it's better than nothing). + */ + char *curdir, *tmp; + + curdir = getcwd(NULL, PATH_MAX); + if (curdir == NULL) + err(2, NULL); + + asprintf(&tmp, "%s/%s", curdir, wp->file); + if (tmp == NULL) + err(2, NULL); + + if (!isfile(tmp)) { + warnx("%s: file cannot be found", tmp); + wp->skip = TRUE; + } else + strlcpy(wp->file, tmp, PATH_MAX); + + free(tmp); + free(curdir); + } + } + + installed = matchinstalled(MATCH_ALL, NULL, &errcode); + if (installed == NULL) + return errcode; + + for (i = 0; installed[i] != NULL; i++) { + FILE *fp; + Package pkg; + PackingList itr; + char *cwd = NULL; + char tmp[PATH_MAX]; + + snprintf(tmp, PATH_MAX, "%s/%s/%s", db_dir, installed[i], + CONTENTS_FNAME); + fp = fopen(tmp, "r"); + if (fp == NULL) { + warn("%s", tmp); + return 1; + } + + pkg.head = pkg.tail = NULL; + read_plist(&pkg, fp); + fclose(fp); + for (itr = pkg.head; itr != pkg.tail; itr = itr->next) { + if (itr->type == PLIST_CWD) { + cwd = itr->name; + } else if (itr->type == PLIST_FILE) { + TAILQ_FOREACH(wp, which_list, next) { + if (wp->skip == TRUE) + continue; + if (!cmp_path(wp->file, itr->name, cwd)) + continue; + if (wp->package[0] != '\0') { + warnx("Both %s and %s claim to have installed %s\n", + wp->package, installed[i], wp->file); + } else { + strlcpy(wp->package, installed[i], PATH_MAX); + } + } + } + } + free_plist(&pkg); + } + + TAILQ_FOREACH(wp, which_list, next) { + if (wp->package[0] != '\0') { + if (Quiet) + puts(wp->package); + else + printf("%s was installed by package %s\n", \ + wp->file, wp->package); + } + } + while (!TAILQ_EMPTY(which_list)) { + wp = TAILQ_FIRST(which_list); + TAILQ_REMOVE(which_list, wp, next); + free(wp); + } + + free(which_list); + return 0; +} Index: info/pkg_info.1 =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/pkg_info.1,v retrieving revision 1.37 diff -d -u -r1.37 pkg_info.1 --- info/pkg_info.1 2001/02/20 21:57:19 1.37 +++ info/pkg_info.1 2001/03/23 18:18:44 @@ -29,6 +29,7 @@ .Op Fl e Ar package .Op Fl l Ar prefix .Op Fl t Ar template +.Op Fl W Ar filename .Op Ar pkg-name ... .Nm .Fl a @@ -105,6 +106,14 @@ .Nm automatically expands shell glob patterns in the .Ar pkg-name ) . +.It Fl W +For the specified +.Ar filename +argument show which package it belongs to. If the file is not in the +current directory, and does not have an absolute path, then the +.Ev PATH +is searched using +.Xr which 1 . .It Fl x Treat the .Ar pkg-name Index: info/show.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/show.c,v retrieving revision 1.20 diff -d -u -r1.20 show.c --- info/show.c 2001/02/05 09:56:52 1.20 +++ info/show.c 2001/03/23 18:18:45 @@ -25,7 +25,6 @@ #include "lib.h" #include "info.h" - #include #include #include Index: lib/deps.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/deps.c,v retrieving revision 1.1 diff -d -u -r1.1 deps.c --- lib/deps.c 2001/03/15 10:47:00 1.1 +++ lib/deps.c 2001/03/23 18:18:45 @@ -25,7 +25,6 @@ */ #include "lib.h" - #include #include Index: lib/exec.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/exec.c,v retrieving revision 1.7 diff -d -u -r1.7 exec.c --- lib/exec.c 1999/08/28 01:18:05 1.7 +++ lib/exec.c 2001/03/23 18:18:45 @@ -23,8 +23,8 @@ * */ -#include #include "lib.h" +#include /* * Unusual system() substitute. Accepts format string and args, @@ -58,5 +58,52 @@ va_end(args); free(cmd); return ret; +} + +char * +vpipe(const char *fmt, ...) +{ + FILE *fp; + char *cmd, *rp; + int maxargs; + va_list args; + + rp = malloc(MAXPATHLEN); + if (!rp) { + warnx("vpipe can't alloc buffer space"); + return NULL; + } + maxargs = sysconf(_SC_ARG_MAX); + maxargs -= 32; /* some slop for the sh -c */ + cmd = alloca(maxargs); + if (!cmd) { + warnx("vpipe can't alloc arg space"); + return NULL; + } + + va_start(args, fmt); + if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) { + warnx("vsystem args are too long"); + return NULL; + } +#ifdef DEBUG + fprintf(stderr, "Executing %s\n", cmd); +#endif + fflush(NULL); + fp = popen(cmd, "r"); + if (fp == NULL) { + warnx("popen() failed"); + return NULL; + } + get_string(rp, MAXPATHLEN, fp); +#ifdef DEBUG + fprintf(stderr, "Returned %s\n", rp); +#endif + va_end(args); + if (pclose(fp) || (strlen(rp) == 0)) { + free(rp); + return NULL; + } + return rp; } Index: lib/lib.h =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/lib.h,v retrieving revision 1.33 diff -d -u -r1.33 lib.h --- lib/lib.h 2001/03/15 10:47:00 1.33 +++ lib/lib.h 2001/03/23 18:18:45 @@ -112,6 +112,7 @@ /* Prototypes */ /* Misc */ int vsystem(const char *, ...); +char *vpipe(const char *, ...); void cleanup(int); char *make_playpen(char *, size_t); char *where_playpen(void); @@ -126,6 +127,7 @@ void str_lowercase(char *); char *basename_of(char *); char *strconcat(char *, char *); +char *get_string(char *, int, FILE *); /* File */ Boolean fexists(char *); Index: lib/match.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/match.c,v retrieving revision 1.3 diff -d -u -r1.3 match.c --- lib/match.c 2001/03/14 19:46:43 1.3 +++ lib/match.c 2001/03/23 18:18:45 @@ -24,7 +24,6 @@ */ #include "lib.h" - #include #include #include @@ -97,14 +96,18 @@ } /* Count number of patterns */ - for (len = 0; patterns[len]; len++) {} - lmatched = alloca(sizeof(*lmatched) * len); - if (lmatched == NULL) { - warnx("%s(): alloca() failed", __FUNCTION__); - if (retval != NULL) - *retval = 1; - return NULL; - } + if (patterns != NULL) { + for (len = 0; patterns[len]; len++) {} + lmatched = alloca(sizeof(*lmatched) * len); + if (lmatched == NULL) { + warnx("%s(): alloca() failed", __FUNCTION__); + if (retval != NULL) + *retval = 1; + return NULL; + } + } else + len = 0; + for (i = 0; i < len; i++) lmatched[i] = FALSE; Index: lib/msg.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/msg.c,v retrieving revision 1.13 diff -d -u -r1.13 msg.c --- lib/msg.c 2000/12/09 09:35:51 1.13 +++ lib/msg.c 2001/03/23 18:18:47 @@ -24,9 +24,9 @@ * */ +#include "lib.h" #include #include -#include "lib.h" /* Die a relatively simple death */ void Index: lib/pen.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/pen.c,v retrieving revision 1.32 diff -d -u -r1.32 pen.c --- lib/pen.c 2000/10/22 09:53:27 1.32 +++ lib/pen.c 2001/03/23 18:18:47 @@ -23,8 +23,8 @@ * */ -#include #include "lib.h" +#include #include #include #include Index: lib/str.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/str.c,v retrieving revision 1.7 diff -d -u -r1.7 str.c --- lib/str.c 2000/10/22 09:53:27 1.7 +++ lib/str.c 2001/03/23 18:18:47 @@ -109,3 +109,22 @@ ++str; } } + +char * +get_string(char *str, int max, FILE *fp) +{ + int len; + + if (!str) + return NULL; + str[0] = '\0'; + while (fgets(str, max, fp)) { + len = strlen(str); + while (len && isspace(str[len - 1])) + str[--len] = '\0'; + if (len) + return str; + } + return NULL; +} + --------------7349CF11425C4E83F4187DF6-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message