Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Feb 2001 14:15:38 -0500
From:      Garrett Rooney <rooneg@electricjellyfish.net>
To:        Maxim Sobolev <sobomax@freebsd.org>
Cc:        ports@freebsd.org, jhk@freebsd.org, gad@freebsd.org, reg@freebsd.org
Subject:   Re: [patch] which package functionality for pkg_info
Message-ID:  <20010225141537.A94657@electricjellyfish.net>
In-Reply-To: <200102251057.f1PAvor63002@vic.sabbo.net>; from sobomax@freebsd.org on Sun, Feb 25, 2001 at 12:57:08PM %2B0200
References:  <20010225001624.A41801@electricjellyfish.net> <200102251057.f1PAvor63002@vic.sabbo.net>

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

--tThc/1wpZn/ma/RB
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sun, Feb 25, 2001 at 12:57:08PM +0200, Maxim Sobolev wrote:
> I believe that some time ago Jeremy Leas <reg@FreeBSD.org> did something
> similar, but for some reasons his patch had not been merged into base
> system yet (see http://people.freebsd.org/~reg/). Therefore I would like
> to see your patches merged with his before they will be committed.

since Jeremy's patches seem rather large and all encompassing, and it looks
like they may take some time to get to the point where they can be committed,
here is a revised patch which makes the two more compatable (it now uses the
-W flag, since that's what he used, and he was here first), and to add some of
Jeremy's functionality to my patch.

this patch adds the vpipe() and get_string() functions to lib/str.c and
lib/exec.c, from Jeremy's patch, and allows one to specify an executable on
the command line (pkg_info -W vim) and then determines where it is in the
path (by calling which) and then does the search.  if you specify a relative
path to a file, it will try to compensate by tacking on the current working
directory.

Jeremy's patch has a bit more functionality in this area, in that he allows 
you to specify more than one file to look up, and he lets you look for a
shared library with another flag on the command line, but overall, this patch 
pretty produces most of what his does in this area, and isn't depending on all
of his other changes, which look like they could take some time to finish up.

comments welcome as always.

-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.

--tThc/1wpZn/ma/RB
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="pkg_info.patch"

Index: info/info.h
===================================================================
RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/info.h,v
retrieving revision 1.17
diff -u -r1.17 info.h
--- info/info.h	2001/02/08 17:43:59	1.17
+++ info/info.h	2001/02/25 08:04:46
@@ -1,4 +1,4 @@
-/* $FreeBSD$ */
+/* $FreeBSD: src/usr.sbin/pkg_install/info/info.h,v 1.17 2001/02/08 17:43:59 sobomax Exp $ */
 
 /*
  * FreeBSD install - a package for the installation and maintainance
@@ -58,6 +58,7 @@
 extern char *InfoPrefix;
 extern char PlayPen[];
 extern char *CheckPkg;
+extern char *CheckFile;
 extern match_t MatchType;
 
 extern void	show_file(char *, char *);
Index: info/main.c
===================================================================
RCS file: /usr/local/cvs/src/usr.sbin/pkg_install/info/main.c,v
retrieving revision 1.29
diff -u -r1.29 main.c
--- info/main.c	2001/02/08 17:44:00	1.29
+++ info/main.c	2001/02/25 19:00:46
@@ -28,7 +28,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 +36,7 @@
 char *InfoPrefix	= "";
 char PlayPen[FILENAME_MAX];
 char *CheckPkg		= NULL;
+char *CheckFile         = NULL;
 
 static void usage __P((void));
 
@@ -148,6 +149,10 @@
 	    CheckPkg = optarg;
 	    break;
 
+        case 'W':
+            CheckFile = optarg;
+            break;
+
 	case 'h':
 	case '?':
 	default:
@@ -185,7 +190,7 @@
     }
 
     /* If no packages, yelp */
-    if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg)
+    if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg && !CheckFile)
 	warnx("missing package name(s)"), usage();
     *pkgs = NULL;
     return pkg_perform(start);
