From eb5ddda829ab0431f0dca5defa27b67f1669bdf6 Mon Sep 17 00:00:00 2001 From: Eygene Ryabinkin Date: Mon, 6 Oct 2008 18:43:50 +0400 Subject: [PATCH 2/4] Add function match_get_pkgorigin() This new function enables one to obtain the package origin during the matching session. I had also turned origin search into the static function and fixed potential bug with snprintf(tmp, SIZE, "%s/%s", tmp, whatever): the order of access to the 'tmp' pointers is not determined, so this can lead to the funny results. Signed-off-by: Eygene Ryabinkin --- usr.sbin/pkg_install/lib/lib.h | 1 + usr.sbin/pkg_install/lib/match.c | 117 +++++++++++++++++++++++++++----------- 2 files changed, 85 insertions(+), 33 deletions(-) diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h index fe7a5bc..559d10b 100644 --- a/usr.sbin/pkg_install/lib/lib.h +++ b/usr.sbin/pkg_install/lib/lib.h @@ -233,6 +233,7 @@ void match_end(struct match_session *); Boolean match_next_package(struct match_session *); int match_matches(struct match_session *, char *); const char *match_get_pkgname(struct match_session *); +const char *match_get_pkgorigin(struct match_session *); /* Dependencies */ int sortdeps(char **); diff --git a/usr.sbin/pkg_install/lib/match.c b/usr.sbin/pkg_install/lib/match.c index 3a7edb2..b4d1c82 100644 --- a/usr.sbin/pkg_install/lib/match.c +++ b/usr.sbin/pkg_install/lib/match.c @@ -47,11 +47,20 @@ struct match_session { match_t match_type;; }; +/* Return values for getorigin() */ +enum st_getorigin { + e_origin_ok = 0, /* All OK */ + e_origin_emptydir, /* Package directory is empty */ + e_origin_infocorrupt, /* Package information is corrupt */ + e_origin_missing /* Package origin is not recorded */ +}; + static int rex_match(const char *, const char *, int); static int csh_match(const char *, const char *, int); struct store *storecreate(struct store *); static int storeappend(struct store *, const char *); static int fname_cmp(const FTSENT * const *, const FTSENT * const *); +static enum st_getorigin getorigin(const char *_name, char **_origin); /* * Function to query names of installed packages. @@ -244,45 +253,32 @@ pattern_match(match_t MatchType, char *pattern, const char *pkgname) } /* - * Synopsis is similar to matchinstalled(), but use origin - * as a key for matching packages. + * Obtains package origin from the package name. + * Arguments: + * - name, the name of the package; + * - origin, pointer to a pointer where origin will be saved. + * On error, *origin will be NULLified. */ -char *** -matchallbyorigin(const char **origins, int *retval) +static enum st_getorigin getorigin(const char *name, char **origin) { - char **installed, **allorigins = NULL; - char ***matches = NULL; - int i, j; - - if (retval != NULL) - *retval = 0; - - installed = matchinstalled(MATCH_ALL, NULL, retval); - if (installed == NULL) - return NULL; - - /* Gather origins for all installed packages */ - for (i = 0; installed[i] != NULL; i++) { FILE *fp; - char *buf, *cp, tmp[PATH_MAX]; + char *cp, tmp[PATH_MAX]; int cmd; - allorigins = realloc(allorigins, (i + 1) * sizeof(*allorigins)); - allorigins[i] = NULL; - - snprintf(tmp, PATH_MAX, "%s/%s", LOG_DIR, installed[i]); + *origin = NULL; + snprintf(tmp, PATH_MAX, "%s/%s", LOG_DIR, name); /* * SPECIAL CASE: ignore empty dirs, since we can can see them * during port installation. */ if (isemptydir(tmp)) - continue; - snprintf(tmp, PATH_MAX, "%s/%s", tmp, CONTENTS_FNAME); + return e_origin_emptydir; + if (PATH_MAX - strlen(tmp) > 0) + snprintf(tmp + strlen(tmp), PATH_MAX - strlen(tmp), + "/%s", CONTENTS_FNAME); fp = fopen(tmp, "r"); - if (fp == NULL) { - warnx("the package info for package '%s' is corrupt", installed[i]); - continue; - } + if (fp == NULL) + return e_origin_infocorrupt; cmd = -1; while (fgets(tmp, sizeof(tmp), fp)) { @@ -297,14 +293,53 @@ matchallbyorigin(const char **origins, int *retval) continue; cmd = plist_cmd(tmp + 1, &cp); if (cmd == PLIST_ORIGIN) { - asprintf(&buf, "%s", cp); - allorigins[i] = buf; + asprintf(origin, "%s", cp); break; } } - if (cmd != PLIST_ORIGIN && ( Verbose || 0 != strncmp("bsdpan-", installed[i], 7 ) ) ) - warnx("package %s has no origin recorded", installed[i]); fclose(fp); + if (cmd != PLIST_ORIGIN) + return e_origin_missing; + else + return e_origin_ok; +} + +/* + * Synopsis is similar to matchinstalled(), but use origin + * as a key for matching packages. + */ +char *** +matchallbyorigin(const char **origins, int *retval) +{ + char **installed, **allorigins = NULL; + char ***matches = NULL; + int i, j; + + if (retval != NULL) + *retval = 0; + + installed = matchinstalled(MATCH_ALL, NULL, retval); + if (installed == NULL) + return NULL; + + /* Gather origins for all installed packages */ + for (i = 0; installed[i] != NULL; i++) { + allorigins = realloc(allorigins, (i + 1) * sizeof(*allorigins)); + allorigins[i] = NULL; + + switch (getorigin(installed[i], &allorigins[i])) { + case e_origin_ok: + break; + case e_origin_emptydir: + continue; + case e_origin_infocorrupt: + warnx("the package info for package '%s' is corrupt", installed[i]); + continue; + case e_origin_missing: + if (Verbose || 0 != strncmp("bsdpan-", installed[i], 7)) + warnx("package %s has no origin recorded", installed[i]); + break; + } } /* Resolve origins into package names, retaining the sequence */ @@ -511,11 +546,27 @@ match_get_pkgname(struct match_session *sess) { if (sess == NULL || sess->ftsp == NULL || sess->f == NULL) return NULL; - + return (const char *)(sess->f->fts_name); } /* + * Returns origin of the current package. Caller should free the + * returned value when it will not be needed anymore. + */ +const char * +match_get_pkgorigin(struct match_session *sess) +{ + char *origin; + + if (sess == NULL || sess->ftsp == NULL || sess->f == NULL) + return NULL; + + getorigin(sess->f->fts_name, &origin); + return (const char *)origin; +} + +/* * Returns 1 if specified pkgname matches RE pattern. * Otherwise returns 0 if doesn't match or -1 if RE * engine reported an error (usually invalid syntax). -- 1.6.2.4