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

Signed-off-by: Allan McRae <[email protected]>
---
 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

Reply via email to