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>