It is now possible to invert patterns in NoExtract and NoUpgrade. This feature allows users to whitelist certain files that were previously blacklisted by another entry. --- Fixed remarks by Andrew: - docs now mention the need to escape leading exclamation mark or backslash. - _alpm_fnmatch_patterns now iterates over NoExtract in reverse doc/pacman.conf.5.txt | 10 ++++++++-- lib/libalpm/add.c | 4 ++-- lib/libalpm/util.c | 31 +++++++++++++++++++++++++++++++ lib/libalpm/util.h | 1 + 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index 83a399e..049faee 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -128,7 +128,10 @@ Options '.pacnew' extension. These files refer to files in the package archive, so do not include the leading slash (the RootDir) when specifying them. Shell-style glob patterns - are allowed. + are allowed. It is possible to invert matches by prepending a file with + an exclamation mark. Inverted files will result in previously blacklisted + files being whitelisted again. Subsequent matches will override previous + ones. A leading literal exclamation mark or backslash needs to be escaped. *NoExtract =* file ...:: All files listed with a `NoExtract` directive will never be extracted from @@ -138,7 +141,10 @@ Options from the 'apache' package. These files refer to files in the package archive, so do not include the leading slash (the RootDir) when specifying them. Shell-style glob patterns - are allowed. + are allowed. It is possible to invert matches by prepending a file with + an exclamation mark. Inverted files will result in previously blacklisted + files being whitelisted again. Subsequent matches will override previous + ones. A leading literal exclamation mark or backslash needs to be escaped. *CleanMethod =* KeepInstalled &| KeepCurrent:: If set to `KeepInstalled` (the default), the '-Sc' operation will clean diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index c20e7c6..6e12f56 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -183,7 +183,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, } /* if a file is in NoExtract then we never extract it */ - if(alpm_list_find(handle->noextract, entryname, _alpm_fnmatch)) { + if(_alpm_fnmatch_patterns(handle->noextract, entryname) == 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract," " skipping extraction of %s\n", entryname, filename); @@ -245,7 +245,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive, } else { /* case 3: */ /* if file is in NoUpgrade, don't touch it */ - if(alpm_list_find(handle->noupgrade, entryname, _alpm_fnmatch)) { + if(_alpm_fnmatch_patterns(handle->noupgrade, entryname) == 0) { notouch = 1; } else { alpm_backup_t *backup; diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index f84fb66..15c1a67 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -1249,6 +1249,37 @@ int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int a return ret; } +/** Checks whether a string matches at least one shell wildcard pattern. + * Checks for matches with fnmatch. Matches are inverted by prepending + * patterns with an exclamation mark. Preceding exclamation marks may be + * escaped. Subsequent matches override previous ones. + * @param patterns patterns to match against + * @param string string to check against pattern + * @return 0 if string matches pattern, negative if they don't match and + * positive if the last match was inverted + */ +int _alpm_fnmatch_patterns(alpm_list_t *patterns, const char *string) +{ + alpm_list_t *i; + char *pattern; + short inverted; + + for(i = alpm_list_last(patterns); i; i = alpm_list_previous(i)) { + pattern = i->data; + + inverted = pattern[0] == '!'; + if(inverted || pattern[0] == '\\') { + pattern++; + } + + if(_alpm_fnmatch(pattern, string) == 0) { + return inverted; + } + } + + return -1; +} + /** Checks whether a string matches a shell wildcard pattern. * Wrapper around fnmatch. * @param pattern pattern to match against diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 56031f3..24b7c22 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -140,6 +140,7 @@ alpm_time_t _alpm_parsedate(const char *line); int _alpm_raw_cmp(const char *first, const char *second); int _alpm_raw_ncmp(const char *first, const char *second, size_t max); int _alpm_access(alpm_handle_t *handle, const char *dir, const char *file, int amode); +int _alpm_fnmatch_patterns(alpm_list_t *patterns, const char *string); int _alpm_fnmatch(const void *pattern, const void *string); #ifndef HAVE_STRSEP -- 1.8.3.1