[pacman-dev] [PATCH 12/13] Add regex search option to sync database file searching

Allan McRae allan at archlinux.org
Sat Jun 20 07:42:25 UTC 2015


e.g. pacman -Fsx kcm.*print.*\.so

Signed-off-by: Allan McRae <allan at archlinux.org>
---
 src/pacman/conf.h   |  3 +++
 src/pacman/files.c  | 28 ++++++++++++++++++++++------
 src/pacman/pacman.c | 12 ++++++++++--
 3 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 84b5a25..3fff900 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -88,6 +88,8 @@ typedef struct __config_t {
 	unsigned short op_s_search;
 	unsigned short op_s_upgrade;
 
+	unsigned short op_f_regex;
+
 	unsigned short group;
 	unsigned short noask;
 	unsigned int ask;
@@ -187,6 +189,7 @@ enum {
 	OP_ROOT,
 	OP_RECURSIVE,
 	OP_SEARCH,
+	OP_REGEX,
 	OP_UNREQUIRED,
 	OP_UPGRADES,
 	OP_SYSUPGRADE,
diff --git a/src/pacman/files.c b/src/pacman/files.c
index fc06ae7..5156e46 100644
--- a/src/pacman/files.c
+++ b/src/pacman/files.c
@@ -19,6 +19,7 @@
 
 #include <alpm.h>
 #include <alpm_list.h>
+#include <regex.h>
 
 /* pacman */
 #include "pacman.h"
@@ -83,24 +84,33 @@ notfound:
 	return 0;
 }
 
-static int files_search(alpm_list_t *syncs, alpm_list_t *targets) {
+static int files_search(alpm_list_t *syncs, alpm_list_t *targets, int regex) {
 	int ret = 0;
 	alpm_list_t *t;
 	const colstr_t *colstr = &config->colstr;
 
 	for(t = targets; t; t = alpm_list_next(t)) {
-		char *filename = NULL;
+		char *targ = NULL;
 		alpm_list_t *s;
 		int found = 0;
+		regex_t reg;
 
-		if((filename = strdup(t->data)) == NULL) {
+		if((targ = strdup(t->data)) == NULL) {
 			goto notfound;
 		}
 
+		if(regex) {
+			if(regcomp(&reg, targ, REG_EXTENDED | REG_NOSUB | REG_ICASE | REG_NEWLINE) != 0) {
+				/* TODO: error message */
+				goto notfound;
+			}
+		}
+
 		for(s = syncs; s; s = alpm_list_next(s)) {
 			alpm_list_t *p;
 			alpm_db_t *repo = s->data;
 			alpm_list_t *packages = alpm_db_get_pkgcache(repo);
+			int m;
 
 			for(p = packages; p; p = alpm_list_next(p)) {
 				size_t f = 0;
@@ -112,7 +122,12 @@ static int files_search(alpm_list_t *syncs, alpm_list_t *targets) {
 				while(f < files->count) {
 					c = strrchr(files->files[f].name, '/');
 					if(c && *(c + 1)) {
-						if(strcmp(c + 1, filename) == 0) {
+						if(regex) {
+							m = regexec(&reg, (c + 1), 0, 0, 0);
+						} else {
+							m = strcmp(c + 1, targ);
+						}
+						if(m == 0) {
 							match = alpm_list_add(match, strdup(files->files[f].name));
 							found = 1;
 						}
@@ -138,7 +153,8 @@ static int files_search(alpm_list_t *syncs, alpm_list_t *targets) {
 				}
 			}
 		}
-		free(filename);
+
+		free(targ);
 
 notfound:
 		if(!found) {
@@ -219,7 +235,7 @@ int pacman_files(alpm_list_t *targets)
 
 	/* search for a file */
 	if(config->op_s_search) {
-		return files_search(files_dbs, targets);
+		return files_search(files_dbs, targets, config->op_f_regex);
 	}
 
 	/* get a listing of files in sync DBs */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 951d628..c680067 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -177,7 +177,8 @@ static void usage(int op, const char * const myname)
 		} else if(op == PM_OP_FILES) {
 			addlist(_("  -l, --list           list the files owned by the queried package\n"));
 			addlist(_("  -o, --owns <file>    query the package that owns <file>\n"));
-			addlist(_("  -s, --search <regex> search package file names for matching strings\n"));
+			addlist(_("  -s, --search <file>  search package file names for matching strings\n"));
+			addlist(_("  -x, --regex          enable searching using regular expressions\n"));
 			addlist(_("  -y, --refresh        download fresh package databases from the server\n"
 			          "                       (-yy to force a refresh even if up to date)\n"));
 		}
@@ -787,6 +788,10 @@ static int parsearg_files(int opt)
 		case 'y':
 			(config->op_s_sync)++;
 			break;
+		case OP_REGEX:
+		case 'x':
+			config->op_f_regex = 1;
+			break;
 		case OP_QUIET:
 		case 'q':
 			config->quiet = 1;
@@ -802,8 +807,10 @@ static void checkargs_files(void)
 	if(config->op_q_owns) {
 		invalid_opt(config->op_q_list, "--owns", "--list");
 		invalid_opt(config->op_q_search, "--owns", "--search");
+		invalid_opt(config->op_f_regex, "--owns", "--regex");
 	} else if(config->op_q_list) {
 		invalid_opt(config->op_q_search, "--list", "--search");
+		invalid_opt(config->op_f_regex, "--list", "--regex");
 	}
 }
 
@@ -899,7 +906,7 @@ static int parseargs(int argc, char *argv[])
 	int opt;
 	int option_index = 0;
 	int result;
-	const char *optstring = "DFQRSTUVb:cdefghiklmnopqr:stuvwy";
+	const char *optstring = "DFQRSTUVb:cdefghiklmnopqr:stuvwxy";
 	static const struct option opts[] =
 	{
 		{"database",   no_argument,       0, 'D'},
@@ -933,6 +940,7 @@ static int parseargs(int argc, char *argv[])
 		{"root",       required_argument, 0, OP_ROOT},
 		{"recursive",  no_argument,       0, OP_RECURSIVE},
 		{"search",     no_argument,       0, OP_SEARCH},
+		{"regex",      no_argument,       0, OP_REGEX},
 		{"unrequired", no_argument,       0, OP_UNREQUIRED},
 		{"upgrades",   no_argument,       0, OP_UPGRADES},
 		{"sysupgrade", no_argument,       0, OP_SYSUPGRADE},
-- 
2.4.4


More information about the pacman-dev mailing list