From owner-freebsd-ports Mon Feb 26 7:35:21 2001 Delivered-To: freebsd-ports@freebsd.org Received: from isris.pair.com (isris.pair.com [209.68.2.39]) by hub.freebsd.org (Postfix) with SMTP id 9100137B65D for ; Mon, 26 Feb 2001 07:34:59 -0800 (PST) (envelope-from rooneg@isris.pair.com) Received: (qmail 28474 invoked by uid 3130); 26 Feb 2001 15:34:57 -0000 Date: Mon, 26 Feb 2001 10:34:57 -0500 From: Garrett Rooney To: Maxim Sobolev Cc: ports@FreeBSD.org, jhk@FreeBSD.org, gad@FreeBSD.org, reg@FreeBSD.org Subject: Re: [patch] which package functionality for pkg_info Message-ID: <20010226103457.A24987@electricjellyfish.net> References: <20010225161633.C94657@electricjellyfish.net> <200102252125.f1PLPH132145@vic.sabbo.net> <20010225192632.C37487@electricjellyfish.net> <20010225200351.A48200@electricjellyfish.net> <3A99FC4E.B825CB6B@FreeBSD.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="liOOAslEiF7prFVr" Content-Disposition: inline User-Agent: Mutt/1.2.5i In-Reply-To: <3A99FC4E.B825CB6B@FreeBSD.org>; from sobomax@FreeBSD.org on Mon, Feb 26, 2001 at 08:48:46AM +0200 Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org --liOOAslEiF7prFVr 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, now i'm completely confused. i replaced one such instance just fine, but if i replace the other, pkg_info -W crashes, even if it never goes near that code. i'm attatching a patch with what i've got, but be warned, it will crash. if you comment out lines 442-444 and uncomment the section immediately preceding them, it will work again. i'm sure i'm making some trivial mistake, but i just can't see it at the moment and it's driving me crazy. -- 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. --liOOAslEiF7prFVr 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 15:33:07 @@ -27,6 +27,10 @@ #include "info.h" #include +#include +#include +#include +#include #include #include #include @@ -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,141 @@ 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); + + file_len = strlen(file); + dir_len = strlen(curdir); + + /*resolved_file = calloc(file_len + dir_len + 2, sizeof(char)); + if (resolved_file == NULL) + errx(2, strerror(errno)); + sprintf(resolved_file, "%s/%s", curdir, file);*/ + 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) { + 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 (isfile(file)) + 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; +} + --liOOAslEiF7prFVr-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message