Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Mar 2001 20:26:45 +0200
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        Garrett Rooney <rooneg@electricjellyfish.net>, ports@FreeBSD.org, jhk@FreeBSD.org, gad@FreeBSD.org
Subject:   Re: [patch] which package functionality for pkg_info
Message-ID:  <3ABB9565.F5F0C22@FreeBSD.org>
References:  <20010301145950.B90945@electricjellyfish.net> <200103012014.f21KESc59992@vic.sabbo.net> <20010322183141.B23846@electricjellyfish.net> <3ABB17E8.A5558BDD@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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 <sys/queue.h>
+
 #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 <err.h>
 #include "lib.h"
 #include "info.h"
+#include <err.h>
 
 #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 <sys/types.h>
 #include <err.h>
 #include <signal.h>
 
 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 <err.h>
 #include <stdlib.h>
 #include <sys/types.h>
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 <err.h>
 #include <stdio.h>
 
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 <err.h>
 #include "lib.h"
+#include <err.h>
 
 /*
  * 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 <err.h>
 #include <fnmatch.h>
 #include <fts.h>
@@ -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 <err.h>
 #include <paths.h>
-#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 <err.h>
 #include "lib.h"
+#include <err.h>
 #include <sys/signal.h>
 #include <sys/param.h>
 #include <sys/mount.h>
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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3ABB9565.F5F0C22>