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>