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>