Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Feb 2001 13:21:27 -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:  <20010226132127.A47052@electricjellyfish.net>
In-Reply-To: <3A99FC4E.B825CB6B@FreeBSD.org>; from sobomax@FreeBSD.org on Mon, Feb 26, 2001 at 08:48:46AM %2B0200
References:  <20010225161633.C94657@electricjellyfish.net> <200102252125.f1PLPH132145@vic.sabbo.net> <20010225192632.C37487@electricjellyfish.net> <20010225200351.A48200@electricjellyfish.net> <3A99FC4E.B825CB6B@FreeBSD.org>

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

--qDbXVdCdHGoSgWSk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Feb 26, 2001 at 08:48:46AM +0200, Maxim Sobolev wrote:
> Looks better now, however there are several placed when something like the following
> is used:
> len1 = strlen(str1);
> len2 = strlen(str2);
> tmp = calloc(len1 + len2 + 2, sizeof(char));
> if (tmp == NULL)
>     bah!();
> sprintf(tmp, "%s/%s", str1, str2);
> 
> Please replace the whole mess with:
> asprintf(&tmp, "%s/%s", str1, str2);
> if (tmp == NULL)
>     bah!();

ok, i found the bug.  needed to set pkg.head = pkg.tail = NULL before reading
in the plist.

this will be the last version of this patch for a day or so most likely, as
i'm off for a plant trip and may or may not be near a computer/checking email.

any comments are of course welcome.

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

--qDbXVdCdHGoSgWSk
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 23:30:12
@@ -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.30
diff -u -r1.30 main.c
--- info/main.c	2001/02/24 14:10:31	1.30
+++ info/main.c	2001/02/26 04:09:59
@@ -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 [-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.34
diff -u -r1.34 perform.c
--- info/perform.c	2001/02/08 17:44:00	1.34
+++ info/perform.c	2001/02/26 18:18:13
@@ -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,135 @@
 	regfree(&rex);
 
     return retval;
+}
+
+/* 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(cwd) + strlen(current) + 2, sizeof(char *));
+    asprintf(&temp, "%s/%s", cwd, current);
+    if (temp == NULL || fixed_path == 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(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 *resolved_file = NULL;
+    char *result = NULL;
+    Boolean err = FALSE;
+
+    /* if it's not a file, we'll see if it's an executable. */
+    if (isfile(file) == FALSE) {
+	if (strchr(file, '/') == NULL) {
+	    resolved_file = vpipe("which %s", file); 
+	    if (resolved_file == NULL)
+		errx(2, "file %s is not in path", file);
+	} else
+	    errx(2, "file %s cannot be found", file);
+    } else if (strncmp(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 *buf;
+	char *curdir;
+	int file_len, dir_len;
+
+	buf = calloc(MAXPATHLEN, sizeof(char));
+	curdir = getcwd(buf, MAXPATHLEN);
+
+	asprintf(&resolved_file, "%s/%s", curdir, file);
+	if (resolved_file == NULL)
+	    errx(2, strerror(errno));
+
+	free(buf);
+    } else
+	resolved_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 tmp[FILENAME_MAX];
+                char *cwd = NULL;
+		
+		sprintf(tmp, "%s/%s", entp->fts_path, CONTENTS_FNAME);
+		if (tmp == NULL)
+		    errx(2, "out of memory\n");
+
+                fp = fopen(tmp, "r");
+                if (fp) {
+		    pkg.head = pkg.tail = NULL;
+                    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(resolved_file, itr->name, cwd)) {
+				if (result != NULL) {
+				    warnx("Both %s and %s claim to have "
+					  "installed %s\n", result, 
+					  entp->fts_name, CheckFile);
+				    err = TRUE;
+				} else
+				    result = strdup(entp->fts_name);
+                            }
+                        }
+                    }
+                    free_plist(&pkg);
+                    fclose(fp);
+                }
+            }
+        }
+    }
+    if (result != NULL && err == FALSE) {
+	fprintf(stdout, "%s was installed by package %s\n", CheckFile, result);
+	free(result);
+    }
+    if (strncmp(file, "/", 1) != 0 || isfile(file) == FALSE)
+	free(resolved_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/26 00:10:37
@@ -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: 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;
+}
+

--qDbXVdCdHGoSgWSk--

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?20010226132127.A47052>