From 23bc2c4482ca5ca9a31c4a4e17738938d00dbeba Mon Sep 17 00:00:00 2001 From: Eygene Ryabinkin Date: Tue, 26 Aug 2008 14:59:29 +0400 Subject: [PATCH 1/4] Add functions for traversing package database and matching package names This functions will help one who wants to search package database for the given package names or name globs and do something more than just collecting the names of the matched packages. They are skeleton-like functions and are supposed to be used as package database iterator and a handy match function: ----- session = match_begin(MATCH_STYLE); while (match_next_package(session)) { ... pkg_name = match_get_pkgname(session); ... match_matches(session, template); ... } match_end(session); ----- Signed-off-by: Eygene Ryabinkin --- usr.sbin/pkg_install/lib/lib.h | 5 ++ usr.sbin/pkg_install/lib/match.c | 110 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h index 422912e..fe7a5bc 100644 --- a/usr.sbin/pkg_install/lib/lib.h +++ b/usr.sbin/pkg_install/lib/lib.h @@ -228,6 +228,11 @@ char **matchbyorigin(const char *, int *); char ***matchallbyorigin(const char **, int *); int isinstalledpkg(const char *name); int pattern_match(match_t MatchType, char *pattern, const char *pkgname); +struct match_session *match_begin(match_t); +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 *); /* Dependencies */ int sortdeps(char **); diff --git a/usr.sbin/pkg_install/lib/match.c b/usr.sbin/pkg_install/lib/match.c index 1f8b02a..3a7edb2 100644 --- a/usr.sbin/pkg_install/lib/match.c +++ b/usr.sbin/pkg_install/lib/match.c @@ -37,6 +37,16 @@ struct store { char **store; }; +/* + * Structure that holds information about package traversal + * and matching session. + */ +struct match_session { + FTS *ftsp; + FTSENT *f; + match_t match_type;; +}; + static int rex_match(const char *, const char *, int); static int csh_match(const char *, const char *, int); struct store *storecreate(struct store *); @@ -91,10 +101,10 @@ matchinstalled(match_t MatchType, char **patterns, int *retval) if (retval != NULL) *retval = 1; return NULL; - } + } } else len = 0; - + for (i = 0; i < len; i++) lmatched[i] = FALSE; @@ -107,7 +117,7 @@ matchinstalled(match_t MatchType, char **patterns, int *retval) errcode = 0; if (MatchType == MATCH_ALL) matched = f->fts_name; - else + else for (i = 0; patterns[i]; i++) { errcode = pattern_match(MatchType, patterns[i], f->fts_name); if (errcode == 1) { @@ -359,7 +369,7 @@ struct iip_memo { LIST_HEAD(, iip_memo) iip_memo = LIST_HEAD_INITIALIZER(iip_memo); /* - * + * * Return 1 if the specified package is installed, * 0 if not, and -1 if an error occured. */ @@ -374,7 +384,7 @@ isinstalledpkg(const char *name) if (strcmp(memo->iip_name, name) == 0) return memo->iip_result; } - + buf2 = NULL; asprintf(&buf, "%s/%s", LOG_DIR, name); if (buf == NULL) @@ -416,6 +426,96 @@ errout: } /* + * Prepares package database for the traversal. + */ +struct match_session * +match_begin(match_t MatchType) +{ + struct match_session *sess; + const char *paths[2] = {LOG_DIR, NULL}; + + if (!isdir(paths[0])) + return NULL; + + sess = (struct match_session *)malloc(sizeof(*sess)); + if (sess == NULL) + return NULL; + bzero((void *)sess, sizeof(*sess)); + + sess->match_type = MatchType; + sess->ftsp = fts_open((char * const *)(uintptr_t)paths, + FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, fname_cmp); + if (sess->ftsp == NULL) { + free((void *)sess); + return NULL; + } + + return sess; +} + +/* + * Ends package traversal session. + */ +void +match_end(struct match_session *sess) +{ + if (sess == NULL) + return; + if (sess->ftsp != NULL) + fts_close(sess->ftsp); + free((void *)sess); + return; +} + +/* + * Proceeds to the next package in the session. + * Returns TRUE if package was selected, FALSE otherwise. + */ +Boolean +match_next_package(struct match_session *sess) +{ + if (sess == NULL || sess->ftsp == NULL) + return FALSE; + + while ((sess->f = fts_read(sess->ftsp)) != NULL) { + if (sess->f->fts_info == FTS_D && + sess->f->fts_level == 1) { + fts_set(sess->ftsp, sess->f, FTS_SKIP); + return TRUE; + } + } + return FALSE; +} + +/* + * Matches the current package name against the given pattern. + * Returns 1 if pattern matches, 0 if not matches and -1 for + * the error condition. + */ +int +match_matches(struct match_session *sess, char *pattern) +{ + if (sess == NULL || sess->ftsp == NULL || sess->f == NULL || + pattern == NULL) + return FALSE; + + return pattern_match(sess->match_type, pattern, + sess->f->fts_name); +} + +/* + * Returns name of the current package. + */ +const char * +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 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