[pacman-dev] [PATCH 1/3] Make (_alpm_)fnmatch_patterns available to front-end
This function will be useful in determining if any files are in the NoExtract array when checking for missing files. Signed-off-by: Allan McRae <allan@archlinux.org> --- lib/libalpm/add.c | 4 ++-- lib/libalpm/util.c | 31 ------------------------------- lib/libalpm/util.h | 1 - src/common/util-common.c | 32 ++++++++++++++++++++++++++++++++ src/common/util-common.h | 4 ++++ 5 files changed, 38 insertions(+), 34 deletions(-) diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index bbf2a51..9f7c9fa 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -190,7 +190,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_fnmatch_patterns(handle->noextract, entryname) == 0) { + if(fnmatch_patterns(handle->noextract, entryname) == 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract," " skipping extraction of %s\n", entryname, filename); @@ -266,7 +266,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_fnmatch_patterns(handle->noupgrade, entryname) == 0) { + if(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 43d0d7b..39ac890 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -1224,37 +1224,6 @@ 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 6f47073..9422646 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -137,7 +137,6 @@ 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); void *_alpm_realloc(void **data, size_t *current, const size_t required); void *_alpm_greedy_grow(void **data, size_t *current, const size_t required); diff --git a/src/common/util-common.c b/src/common/util-common.c index ab74e7c..1930d64 100644 --- a/src/common/util-common.c +++ b/src/common/util-common.c @@ -20,6 +20,7 @@ #include <errno.h> #include <stdlib.h> #include <string.h> +#include <fnmatch.h> #include "util-common.h" @@ -103,6 +104,37 @@ int llstat(char *path, struct stat *buf) 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 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(fnmatch(pattern, string, 0) == 0) { + return inverted; + } + } + + return -1; +} + /** Wrapper around fgets() which properly handles EINTR * @param s string to read into * @param size maximum length to read diff --git a/src/common/util-common.h b/src/common/util-common.h index ca8db5a..17f8d87 100644 --- a/src/common/util-common.h +++ b/src/common/util-common.h @@ -20,6 +20,8 @@ #ifndef _PM_UTIL_COMMON_H #define _PM_UTIL_COMMON_H +#include <alpm_list.h> + #include <stdio.h> #include <sys/stat.h> /* struct stat */ @@ -28,6 +30,8 @@ char *mdirname(const char *path); int llstat(char *path, struct stat *buf); +int fnmatch_patterns(alpm_list_t *patterns, const char *string); + char *safe_fgets(char *s, int size, FILE *stream); #ifndef HAVE_STRNDUP -- 2.1.3
When the system root is passed to fnmatch_patterns, it is stripped from the start of the string before comparisions are made. Signed-off-by: Allan McRae <allan@archlinux.org> --- lib/libalpm/add.c | 4 ++-- src/common/util-common.c | 9 ++++++++- src/common/util-common.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 9f7c9fa..604e0c7 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -190,7 +190,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(fnmatch_patterns(handle->noextract, entryname) == 0) { + if(fnmatch_patterns(handle->noextract, entryname, NULL) == 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract," " skipping extraction of %s\n", entryname, filename); @@ -266,7 +266,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(fnmatch_patterns(handle->noupgrade, entryname) == 0) { + if(fnmatch_patterns(handle->noupgrade, entryname, NULL) == 0) { notouch = 1; } else { alpm_backup_t *backup; diff --git a/src/common/util-common.c b/src/common/util-common.c index 1930d64..63355a4 100644 --- a/src/common/util-common.c +++ b/src/common/util-common.c @@ -110,14 +110,21 @@ int llstat(char *path, struct stat *buf) * escaped. Subsequent matches override previous ones. * @param patterns patterns to match against * @param string string to check against pattern + * @param root prefix to be stripped from string before comparison * @return 0 if string matches pattern, negative if they don't match and * positive if the last match was inverted */ -int fnmatch_patterns(alpm_list_t *patterns, const char *string) +int fnmatch_patterns(alpm_list_t *patterns, const char *string, const char *root) { alpm_list_t *i; char *pattern; short inverted; + size_t len = 0; + + if(root) { + len = strlen(root); + } + string = string + len; for(i = alpm_list_last(patterns); i; i = alpm_list_previous(i)) { pattern = i->data; diff --git a/src/common/util-common.h b/src/common/util-common.h index 17f8d87..e731e52 100644 --- a/src/common/util-common.h +++ b/src/common/util-common.h @@ -30,7 +30,7 @@ char *mdirname(const char *path); int llstat(char *path, struct stat *buf); -int fnmatch_patterns(alpm_list_t *patterns, const char *string); +int fnmatch_patterns(alpm_list_t *patterns, const char *string, const char *root); char *safe_fgets(char *s, int size, FILE *stream); -- 2.1.3
On 11/17/14 at 11:33pm, Allan McRae wrote:
When the system root is passed to fnmatch_patterns, it is stripped from the start of the string before comparisions are made.
Signed-off-by: Allan McRae <allan@archlinux.org> --- lib/libalpm/add.c | 4 ++-- src/common/util-common.c | 9 ++++++++- src/common/util-common.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 9f7c9fa..604e0c7 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -190,7 +190,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(fnmatch_patterns(handle->noextract, entryname) == 0) { + if(fnmatch_patterns(handle->noextract, entryname, NULL) == 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in NoExtract," " skipping extraction of %s\n", entryname, filename); @@ -266,7 +266,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(fnmatch_patterns(handle->noupgrade, entryname) == 0) { + if(fnmatch_patterns(handle->noupgrade, entryname, NULL) == 0) { notouch = 1; } else { alpm_backup_t *backup; diff --git a/src/common/util-common.c b/src/common/util-common.c index 1930d64..63355a4 100644 --- a/src/common/util-common.c +++ b/src/common/util-common.c @@ -110,14 +110,21 @@ int llstat(char *path, struct stat *buf) * escaped. Subsequent matches override previous ones. * @param patterns patterns to match against * @param string string to check against pattern + * @param root prefix to be stripped from string before comparison * @return 0 if string matches pattern, negative if they don't match and * positive if the last match was inverted */ -int fnmatch_patterns(alpm_list_t *patterns, const char *string) +int fnmatch_patterns(alpm_list_t *patterns, const char *string, const char *root) { alpm_list_t *i; char *pattern; short inverted; + size_t len = 0; + + if(root) { + len = strlen(root); + } + string = string + len;
Why do this here? The caller can just as easily achieve this by calling fnmatch_patterns(patterns, string + strlen(root)) and may even be able to avoid duplicate strlen calls by caching the root length.
for(i = alpm_list_last(patterns); i; i = alpm_list_previous(i)) { pattern = i->data; diff --git a/src/common/util-common.h b/src/common/util-common.h index 17f8d87..e731e52 100644 --- a/src/common/util-common.h +++ b/src/common/util-common.h @@ -30,7 +30,7 @@ char *mdirname(const char *path);
int llstat(char *path, struct stat *buf);
-int fnmatch_patterns(alpm_list_t *patterns, const char *string); +int fnmatch_patterns(alpm_list_t *patterns, const char *string, const char *root);
char *safe_fgets(char *s, int size, FILE *stream);
-- 2.1.3
When checking a packages files, ignore any missing files in NoExtract Signed-off-by: Allan McRae <allan@archlinux.org> --- src/pacman/check.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/pacman/check.c b/src/pacman/check.c index 7109c7a..1a49537 100644 --- a/src/pacman/check.c +++ b/src/pacman/check.c @@ -27,17 +27,23 @@ #include "util.h" static int check_file_exists(const char *pkgname, char *filepath, - struct stat *st) + const char *root, struct stat *st) { /* use lstat to prevent errors from symlinks */ if(llstat(filepath, st) != 0) { - if(config->quiet) { - printf("%s %s\n", pkgname, filepath); + if(fnmatch_patterns(alpm_option_get_noextracts(config->handle), + filepath, root) == 0) { + /* NoExtract */ + return -1; } else { - pm_printf(ALPM_LOG_WARNING, "%s: %s (%s)\n", - pkgname, filepath, strerror(errno)); + if(config->quiet) { + printf("%s %s\n", pkgname, filepath); + } else { + pm_printf(ALPM_LOG_WARNING, "%s: %s (%s)\n", + pkgname, filepath, strerror(errno)); + } + return 1; } - return 1; } return 0; @@ -209,6 +215,7 @@ int check_pkg_fast(alpm_pkg_t *pkg) for(i = 0; i < filelist->count; i++) { const alpm_file_t *file = filelist->files + i; struct stat st; + int exists; const char *path = file->name; size_t plen = strlen(path); @@ -218,7 +225,8 @@ int check_pkg_fast(alpm_pkg_t *pkg) } strcpy(filepath + rootlen, path); - if(check_file_exists(pkgname, filepath, &st) == 0) { + exists = check_file_exists(pkgname, filepath, root, &st); + if(exists == 0) { int expect_dir = path[plen - 1] == '/' ? 1 : 0; int is_dir = S_ISDIR(st.st_mode) ? 1 : 0; if(expect_dir != is_dir) { @@ -226,7 +234,7 @@ int check_pkg_fast(alpm_pkg_t *pkg) pkgname, filepath); ++errors; } - } else { + } else if(exists == 1) { ++errors; } } @@ -278,6 +286,7 @@ int check_pkg_full(alpm_pkg_t *pkg) mode_t type; size_t file_errors = 0; int backup = 0; + int exists; /* strip leading "./" from path entries */ if(path[0] == '.' && path[1] == '/') { @@ -310,9 +319,13 @@ int check_pkg_full(alpm_pkg_t *pkg) } strcpy(filepath + rootlen, path); - if(check_file_exists(pkgname, filepath, &st) == 1) { + exists = check_file_exists(pkgname, filepath, root, &st); + if(exists == 1) { errors++; continue; + } else if (exists == -1) { + /* NoExtract */ + continue; } type = archive_entry_filetype(entry); -- 2.1.3
On 11/17/14 at 11:33pm, Allan McRae wrote:
This function will be useful in determining if any files are in the NoExtract array when checking for missing files.
Signed-off-by: Allan McRae <allan@archlinux.org> --- lib/libalpm/add.c | 4 ++-- lib/libalpm/util.c | 31 ------------------------------- lib/libalpm/util.h | 1 - src/common/util-common.c | 32 ++++++++++++++++++++++++++++++++ src/common/util-common.h | 4 ++++ 5 files changed, 38 insertions(+), 34 deletions(-)
Rather than moving this low-level function into util-common, I think we should expose higher level functions through the API, something like alpm_path_match_noextract or alpm_option_match_noextract. apg
On 18/11/14 02:33, Andrew Gregory wrote:
On 11/17/14 at 11:33pm, Allan McRae wrote:
This function will be useful in determining if any files are in the NoExtract array when checking for missing files.
Signed-off-by: Allan McRae <allan@archlinux.org> --- lib/libalpm/add.c | 4 ++-- lib/libalpm/util.c | 31 ------------------------------- lib/libalpm/util.h | 1 - src/common/util-common.c | 32 ++++++++++++++++++++++++++++++++ src/common/util-common.h | 4 ++++ 5 files changed, 38 insertions(+), 34 deletions(-)
Rather than moving this low-level function into util-common, I think we should expose higher level functions through the API, something like alpm_path_match_noextract or alpm_option_match_noextract.
That makes a lot of sense. I'll submit new patches later. Allan
participants (2)
-
Allan McRae
-
Andrew Gregory