summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/pacman.conf.5.txt10
-rw-r--r--lib/libalpm/add.c4
-rw-r--r--lib/libalpm/util.c31
-rw-r--r--lib/libalpm/util.h1
4 files changed, 42 insertions, 4 deletions
diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index 83a399e1..049faee2 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 cab04a8b..3d0cf55a 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 f84fb666..15c1a67c 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 56031f3e..24b7c229 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