match.c revision 80042
173134Ssobomax#ifndef lint 273134Ssobomaxstatic const char rcsid[] = 373134Ssobomax "$FreeBSD: head/usr.sbin/pkg_install/lib/match.c 80042 2001-07-20 13:20:32Z sobomax $"; 473134Ssobomax#endif 573134Ssobomax 673134Ssobomax/* 773134Ssobomax * FreeBSD install - a package for the installation and maintainance 873134Ssobomax * of non-core utilities. 973134Ssobomax * 1073134Ssobomax * Redistribution and use in source and binary forms, with or without 1173134Ssobomax * modification, are permitted provided that the following conditions 1273134Ssobomax * are met: 1373134Ssobomax * 1. Redistributions of source code must retain the above copyright 1473134Ssobomax * notice, this list of conditions and the following disclaimer. 1573134Ssobomax * 2. Redistributions in binary form must reproduce the above copyright 1673134Ssobomax * notice, this list of conditions and the following disclaimer in the 1773134Ssobomax * documentation and/or other materials provided with the distribution. 1873134Ssobomax * 1973134Ssobomax * Maxim Sobolev 2073134Ssobomax * 24 February 2001 2173134Ssobomax * 2273134Ssobomax * Routines used to query installed packages. 2373134Ssobomax * 2473134Ssobomax */ 2573134Ssobomax 2673134Ssobomax#include "lib.h" 2773134Ssobomax#include <err.h> 2873134Ssobomax#include <fnmatch.h> 2973134Ssobomax#include <fts.h> 3073134Ssobomax#include <regex.h> 3173134Ssobomax 3273134Ssobomax/* 3373134Ssobomax * Simple structure representing argv-like 3473134Ssobomax * NULL-terminated list. 3573134Ssobomax */ 3673134Ssobomaxstruct store { 3773134Ssobomax int currlen; 3873134Ssobomax int used; 3973134Ssobomax char **store; 4073134Ssobomax}; 4173134Ssobomax 4273134Ssobomaxstatic int rex_match(char *, char *); 4373144Ssobomaxstatic int storeappend(struct store *, const char *); 4473134Ssobomaxstatic int fname_cmp(const FTSENT **, const FTSENT **); 4573134Ssobomax 4673134Ssobomax/* 4773134Ssobomax * Function to query names of installed packages. 4873134Ssobomax * MatchType - one of MATCH_ALL, MATCH_REGEX, MATCH_GLOB; 4973134Ssobomax * patterns - NULL-terminated list of glob or regex patterns 5073134Ssobomax * (could be NULL for MATCH_ALL); 5173134Ssobomax * retval - return value (could be NULL if you don't want/need 5273134Ssobomax * return value). 5373134Ssobomax * Returns NULL-terminated list with matching names. 5473134Ssobomax * Names in list returned are dynamically allocated and should 5573134Ssobomax * not be altered by the caller. 5673134Ssobomax */ 5773134Ssobomaxchar ** 5873134Ssobomaxmatchinstalled(match_t MatchType, char **patterns, int *retval) 5973134Ssobomax{ 6074258Ssobomax int i, errcode, len; 6173144Ssobomax char *tmp, *matched; 6273134Ssobomax char *paths[2]; 6373134Ssobomax static struct store *store = NULL; 6473134Ssobomax FTS *ftsp; 6573134Ssobomax FTSENT *f; 6674258Ssobomax Boolean *lmatched; 6773134Ssobomax 6873134Ssobomax if (store == NULL) { 6973134Ssobomax store = malloc(sizeof *store); 7073144Ssobomax if (store == NULL) { 7173144Ssobomax warnx("%s(): malloc() failed", __FUNCTION__); 7273144Ssobomax if (retval != NULL) 7373144Ssobomax *retval = 1; 7473144Ssobomax return NULL; 7573144Ssobomax } 7673134Ssobomax store->currlen = 0; 7773134Ssobomax store->store = NULL; 7873144Ssobomax } else 7973144Ssobomax if (store->store != NULL) 8073134Ssobomax /* Free previously allocated memory */ 8173134Ssobomax for (i = 0; store->store[i] != NULL; i++) 8273134Ssobomax free(store->store[i]); 8373134Ssobomax store->used = 0; 8473134Ssobomax 8573134Ssobomax if (retval != NULL) 8673134Ssobomax *retval = 0; 8773134Ssobomax 8873134Ssobomax tmp = getenv(PKG_DBDIR); 8973134Ssobomax if (!tmp) 9073134Ssobomax tmp = DEF_LOG_DIR; 9173134Ssobomax if (!isdir(tmp)) { 9273134Ssobomax if (retval != NULL) 9373134Ssobomax *retval = 1; 9473134Ssobomax return NULL; 9573134Ssobomax /* Not reached */ 9673134Ssobomax } 9773134Ssobomax 9874258Ssobomax /* Count number of patterns */ 9974699Ssobomax if (patterns != NULL) { 10074699Ssobomax for (len = 0; patterns[len]; len++) {} 10174699Ssobomax lmatched = alloca(sizeof(*lmatched) * len); 10274699Ssobomax if (lmatched == NULL) { 10374699Ssobomax warnx("%s(): alloca() failed", __FUNCTION__); 10474699Ssobomax if (retval != NULL) 10574699Ssobomax *retval = 1; 10674699Ssobomax return NULL; 10774699Ssobomax } 10874699Ssobomax } else 10974699Ssobomax len = 0; 11074699Ssobomax 11174258Ssobomax for (i = 0; i < len; i++) 11274258Ssobomax lmatched[i] = FALSE; 11374258Ssobomax 11473134Ssobomax paths[0] = tmp; 11573134Ssobomax paths[1] = NULL; 11673134Ssobomax ftsp = fts_open(paths, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, fname_cmp); 11773134Ssobomax if (ftsp != NULL) { 11873134Ssobomax while ((f = fts_read(ftsp)) != NULL) { 11973134Ssobomax if (f->fts_info == FTS_D && f->fts_level == 1) { 12073134Ssobomax fts_set(ftsp, f, FTS_SKIP); 12173144Ssobomax matched = NULL; 12273144Ssobomax errcode = 0; 12373144Ssobomax if (MatchType == MATCH_ALL) 12473144Ssobomax matched = f->fts_name; 12573144Ssobomax else 12673144Ssobomax for (i = 0; patterns[i]; i++) { 12773144Ssobomax switch (MatchType) { 12873144Ssobomax case MATCH_REGEX: 12973144Ssobomax errcode = rex_match(patterns[i], f->fts_name); 13073144Ssobomax if (errcode == 1) { 13173144Ssobomax matched = f->fts_name; 13273144Ssobomax errcode = 0; 13373144Ssobomax } 13473144Ssobomax break; 13573144Ssobomax case MATCH_GLOB: 13674258Ssobomax if (fnmatch(patterns[i], f->fts_name, 0) == 0) { 13773144Ssobomax matched = f->fts_name; 13874258Ssobomax lmatched[i] = TRUE; 13974258Ssobomax } 14073144Ssobomax break; 14173144Ssobomax default: 14273144Ssobomax break; 14373134Ssobomax } 14473144Ssobomax if (matched != NULL || errcode != 0) 14573144Ssobomax break; 14673134Ssobomax } 14773144Ssobomax if (errcode == 0 && matched != NULL) 14873144Ssobomax errcode = storeappend(store, matched); 14973144Ssobomax if (errcode != 0) { 15073144Ssobomax if (retval != NULL) 15173144Ssobomax *retval = 1; 15273144Ssobomax return NULL; 15373144Ssobomax /* Not reached */ 15473134Ssobomax } 15573134Ssobomax } 15673134Ssobomax } 15773134Ssobomax fts_close(ftsp); 15873134Ssobomax } 15973134Ssobomax 16074258Ssobomax if (MatchType == MATCH_GLOB) { 16174258Ssobomax for (i = 0; i < len; i++) 16274258Ssobomax if (lmatched[i] == FALSE) 16374258Ssobomax storeappend(store, patterns[i]); 16474258Ssobomax } 16574258Ssobomax 16673134Ssobomax if (store->used == 0) 16773134Ssobomax return NULL; 16873134Ssobomax else 16973134Ssobomax return store->store; 17073134Ssobomax} 17173134Ssobomax 17273134Ssobomax/* 17373134Ssobomax * Returns 1 if specified pkgname matches RE pattern. 17473134Ssobomax * Otherwise returns 0 if doesn't match or -1 if RE 17573134Ssobomax * engine reported an error (usually invalid syntax). 17673134Ssobomax */ 17773134Ssobomaxstatic int 17873134Ssobomaxrex_match(char *pattern, char *pkgname) 17973134Ssobomax{ 18073134Ssobomax char errbuf[128]; 18173134Ssobomax int errcode; 18273134Ssobomax int retval; 18373134Ssobomax regex_t rex; 18473134Ssobomax 18573134Ssobomax retval = 0; 18673134Ssobomax 18773134Ssobomax errcode = regcomp(&rex, pattern, REG_BASIC | REG_NOSUB); 18873134Ssobomax if (errcode == 0) 18973134Ssobomax errcode = regexec(&rex, pkgname, 0, NULL, 0); 19073134Ssobomax 19173134Ssobomax if (errcode == 0) { 19273134Ssobomax retval = 1; 19373134Ssobomax } else if (errcode != REG_NOMATCH) { 19473134Ssobomax regerror(errcode, &rex, errbuf, sizeof(errbuf)); 19573134Ssobomax warnx("%s: %s", pattern, errbuf); 19673134Ssobomax retval = -1; 19773134Ssobomax } 19873134Ssobomax 19973134Ssobomax regfree(&rex); 20073134Ssobomax 20173134Ssobomax return retval; 20273134Ssobomax} 20373134Ssobomax 20473144Ssobomaxstatic int 20573134Ssobomaxstoreappend(struct store *store, const char *item) 20673134Ssobomax{ 20773134Ssobomax if (store->used + 2 > store->currlen) { 20873134Ssobomax store->currlen += 16; 20980042Ssobomax store->store = reallocf(store->store, 21080042Ssobomax store->currlen * sizeof(*(store->store))); 21173144Ssobomax if (store->store == NULL) { 21280042Ssobomax store->currlen = 0; 21380042Ssobomax warnx("%s(): reallocf() failed", __FUNCTION__); 21473144Ssobomax return 1; 21573144Ssobomax } 21673134Ssobomax } 21773134Ssobomax 21873134Ssobomax asprintf(&(store->store[store->used]), "%s", item); 21973144Ssobomax if (store->store[store->used] == NULL) { 22073144Ssobomax warnx("%s(): malloc() failed", __FUNCTION__); 22173144Ssobomax return 1; 22273144Ssobomax } 22373134Ssobomax store->used++; 22473134Ssobomax store->store[store->used] = NULL; 22573144Ssobomax 22673144Ssobomax return 0; 22773134Ssobomax} 22873134Ssobomax 22973134Ssobomaxstatic int 23073134Ssobomaxfname_cmp(const FTSENT **a, const FTSENT **b) 23173134Ssobomax{ 23273134Ssobomax return strcmp((*a)->fts_name, (*b)->fts_name); 23373134Ssobomax} 234