Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Mar 2001 18:31:41 -0500
From:      Garrett Rooney <rooneg@electricjellyfish.net>
To:        Maxim Sobolev <sobomax@FreeBSD.ORG>
Cc:        ports@FreeBSD.ORG, jhk@FreeBSD.ORG, gad@FreeBSD.ORG
Subject:   Re: [patch] which package functionality for pkg_info
Message-ID:  <20010322183141.B23846@electricjellyfish.net>
In-Reply-To: <200103012014.f21KESc59992@vic.sabbo.net>; from sobomax@FreeBSD.ORG on Thu, Mar 01, 2001 at 10:13:57PM %2B0200
References:  <20010301145950.B90945@electricjellyfish.net> <200103012014.f21KESc59992@vic.sabbo.net>

next in thread | previous in thread | raw e-mail | index | archive | help

--2fHTh5uZTiUOsy+g
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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.

-garrett

-- 
garrett rooney                     Unix was not designed to stop you from 
rooneg@electricjellyfish.net       doing stupid things, because that would  
http://electricjellyfish.net/      stop you from doing clever things.

--2fHTh5uZTiUOsy+g
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="pkg_info.diff"

Index: info/info.h
===================================================================
RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/info.h,v
retrieving revision 1.18
diff -u -r1.18 info.h
--- info/info.h	2001/02/27 09:00:18	1.18
+++ info/info.h	2001/03/03 06:23:24
@@ -47,12 +47,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: /usr/local/cvs/src/usr.sbin/pkg_install/info/main.c,v
retrieving revision 1.30
diff -u -r1.30 main.c
--- info/main.c	2001/02/24 14:10:31	1.30
+++ info/main.c	2001/03/03 06:23:59
@@ -19,7 +19,9 @@
  *
  */
 
+#include <sys/queue.h>
 #include <err.h>
+
 #include "lib.h"
 #include "info.h"
 
@@ -28,7 +30,7 @@
   "$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 +38,7 @@
 char *InfoPrefix	= "";
 char PlayPen[FILENAME_MAX];
 char *CheckPkg		= NULL;
+struct which_head *whead;
 
 static void usage __P((void));
 
@@ -46,6 +49,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 +156,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 +207,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 +219,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: /usr/local/cvs/src/usr.sbin/pkg_install/info/perform.c,v
retrieving revision 1.36
diff -u -r1.36 perform.c
--- info/perform.c	2001/03/01 13:08:07	1.36
+++ info/perform.c	2001/03/03 06:25:59
@@ -23,14 +23,16 @@
  *
  */
 
-#include "lib.h"
-#include "info.h"
-
-#include <sys/types.h>
 #include <err.h>
 #include <signal.h>
+#include <sys/queue.h>
 
+#include "lib.h"
+#include "info.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 +44,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 +244,155 @@
 	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 *fixed_path;
+    char *temp;
+    char *itr1;
+    char *itr2;
+    int rval, fixed_len;
+
+    fixed_path = calloc(strlen(current) + strlen(cwd) + 2, sizeof(char));
+    asprintf(&temp, "%s/%s", cwd, current);
+    if (fixed_path == NULL || temp == NULL) {
+        errx(2, "out of memory\n");
+    }
+
+    /* make sure there's no multiple /'s, since some plists seem to have them 
+     * and it could screw up our strncmp. */
+    for (itr1 = temp, itr2 = fixed_path; *itr1 != '\0'; itr1++) {
+        *itr2 = *itr1;
+        if (*itr2 == '/') {
+            if (*(itr1 + 1) != '/')
+                itr2++;
+        } else
+            itr2++;
+    }
+    
+    fixed_len = strlen(fixed_path);
+    if (strlen(target) == fixed_len && !strncmp(target, fixed_path, fixed_len))
+	rval = 1;
+    else
+	rval = 0;
+    free(fixed_path);
+    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)
+{
+    struct which_entry *wp;
+    char **installed;
+    int errcode, i;
+
+    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("which %s", wp->file); 
+		if (tmp == NULL) {
+		    warnx("file %s is not in path", wp->file);
+		    wp->skip = TRUE;
+		} else
+		    strlcpy(wp->file, tmp, PATH_MAX);
+		free(tmp);
+	    } else {
+		warnx("file %s cannot be found", wp->file);
+		wp->skip = TRUE;
+	    }
+	} else if (strncmp(wp->file, "/", 1) != 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;
+	    char *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("file %s 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)
+		fprintf(stdout, "%s\n", wp->package);
+	    else
+		fprintf(stdout, "%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: /usr/local/cvs/src/usr.sbin/pkg_install/info/pkg_info.1,v
retrieving revision 1.37
diff -u -r1.37 pkg_info.1
--- info/pkg_info.1	2001/02/20 21:57:19	1.37
+++ info/pkg_info.1	2001/03/03 06:21:19
@@ -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: /usr/local/cvs/src/usr.sbin/pkg_install/info/show.c,v
retrieving revision 1.20
diff -u -r1.20 show.c
--- info/show.c	2001/02/05 09:56:52	1.20
+++ info/show.c	2001/03/03 06:21:19
@@ -23,14 +23,15 @@
  *
  */
 
-#include "lib.h"
-#include "info.h"
-
 #include <err.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/queue.h>
 #include <md5.h>
+
+#include "lib.h"
+#include "info.h"
 
 void
 show_file(char *title, char *fname)
Index: lib/exec.c
===================================================================
RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/lib/exec.c,v
retrieving revision 1.7
diff -u -r1.7 exec.c
--- lib/exec.c	1999/08/28 01:18:05	1.7
+++ lib/exec.c	2001/03/03 06:21:19
@@ -60,3 +60,47 @@
     return ret;
 }
 
+char *
+vpipe(const char *fmt, ...)
+{
+   va_list args;
+   char *cmd, *rp;
+   int maxargs;
+   FILE *fp;
+
+    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 = malloc(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
+    printf("Executing %s\n", cmd);
+#endif
+    fflush(NULL);
+    fp = popen(cmd, "r");
+    get_string(rp, MAXPATHLEN, fp);
+#ifdef DEBUG
+    printf("Returned %s\n", rp);
+#endif
+    va_end(args);
+    free(cmd);
+    if (pclose(fp) || (strlen(rp) == 0)) {
+	free(rp);
+	return NULL;
+    }
+    return rp;
+}
+
Index: lib/lib.h
===================================================================
RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/lib/lib.h,v
retrieving revision 1.33
diff -u -r1.33 lib.h
--- lib/lib.h	2001/03/15 10:47:00	1.33
+++ lib/lib.h	2001/03/22 23:09:33
@@ -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: /usr/local/cvs/src/usr.sbin/pkg_install/lib/match.c,v
retrieving revision 1.3
diff -u -r1.3 match.c
--- lib/match.c	2001/03/14 19:46:43	1.3
+++ lib/match.c	2001/03/22 23:22:05
@@ -97,14 +97,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/str.c
===================================================================
RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/lib/str.c,v
retrieving revision 1.7
diff -u -r1.7 str.c
--- lib/str.c	2000/10/22 09:53:27	1.7
+++ lib/str.c	2001/03/03 06:21:19
@@ -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;
+}
+

--2fHTh5uZTiUOsy+g--

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?20010322183141.B23846>