@@ -196,7 +201,7 @@
 {
     fprintf(stderr, "%s\n%s\n%s\n",
 	"usage: pkg_info [-cdDfiIkLmopqrRsv] [-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.34
diff -u -r1.34 perform.c
--- info/perform.c	2001/02/08 17:44:00	1.34
+++ info/perform.c	2001/02/25 19:03:45
@@ -27,6 +27,10 @@
 #include "info.h"
 
 #include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
 #include <err.h>
 #include <glob.h>
 #include <fts.h>
@@ -36,6 +40,8 @@
 static int fname_cmp(const FTSENT **, const FTSENT **);
 static int pkg_do(char *);
 static int rexs_match(char **, char *);
+static int find_pkg(char *, char *);
+static int cmp_path(const char *, const char *, const char *);
 
 int
 pkg_perform(char **pkgs)
@@ -55,6 +61,8 @@
 	snprintf(buf, FILENAME_MAX, "%s/%s", tmp, CheckPkg);
 	return abs(access(buf, R_OK));
 	/* Not reached */
+    } else if (CheckFile) {
+        return find_pkg(tmp, CheckFile);
     }
 
     switch (MatchType) {
@@ -352,4 +360,138 @@
 	regfree(&rex);
 
     return retval;
+}
+
+/* comparison to see if two paths we're on matches the one we're 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 cwd_len, current_len, total_len, rval;
+
+    cwd_len = strlen(cwd);
+    current_len = strlen(current);
+    total_len = cwd_len + current_len + 2;
+    temp = calloc(total_len, sizeof(char *));
+    fixed_path = calloc(total_len, sizeof(char *));
+    if (temp == NULL || fixed_path == NULL) {
+        errx(2, "out of memory\n");
+    }
+    strncpy(temp, cwd, cwd_len);
+    strncat(temp, "/", 1);
+    strncat(temp, current, current_len);
+
+    /* 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++;
+    }
+
+    if (!strncmp(target, fixed_path, strlen(target)))
+	rval = 1;
+    else
+	rval = 0;
+    free(temp);
+    free(fixed_path);
+    return rval;
+}
+
+/* look through package dbs in db_dir and find which package installed file */
+static int 
+find_pkg(char *db_dir, char *file)
+{
+    FTS *ftsp;
+    FTSENT *entp;
+    char *dir[2];
+    char *res_file;
+
+    /* if it's not a file, we'll see if it's an executable. */
+    if (!isfile(file)) {
+	res_file = vpipe("which %s", file); 
+        if (res_file == NULL)
+	    errx(2, "file not in path\n");
+    } else if (strncmp(file, "/", 1)) {
+	/* if it is a file, and it doesn't start with a /, then we assume it's 
+	 * a relative path (which may or may not be a good assumption, but it's 
+	 * better than nothing. */
+	char *buf;
+	char *curdir;
+	int file_len, dir_len;
+
+	buf = calloc(MAXPATHLEN, sizeof(char));
+	curdir = getcwd(buf, MAXPATHLEN);
+
+	file_len = strlen(file);
+	dir_len = strlen(curdir);
+
+	res_file = calloc(file_len + dir_len + 2, sizeof(char));
+	if (res_file == NULL)
+	    errx(2, strerror(errno));
+
+	strncpy(res_file, curdir, dir_len);
+	strncat(res_file, "/", 1);
+	strncat(res_file, file, file_len);
+
+	free(buf);
+    } else
+	res_file = file;
+
+    dir[0] = db_dir;
+    dir[1] = NULL;
+
+    ftsp = fts_open(dir, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, fname_cmp);
+   
+    if (ftsp != NULL) {
+        while((entp = fts_read(ftsp)) != NULL) {
+            if (entp->fts_level == 1 && entp->fts_info == FTS_D) {
+                Package pkg;
+                PackingList itr;
+                FILE *fp;
+                char buf[FILENAME_MAX];
+                char *cwd = NULL;
+
+                bzero(buf, FILENAME_MAX);
+                strncpy(buf, entp->fts_path, strlen(entp->fts_path));
+                strncat(buf, "/", 1);
+                strncat(buf, CONTENTS_FNAME, strlen(CONTENTS_FNAME));
+
+                fp = fopen(buf, "r");
+                if (fp) {
+                    read_plist(&pkg, 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) {
+                            if (cmp_path(res_file, itr->name, cwd)) {
+                                fprintf(stdout,
+                                        "%s is from package %s\n",
+                                        CheckFile,
+                                        entp->fts_name);
+				if (strncmp(file, "/", 1))
+				    free(res_file);
+                                free_plist(&pkg);
+                                fclose(fp);
+                                fts_close(ftsp);
+                                return 1;
+                            }
+                        }
+                    }
+                    free_plist(&pkg);
+                    fclose(fp);
+                }
+            }
+        }
+    }
+    if (strncmp(file, "/", 1))
+	free(res_file);
+    fts_close(ftsp);
+    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/02/25 19:00:23
@@ -25,10 +25,11 @@
 .Nd a utility for displaying information on software packages
 .Sh SYNOPSIS
 .Nm
-.Op Fl cdDfgGiIkLmopqrRsvx
+.Op Fl cdDfgGiIkLmopqrRsvWx
 .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,10 @@
 .Nm
 automatically expands shell glob patterns in the
 .Ar pkg-name ) .
+.It Fl W
+For the specified
+.Ar filename
+argument, show which package(s) it belongs to.
 .It Fl x
 Treat the
 .Ar pkg-name
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/02/25 18:49:43
@@ -60,3 +60,48 @@
     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.31
diff -u -r1.31 lib.h
--- lib/lib.h	2000/09/18 07:41:48	1.31
+++ lib/lib.h	2001/02/25 18:58:22
@@ -107,6 +107,7 @@
 /* Prototypes */
 /* Misc */
 int		vsystem(const char *, ...);
+char		*vpipe(const char *, ...);
 void		cleanup(int);
 char		*make_playpen(char *, size_t);
 char		*where_playpen(void);
@@ -121,6 +122,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/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/02/25 18:57:50
@@ -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;
+}
+

--tThc/1wpZn/ma/RB--

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?20010225141537.A94657>