Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Feb 2001 23:40:16 -0800
From:      Jordan Hubbard <jkh@osd.bsdi.com>
To:        rooneg@electricjellyfish.net
Cc:        ports@freebsd.org, jhk@freebsd.org, sobomax@freebsd.org, gad@freebsd.org
Subject:   Re: [patch] which package functionality for pkg_info
Message-ID:  <20010224234016X.jkh@osd.bsdi.com>
In-Reply-To: <20010225001624.A41801@electricjellyfish.net>
References:  <20010225001624.A41801@electricjellyfish.net>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Sat_Feb_24_23:39:40_2001_41)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

From: Garrett Rooney <rooneg@electricjellyfish.net>
Subject: [patch] which package functionality for pkg_info
Date: Sun, 25 Feb 2001 00:16:24 -0500

> a few days ago, i got frustrated with how much of a pain it was to determine
> what package a given file on my system came from.  rather than simply using
> the old 'grep /var/db/pkg/*/+CONTENTS' method, i wrote a script to do some
> better searching, and then after a little inspection of the pkg_info code, i
> came up with a patch adding this functionality to pkg_info.

Hmmm.  This is not a bad start, and here are some diffs tighten all of
this up as well as fix some style bugs, add a man page entry for the
new option and, finally, address the one truly fatal flaw which is in
using realpath().  You actually *don't* want to use realpath() since
that will simply cause the algorithm to fail for cases where
/usr/local or /usr/X11R6 (or any sub-component thereof) is symlinked
off somewhere else.  This was certainly true in my case, where just
about everything of size is symlinked off to someplace like /vol1 and
pkg_info -w can't find anything I give it in /usr/local or /usr/X11R6.

- Jordan

----Next_Part(Sat_Feb_24_23:39:40_2001_41)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="info.diff"

Index: info.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/info.h,v
retrieving revision 1.11.2.5
diff -u -r1.11.2.5 info.h
--- info.h	2001/02/20 23:32:49	1.11.2.5
+++ info.h	2001/02/25 06:57:01
@@ -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: main.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/main.c,v
retrieving revision 1.22.2.7
diff -u -r1.22.2.7 main.c
--- main.c	2001/02/20 23:32:49	1.22.2.7
+++ main.c	2001/02/25 06:59:20
@@ -28,7 +28,7 @@
   "$FreeBSD: src/usr.sbin/pkg_install/info/main.c,v 1.22.2.7 2001/02/20 23:32:49 jkh Exp $";
 #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: perform.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/perform.c,v
retrieving revision 1.29.2.5
diff -u -r1.29.2.5 perform.c
--- perform.c	2001/02/20 23:32:49	1.29.2.5
+++ perform.c	2001/02/25 07:30:23
@@ -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,107 @@
 	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");
+        exit(2);
+    }
+    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];
+    struct stat st;
+
+    if (stat(file, &st) == -1)
+	errx(2, strerror(errno));
+
+    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(file, itr->name, cwd)) {
+                                fprintf(stdout,
+                                        "%s is from package %s\n",
+                                        CheckFile,
+                                        entp->fts_name);
+                                free_plist(&pkg);
+                                fclose(fp);
+                                fts_close(ftsp);
+                                return 1;
+                            }
+                        }
+                    }
+                    free_plist(&pkg);
+                    fclose(fp);
+                }
+            }
+        }
+    }
+    fts_close(ftsp);
+    return 0;
 }
Index: pkg_info.1
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/info/pkg_info.1,v
retrieving revision 1.24.2.8
diff -u -r1.24.2.8 pkg_info.1
--- pkg_info.1	2001/02/20 23:32:49	1.24.2.8
+++ pkg_info.1	2001/02/25 07:23:06
@@ -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

----Next_Part(Sat_Feb_24_23:39:40_2001_41)----

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?20010224234016X.jkh>