2 * Copyright (c) 2003-2007 Tim Kientzle
3 * Copyright (c) 2012 Michihiro NAKAJIMA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD$");
41 #include "archive_private.h"
42 #include "archive_entry.h"
43 #include "archive_getdate.h"
44 #include "archive_pathmatch.h"
45 #include "archive_rb.h"
46 #include "archive_string.h"
51 struct archive_mstring pattern;
59 struct match *unmatched_next;
64 struct archive_rb_node node;
65 struct match_file *next;
66 struct archive_mstring pathname;
75 struct match_file *first;
76 struct match_file **last;
81 size_t size;/* Allocated size */
86 #define PATTERN_IS_SET 1
90 struct archive_match {
91 struct archive archive;
93 /* exclusion/inclusion set flag. */
97 * Matching filename patterns.
99 struct match_list exclusions;
100 struct match_list inclusions;
103 * Matching time stamps.
106 int newer_mtime_filter;
107 time_t newer_mtime_sec;
108 long newer_mtime_nsec;
109 int newer_ctime_filter;
110 time_t newer_ctime_sec;
111 long newer_ctime_nsec;
112 int older_mtime_filter;
113 time_t older_mtime_sec;
114 long older_mtime_nsec;
115 int older_ctime_filter;
116 time_t older_ctime_sec;
117 long older_ctime_nsec;
119 * Matching time stamps with its filename.
121 struct archive_rb_tree exclusion_tree;
122 struct entry_list exclusion_entry_list;
125 * Matching file owners.
127 struct id_array inclusion_uids;
128 struct id_array inclusion_gids;
129 struct match_list inclusion_unames;
130 struct match_list inclusion_gnames;
133 static int add_pattern_from_file(struct archive_match *,
134 struct match_list *, int, const void *, int);
135 static int add_entry(struct archive_match *, int,
136 struct archive_entry *);
137 static int add_owner_id(struct archive_match *, struct id_array *,
139 static int add_owner_name(struct archive_match *, struct match_list *,
141 static int add_pattern_mbs(struct archive_match *, struct match_list *,
143 static int add_pattern_wcs(struct archive_match *, struct match_list *,
145 static int cmp_key_mbs(const struct archive_rb_node *, const void *);
146 static int cmp_key_wcs(const struct archive_rb_node *, const void *);
147 static int cmp_node_mbs(const struct archive_rb_node *,
148 const struct archive_rb_node *);
149 static int cmp_node_wcs(const struct archive_rb_node *,
150 const struct archive_rb_node *);
151 static void entry_list_add(struct entry_list *, struct match_file *);
152 static void entry_list_free(struct entry_list *);
153 static void entry_list_init(struct entry_list *);
154 static int error_nomem(struct archive_match *);
155 static void match_list_add(struct match_list *, struct match *);
156 static void match_list_free(struct match_list *);
157 static void match_list_init(struct match_list *);
158 static int match_list_unmatched_inclusions_next(struct archive_match *,
159 struct match_list *, int, const void **);
160 static int match_owner_id(struct id_array *, int64_t);
161 #if !defined(_WIN32) || defined(__CYGWIN__)
162 static int match_owner_name_mbs(struct archive_match *,
163 struct match_list *, const char *);
165 static int match_owner_name_wcs(struct archive_match *,
166 struct match_list *, const wchar_t *);
168 static int match_path_exclusion(struct archive_match *,
169 struct match *, int, const void *);
170 static int match_path_inclusion(struct archive_match *,
171 struct match *, int, const void *);
172 static int owner_excluded(struct archive_match *,
173 struct archive_entry *);
174 static int path_excluded(struct archive_match *, int, const void *);
175 static int set_timefilter(struct archive_match *, int, time_t, long,
177 static int set_timefilter_pathname_mbs(struct archive_match *,
179 static int set_timefilter_pathname_wcs(struct archive_match *,
180 int, const wchar_t *);
181 static int set_timefilter_date(struct archive_match *, int, const char *);
182 static int set_timefilter_date_w(struct archive_match *, int,
184 static int time_excluded(struct archive_match *,
185 struct archive_entry *);
186 static int validate_time_flag(struct archive *, int, const char *);
188 #define get_date __archive_get_date
190 static const struct archive_rb_tree_ops rb_ops_mbs = {
191 cmp_node_mbs, cmp_key_mbs
194 static const struct archive_rb_tree_ops rb_ops_wcs = {
195 cmp_node_wcs, cmp_key_wcs
199 * The matching logic here needs to be re-thought. I started out to
200 * try to mimic gtar's matching logic, but it's not entirely
201 * consistent. In particular 'tar -t' and 'tar -x' interpret patterns
202 * on the command line as anchored, but --exclude doesn't.
206 error_nomem(struct archive_match *a)
208 archive_set_error(&(a->archive), ENOMEM, "No memory");
209 a->archive.state = ARCHIVE_STATE_FATAL;
210 return (ARCHIVE_FATAL);
214 * Create an ARCHIVE_MATCH object.
217 archive_match_new(void)
219 struct archive_match *a;
221 a = (struct archive_match *)calloc(1, sizeof(*a));
224 a->archive.magic = ARCHIVE_MATCH_MAGIC;
225 a->archive.state = ARCHIVE_STATE_NEW;
226 match_list_init(&(a->inclusions));
227 match_list_init(&(a->exclusions));
228 __archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
229 entry_list_init(&(a->exclusion_entry_list));
230 match_list_init(&(a->inclusion_unames));
231 match_list_init(&(a->inclusion_gnames));
233 return (&(a->archive));
237 * Free an ARCHIVE_MATCH object.
240 archive_match_free(struct archive *_a)
242 struct archive_match *a;
246 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
247 ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free");
248 a = (struct archive_match *)_a;
249 match_list_free(&(a->inclusions));
250 match_list_free(&(a->exclusions));
251 entry_list_free(&(a->exclusion_entry_list));
252 free(a->inclusion_uids.ids);
253 free(a->inclusion_gids.ids);
254 match_list_free(&(a->inclusion_unames));
255 match_list_free(&(a->inclusion_gnames));
261 * Convenience function to perform all exclusion tests.
263 * Returns 1 if archive entry is excluded.
264 * Returns 0 if archive entry is not excluded.
265 * Returns <0 if something error happened.
268 archive_match_excluded(struct archive *_a, struct archive_entry *entry)
270 struct archive_match *a;
273 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
274 ARCHIVE_STATE_NEW, "archive_match_excluded_ae");
276 a = (struct archive_match *)_a;
278 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
279 return (ARCHIVE_FAILED);
283 if (a->setflag & PATTERN_IS_SET) {
284 #if defined(_WIN32) && !defined(__CYGWIN__)
285 r = path_excluded(a, 0, archive_entry_pathname_w(entry));
287 r = path_excluded(a, 1, archive_entry_pathname(entry));
293 if (a->setflag & TIME_IS_SET) {
294 r = time_excluded(a, entry);
299 if (a->setflag & ID_IS_SET)
300 r = owner_excluded(a, entry);
305 * Utility functions to manage exclusion/inclusion patterns
309 archive_match_exclude_pattern(struct archive *_a, const char *pattern)
311 struct archive_match *a;
314 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
315 ARCHIVE_STATE_NEW, "archive_match_exclude_pattern");
316 a = (struct archive_match *)_a;
318 if (pattern == NULL || *pattern == '\0') {
319 archive_set_error(&(a->archive), EINVAL, "pattern is empty");
320 return (ARCHIVE_FAILED);
322 if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
328 archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern)
330 struct archive_match *a;
333 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
334 ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w");
335 a = (struct archive_match *)_a;
337 if (pattern == NULL || *pattern == L'\0') {
338 archive_set_error(&(a->archive), EINVAL, "pattern is empty");
339 return (ARCHIVE_FAILED);
341 if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
347 archive_match_exclude_pattern_from_file(struct archive *_a,
348 const char *pathname, int nullSeparator)
350 struct archive_match *a;
352 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
353 ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file");
354 a = (struct archive_match *)_a;
356 return add_pattern_from_file(a, &(a->exclusions), 1, pathname,
361 archive_match_exclude_pattern_from_file_w(struct archive *_a,
362 const wchar_t *pathname, int nullSeparator)
364 struct archive_match *a;
366 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
367 ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w");
368 a = (struct archive_match *)_a;
370 return add_pattern_from_file(a, &(a->exclusions), 0, pathname,
375 archive_match_include_pattern(struct archive *_a, const char *pattern)
377 struct archive_match *a;
380 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
381 ARCHIVE_STATE_NEW, "archive_match_include_pattern");
382 a = (struct archive_match *)_a;
384 if (pattern == NULL || *pattern == '\0') {
385 archive_set_error(&(a->archive), EINVAL, "pattern is empty");
386 return (ARCHIVE_FAILED);
388 if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
394 archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern)
396 struct archive_match *a;
399 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
400 ARCHIVE_STATE_NEW, "archive_match_include_pattern_w");
401 a = (struct archive_match *)_a;
403 if (pattern == NULL || *pattern == L'\0') {
404 archive_set_error(&(a->archive), EINVAL, "pattern is empty");
405 return (ARCHIVE_FAILED);
407 if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
413 archive_match_include_pattern_from_file(struct archive *_a,
414 const char *pathname, int nullSeparator)
416 struct archive_match *a;
418 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
419 ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file");
420 a = (struct archive_match *)_a;
422 return add_pattern_from_file(a, &(a->inclusions), 1, pathname,
427 archive_match_include_pattern_from_file_w(struct archive *_a,
428 const wchar_t *pathname, int nullSeparator)
430 struct archive_match *a;
432 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
433 ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w");
434 a = (struct archive_match *)_a;
436 return add_pattern_from_file(a, &(a->inclusions), 0, pathname,
441 * Test functions for pathname patterns.
443 * Returns 1 if archive entry is excluded.
444 * Returns 0 if archive entry is not excluded.
445 * Returns <0 if something error happened.
448 archive_match_path_excluded(struct archive *_a,
449 struct archive_entry *entry)
451 struct archive_match *a;
453 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
454 ARCHIVE_STATE_NEW, "archive_match_path_excluded");
456 a = (struct archive_match *)_a;
458 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
459 return (ARCHIVE_FAILED);
462 /* If we don't have exclusion/inclusion pattern set at all,
463 * the entry is always not excluded. */
464 if ((a->setflag & PATTERN_IS_SET) == 0)
466 #if defined(_WIN32) && !defined(__CYGWIN__)
467 return (path_excluded(a, 0, archive_entry_pathname_w(entry)));
469 return (path_excluded(a, 1, archive_entry_pathname(entry)));
474 * Utility functions to get statistic information for inclusion patterns.
477 archive_match_path_unmatched_inclusions(struct archive *_a)
479 struct archive_match *a;
481 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
482 ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
483 a = (struct archive_match *)_a;
485 return (a->inclusions.unmatched_count);
489 archive_match_path_unmatched_inclusions_next(struct archive *_a,
492 struct archive_match *a;
496 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
497 ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next");
498 a = (struct archive_match *)_a;
500 r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v);
501 *_p = (const char *)v;
506 archive_match_path_unmatched_inclusions_next_w(struct archive *_a,
509 struct archive_match *a;
513 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
514 ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w");
515 a = (struct archive_match *)_a;
517 r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v);
518 *_p = (const wchar_t *)v;
523 * Add inclusion/exclusion patterns.
526 add_pattern_mbs(struct archive_match *a, struct match_list *list,
532 match = calloc(1, sizeof(*match));
534 return (error_nomem(a));
535 /* Both "foo/" and "foo" should match "foo/bar". */
536 len = strlen(pattern);
537 if (len && pattern[len - 1] == '/')
539 archive_mstring_copy_mbs_len(&(match->pattern), pattern, len);
540 match_list_add(list, match);
541 a->setflag |= PATTERN_IS_SET;
546 add_pattern_wcs(struct archive_match *a, struct match_list *list,
547 const wchar_t *pattern)
552 match = calloc(1, sizeof(*match));
554 return (error_nomem(a));
555 /* Both "foo/" and "foo" should match "foo/bar". */
556 len = wcslen(pattern);
557 if (len && pattern[len - 1] == L'/')
559 archive_mstring_copy_wcs_len(&(match->pattern), pattern, len);
560 match_list_add(list, match);
561 a->setflag |= PATTERN_IS_SET;
566 add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
567 int mbs, const void *pathname, int nullSeparator)
570 struct archive_entry *ae;
571 struct archive_string as;
577 ar = archive_read_new();
579 archive_set_error(&(a->archive), ENOMEM, "No memory");
580 return (ARCHIVE_FATAL);
582 r = archive_read_support_format_raw(ar);
583 r = archive_read_support_format_empty(ar);
584 if (r != ARCHIVE_OK) {
585 archive_copy_error(&(a->archive), ar);
586 archive_read_free(ar);
590 r = archive_read_open_filename(ar, pathname, 512*20);
592 r = archive_read_open_filename_w(ar, pathname, 512*20);
593 if (r != ARCHIVE_OK) {
594 archive_copy_error(&(a->archive), ar);
595 archive_read_free(ar);
598 r = archive_read_next_header(ar, &ae);
599 if (r != ARCHIVE_OK) {
600 archive_read_free(ar);
601 if (r == ARCHIVE_EOF) {
604 archive_copy_error(&(a->archive), ar);
609 archive_string_init(&as);
611 while ((r = archive_read_data_block(ar, &buff, &size, &offset))
613 const char *b = (const char *)buff;
616 const char *s = (const char *)b;
618 int found_separator = 0;
620 while (length < size) {
627 if (*b == 0x0d || *b == 0x0a) {
635 if (!found_separator) {
636 archive_strncat(&as, s, length);
637 /* Read next data block. */
642 archive_strncat(&as, s, length);
644 /* If the line is not empty, add the pattern. */
645 if (archive_strlen(&as) > 0) {
647 r = add_pattern_mbs(a, mlist, as.s);
648 if (r != ARCHIVE_OK) {
649 archive_read_free(ar);
650 archive_string_free(&as);
653 archive_string_empty(&as);
658 /* If an error occurred, report it immediately. */
659 if (r < ARCHIVE_OK) {
660 archive_copy_error(&(a->archive), ar);
661 archive_read_free(ar);
662 archive_string_free(&as);
666 /* If the line is not empty, add the pattern. */
667 if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
669 r = add_pattern_mbs(a, mlist, as.s);
670 if (r != ARCHIVE_OK) {
671 archive_read_free(ar);
672 archive_string_free(&as);
676 archive_read_free(ar);
677 archive_string_free(&as);
682 * Test if pathname is excluded by inclusion/exclusion patterns.
685 path_excluded(struct archive_match *a, int mbs, const void *pathname)
688 struct match *matched;
694 /* Mark off any unmatched inclusions. */
695 /* In particular, if a filename does appear in the archive and
696 * is explicitly included and excluded, then we don't report
697 * it as missing even though we don't extract it.
700 for (match = a->inclusions.first; match != NULL;
701 match = match->next){
702 if (match->matches == 0 &&
703 (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
706 a->inclusions.unmatched_count--;
712 /* Exclusions take priority */
713 for (match = a->exclusions.first; match != NULL;
714 match = match->next){
715 r = match_path_exclusion(a, match, mbs, pathname);
720 /* It's not excluded and we found an inclusion above, so it's
726 /* We didn't find an unmatched inclusion, check the remaining ones. */
727 for (match = a->inclusions.first; match != NULL;
728 match = match->next){
729 /* We looked at previously-unmatched inclusions already. */
730 if (match->matches > 0 &&
731 (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
739 /* If there were inclusions, default is to exclude. */
740 if (a->inclusions.first != NULL)
743 /* No explicit inclusions, default is to match. */
748 * This is a little odd, but it matches the default behavior of
749 * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
753 match_path_exclusion(struct archive_match *a, struct match *m,
754 int mbs, const void *pn)
756 int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
761 r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
763 return (archive_pathmatch(p, (const char *)pn, flag));
766 r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
768 return (archive_pathmatch_w(p, (const wchar_t *)pn,
772 return (error_nomem(a));
777 * Again, mimic gtar: inclusions are always anchored (have to match
778 * the beginning of the path) even though exclusions are not anchored.
781 match_path_inclusion(struct archive_match *a, struct match *m,
782 int mbs, const void *pn)
784 int flag = PATHMATCH_NO_ANCHOR_END;
789 r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
791 return (archive_pathmatch(p, (const char *)pn, flag));
794 r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
796 return (archive_pathmatch_w(p, (const wchar_t *)pn,
800 return (error_nomem(a));
805 match_list_init(struct match_list *list)
808 list->last = &(list->first);
813 match_list_free(struct match_list *list)
817 for (p = list->first; p != NULL; ) {
820 archive_mstring_clean(&(q->pattern));
826 match_list_add(struct match_list *list, struct match *m)
829 list->last = &(m->next);
831 list->unmatched_count++;
835 match_list_unmatched_inclusions_next(struct archive_match *a,
836 struct match_list *list, int mbs, const void **vp)
841 if (list->unmatched_eof) {
842 list->unmatched_eof = 0;
843 return (ARCHIVE_EOF);
845 if (list->unmatched_next == NULL) {
846 if (list->unmatched_count == 0)
847 return (ARCHIVE_EOF);
848 list->unmatched_next = list->first;
851 for (m = list->unmatched_next; m != NULL; m = m->next) {
858 r = archive_mstring_get_mbs(&(a->archive),
860 if (r < 0 && errno == ENOMEM)
861 return (error_nomem(a));
867 r = archive_mstring_get_wcs(&(a->archive),
869 if (r < 0 && errno == ENOMEM)
870 return (error_nomem(a));
875 list->unmatched_next = m->next;
876 if (list->unmatched_next == NULL)
877 /* To return EOF next time. */
878 list->unmatched_eof = 1;
881 list->unmatched_next = NULL;
882 return (ARCHIVE_EOF);
886 * Utility functions to manage inclusion timestamps.
889 archive_match_include_time(struct archive *_a, int flag, time_t sec,
894 r = validate_time_flag(_a, flag, "archive_match_include_time");
897 return set_timefilter((struct archive_match *)_a, flag,
898 sec, nsec, sec, nsec);
902 archive_match_include_date(struct archive *_a, int flag,
907 r = validate_time_flag(_a, flag, "archive_match_include_date");
910 return set_timefilter_date((struct archive_match *)_a, flag, datestr);
914 archive_match_include_date_w(struct archive *_a, int flag,
915 const wchar_t *datestr)
919 r = validate_time_flag(_a, flag, "archive_match_include_date_w");
923 return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
927 archive_match_include_file_time(struct archive *_a, int flag,
928 const char *pathname)
932 r = validate_time_flag(_a, flag, "archive_match_include_file_time");
935 return set_timefilter_pathname_mbs((struct archive_match *)_a,
940 archive_match_include_file_time_w(struct archive *_a, int flag,
941 const wchar_t *pathname)
945 r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
948 return set_timefilter_pathname_wcs((struct archive_match *)_a,
953 archive_match_exclude_entry(struct archive *_a, int flag,
954 struct archive_entry *entry)
956 struct archive_match *a;
959 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
960 ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
961 a = (struct archive_match *)_a;
964 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
965 return (ARCHIVE_FAILED);
967 r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
970 return (add_entry(a, flag, entry));
974 * Test function for time stamps.
976 * Returns 1 if archive entry is excluded.
977 * Returns 0 if archive entry is not excluded.
978 * Returns <0 if something error happened.
981 archive_match_time_excluded(struct archive *_a,
982 struct archive_entry *entry)
984 struct archive_match *a;
986 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
987 ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
989 a = (struct archive_match *)_a;
991 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
992 return (ARCHIVE_FAILED);
995 /* If we don't have inclusion time set at all, the entry is always
997 if ((a->setflag & TIME_IS_SET) == 0)
999 return (time_excluded(a, entry));
1003 validate_time_flag(struct archive *_a, int flag, const char *_fn)
1005 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1006 ARCHIVE_STATE_NEW, _fn);
1008 /* Check a type of time. */
1010 ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
1011 archive_set_error(_a, EINVAL, "Invalid time flag");
1012 return (ARCHIVE_FAILED);
1014 if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
1015 archive_set_error(_a, EINVAL, "No time flag");
1016 return (ARCHIVE_FAILED);
1019 /* Check a type of comparison. */
1021 ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1022 | ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
1023 archive_set_error(_a, EINVAL, "Invalid comparison flag");
1024 return (ARCHIVE_FAILED);
1026 if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1027 | ARCHIVE_MATCH_EQUAL)) == 0) {
1028 archive_set_error(_a, EINVAL, "No comparison flag");
1029 return (ARCHIVE_FAILED);
1032 return (ARCHIVE_OK);
1035 #define JUST_EQUAL(t) (((t) & (ARCHIVE_MATCH_EQUAL |\
1036 ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
1038 set_timefilter(struct archive_match *a, int timetype,
1039 time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
1041 if (timetype & ARCHIVE_MATCH_MTIME) {
1042 if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1043 a->newer_mtime_filter = timetype;
1044 a->newer_mtime_sec = mtime_sec;
1045 a->newer_mtime_nsec = mtime_nsec;
1046 a->setflag |= TIME_IS_SET;
1048 if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1049 a->older_mtime_filter = timetype;
1050 a->older_mtime_sec = mtime_sec;
1051 a->older_mtime_nsec = mtime_nsec;
1052 a->setflag |= TIME_IS_SET;
1055 if (timetype & ARCHIVE_MATCH_CTIME) {
1056 if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1057 a->newer_ctime_filter = timetype;
1058 a->newer_ctime_sec = ctime_sec;
1059 a->newer_ctime_nsec = ctime_nsec;
1060 a->setflag |= TIME_IS_SET;
1062 if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1063 a->older_ctime_filter = timetype;
1064 a->older_ctime_sec = ctime_sec;
1065 a->older_ctime_nsec = ctime_nsec;
1066 a->setflag |= TIME_IS_SET;
1069 return (ARCHIVE_OK);
1073 set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
1077 if (datestr == NULL || *datestr == '\0') {
1078 archive_set_error(&(a->archive), EINVAL, "date is empty");
1079 return (ARCHIVE_FAILED);
1081 t = get_date(a->now, datestr);
1082 if (t == (time_t)-1) {
1083 archive_set_error(&(a->archive), EINVAL, "invalid date string");
1084 return (ARCHIVE_FAILED);
1086 return set_timefilter(a, timetype, t, 0, t, 0);
1090 set_timefilter_date_w(struct archive_match *a, int timetype,
1091 const wchar_t *datestr)
1093 struct archive_string as;
1096 if (datestr == NULL || *datestr == L'\0') {
1097 archive_set_error(&(a->archive), EINVAL, "date is empty");
1098 return (ARCHIVE_FAILED);
1101 archive_string_init(&as);
1102 if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
1103 archive_string_free(&as);
1104 if (errno == ENOMEM)
1105 return (error_nomem(a));
1106 archive_set_error(&(a->archive), -1,
1107 "Failed to convert WCS to MBS");
1108 return (ARCHIVE_FAILED);
1110 t = get_date(a->now, as.s);
1111 archive_string_free(&as);
1112 if (t == (time_t)-1) {
1113 archive_set_error(&(a->archive), EINVAL, "invalid date string");
1114 return (ARCHIVE_FAILED);
1116 return set_timefilter(a, timetype, t, 0, t, 0);
1119 #if defined(_WIN32) && !defined(__CYGWIN__)
1120 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1122 set_timefilter_find_data(struct archive_match *a, int timetype,
1123 DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
1124 DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
1127 time_t ctime_sec, mtime_sec;
1128 long ctime_ns, mtime_ns;
1130 utc.HighPart = ftCreationTime_dwHighDateTime;
1131 utc.LowPart = ftCreationTime_dwLowDateTime;
1132 if (utc.QuadPart >= EPOC_TIME) {
1133 utc.QuadPart -= EPOC_TIME;
1134 ctime_sec = (time_t)(utc.QuadPart / 10000000);
1135 ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
1140 utc.HighPart = ftLastWriteTime_dwHighDateTime;
1141 utc.LowPart = ftLastWriteTime_dwLowDateTime;
1142 if (utc.QuadPart >= EPOC_TIME) {
1143 utc.QuadPart -= EPOC_TIME;
1144 mtime_sec = (time_t)(utc.QuadPart / 10000000);
1145 mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
1150 return set_timefilter(a, timetype,
1151 mtime_sec, mtime_ns, ctime_sec, ctime_ns);
1155 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1158 /* NOTE: stat() on Windows cannot handle nano seconds. */
1162 if (path == NULL || *path == '\0') {
1163 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1164 return (ARCHIVE_FAILED);
1166 h = FindFirstFileA(path, &d);
1167 if (h == INVALID_HANDLE_VALUE) {
1168 la_dosmaperr(GetLastError());
1169 archive_set_error(&(a->archive), errno,
1170 "Failed to FindFirstFileA");
1171 return (ARCHIVE_FAILED);
1174 return set_timefilter_find_data(a, timetype,
1175 d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1176 d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1180 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1181 const wchar_t *path)
1186 if (path == NULL || *path == L'\0') {
1187 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1188 return (ARCHIVE_FAILED);
1190 h = FindFirstFileW(path, &d);
1191 if (h == INVALID_HANDLE_VALUE) {
1192 la_dosmaperr(GetLastError());
1193 archive_set_error(&(a->archive), errno,
1194 "Failed to FindFirstFile");
1195 return (ARCHIVE_FAILED);
1198 return set_timefilter_find_data(a, timetype,
1199 d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1200 d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1203 #else /* _WIN32 && !__CYGWIN__ */
1206 set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
1208 struct archive_entry *ae;
1209 time_t ctime_sec, mtime_sec;
1210 long ctime_ns, mtime_ns;
1212 ae = archive_entry_new();
1214 return (error_nomem(a));
1215 archive_entry_copy_stat(ae, st);
1216 ctime_sec = archive_entry_ctime(ae);
1217 ctime_ns = archive_entry_ctime_nsec(ae);
1218 mtime_sec = archive_entry_mtime(ae);
1219 mtime_ns = archive_entry_mtime_nsec(ae);
1220 archive_entry_free(ae);
1221 return set_timefilter(a, timetype, mtime_sec, mtime_ns,
1222 ctime_sec, ctime_ns);
1226 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1231 if (path == NULL || *path == '\0') {
1232 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1233 return (ARCHIVE_FAILED);
1235 if (stat(path, &st) != 0) {
1236 archive_set_error(&(a->archive), errno, "Failed to stat()");
1237 return (ARCHIVE_FAILED);
1239 return (set_timefilter_stat(a, timetype, &st));
1243 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1244 const wchar_t *path)
1246 struct archive_string as;
1249 if (path == NULL || *path == L'\0') {
1250 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1251 return (ARCHIVE_FAILED);
1254 /* Convert WCS filename to MBS filename. */
1255 archive_string_init(&as);
1256 if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
1257 archive_string_free(&as);
1258 if (errno == ENOMEM)
1259 return (error_nomem(a));
1260 archive_set_error(&(a->archive), -1,
1261 "Failed to convert WCS to MBS");
1262 return (ARCHIVE_FAILED);
1265 r = set_timefilter_pathname_mbs(a, timetype, as.s);
1266 archive_string_free(&as);
1270 #endif /* _WIN32 && !__CYGWIN__ */
1273 * Call back functions for archive_rb.
1276 cmp_node_mbs(const struct archive_rb_node *n1,
1277 const struct archive_rb_node *n2)
1279 struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1280 struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1281 const char *p1, *p2;
1283 archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
1284 archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
1289 return (strcmp(p1, p2));
1293 cmp_key_mbs(const struct archive_rb_node *n, const void *key)
1295 struct match_file *f = (struct match_file *)(uintptr_t)n;
1298 archive_mstring_get_mbs(NULL, &(f->pathname), &p);
1301 return (strcmp(p, (const char *)key));
1305 cmp_node_wcs(const struct archive_rb_node *n1,
1306 const struct archive_rb_node *n2)
1308 struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1309 struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1310 const wchar_t *p1, *p2;
1312 archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
1313 archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
1318 return (wcscmp(p1, p2));
1322 cmp_key_wcs(const struct archive_rb_node *n, const void *key)
1324 struct match_file *f = (struct match_file *)(uintptr_t)n;
1327 archive_mstring_get_wcs(NULL, &(f->pathname), &p);
1330 return (wcscmp(p, (const wchar_t *)key));
1334 entry_list_init(struct entry_list *list)
1337 list->last = &(list->first);
1342 entry_list_free(struct entry_list *list)
1344 struct match_file *p, *q;
1346 for (p = list->first; p != NULL; ) {
1349 archive_mstring_clean(&(q->pathname));
1355 entry_list_add(struct entry_list *list, struct match_file *file)
1358 list->last = &(file->next);
1363 add_entry(struct archive_match *a, int flag,
1364 struct archive_entry *entry)
1366 struct match_file *f;
1367 const void *pathname;
1370 f = calloc(1, sizeof(*f));
1372 return (error_nomem(a));
1374 #if defined(_WIN32) && !defined(__CYGWIN__)
1375 pathname = archive_entry_pathname_w(entry);
1376 if (pathname == NULL) {
1378 archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1379 return (ARCHIVE_FAILED);
1381 archive_mstring_copy_wcs(&(f->pathname), pathname);
1382 a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1385 pathname = archive_entry_pathname(entry);
1386 if (pathname == NULL) {
1388 archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1389 return (ARCHIVE_FAILED);
1391 archive_mstring_copy_mbs(&(f->pathname), pathname);
1392 a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1395 f->mtime_sec = archive_entry_mtime(entry);
1396 f->mtime_nsec = archive_entry_mtime_nsec(entry);
1397 f->ctime_sec = archive_entry_ctime(entry);
1398 f->ctime_nsec = archive_entry_ctime_nsec(entry);
1399 r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
1401 struct match_file *f2;
1403 /* Get the duplicated file. */
1404 f2 = (struct match_file *)__archive_rb_tree_find_node(
1405 &(a->exclusion_tree), pathname);
1408 * We always overwrite comparison condition.
1409 * If you do not want to overwrite it, you should not
1410 * call archive_match_exclude_entry(). We cannot know
1411 * what behavior you really expect since overwriting
1412 * condition might be different with the flag.
1416 f2->mtime_sec = f->mtime_sec;
1417 f2->mtime_nsec = f->mtime_nsec;
1418 f2->ctime_sec = f->ctime_sec;
1419 f2->ctime_nsec = f->ctime_nsec;
1421 /* Release the duplicated file. */
1422 archive_mstring_clean(&(f->pathname));
1424 return (ARCHIVE_OK);
1426 entry_list_add(&(a->exclusion_entry_list), f);
1427 a->setflag |= TIME_IS_SET;
1428 return (ARCHIVE_OK);
1432 * Test if entry is excluded by its timestamp.
1435 time_excluded(struct archive_match *a, struct archive_entry *entry)
1437 struct match_file *f;
1438 const void *pathname;
1443 * If this file/dir is excluded by a time comparison, skip it.
1445 if (a->newer_ctime_filter) {
1446 /* If ctime is not set, use mtime instead. */
1447 if (archive_entry_ctime_is_set(entry))
1448 sec = archive_entry_ctime(entry);
1450 sec = archive_entry_mtime(entry);
1451 if (sec < a->newer_ctime_sec)
1452 return (1); /* Too old, skip it. */
1453 if (sec == a->newer_ctime_sec) {
1454 if (archive_entry_ctime_is_set(entry))
1455 nsec = archive_entry_ctime_nsec(entry);
1457 nsec = archive_entry_mtime_nsec(entry);
1458 if (nsec < a->newer_ctime_nsec)
1459 return (1); /* Too old, skip it. */
1460 if (nsec == a->newer_ctime_nsec &&
1461 (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
1463 return (1); /* Equal, skip it. */
1466 if (a->older_ctime_filter) {
1467 /* If ctime is not set, use mtime instead. */
1468 if (archive_entry_ctime_is_set(entry))
1469 sec = archive_entry_ctime(entry);
1471 sec = archive_entry_mtime(entry);
1472 if (sec > a->older_ctime_sec)
1473 return (1); /* Too new, skip it. */
1474 if (sec == a->older_ctime_sec) {
1475 if (archive_entry_ctime_is_set(entry))
1476 nsec = archive_entry_ctime_nsec(entry);
1478 nsec = archive_entry_mtime_nsec(entry);
1479 if (nsec > a->older_ctime_nsec)
1480 return (1); /* Too new, skip it. */
1481 if (nsec == a->older_ctime_nsec &&
1482 (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
1484 return (1); /* Equal, skip it. */
1487 if (a->newer_mtime_filter) {
1488 sec = archive_entry_mtime(entry);
1489 if (sec < a->newer_mtime_sec)
1490 return (1); /* Too old, skip it. */
1491 if (sec == a->newer_mtime_sec) {
1492 nsec = archive_entry_mtime_nsec(entry);
1493 if (nsec < a->newer_mtime_nsec)
1494 return (1); /* Too old, skip it. */
1495 if (nsec == a->newer_mtime_nsec &&
1496 (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
1498 return (1); /* Equal, skip it. */
1501 if (a->older_mtime_filter) {
1502 sec = archive_entry_mtime(entry);
1503 if (sec > a->older_mtime_sec)
1504 return (1); /* Too new, skip it. */
1505 nsec = archive_entry_mtime_nsec(entry);
1506 if (sec == a->older_mtime_sec) {
1507 if (nsec > a->older_mtime_nsec)
1508 return (1); /* Too new, skip it. */
1509 if (nsec == a->older_mtime_nsec &&
1510 (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
1512 return (1); /* Equal, skip it. */
1516 /* If there is no exclusion list, include the file. */
1517 if (a->exclusion_entry_list.count == 0)
1520 #if defined(_WIN32) && !defined(__CYGWIN__)
1521 pathname = archive_entry_pathname_w(entry);
1522 a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1525 pathname = archive_entry_pathname(entry);
1526 a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1528 if (pathname == NULL)
1531 f = (struct match_file *)__archive_rb_tree_find_node(
1532 &(a->exclusion_tree), pathname);
1533 /* If the file wasn't rejected, include it. */
1537 if (f->flag & ARCHIVE_MATCH_CTIME) {
1538 sec = archive_entry_ctime(entry);
1539 if (f->ctime_sec > sec) {
1540 if (f->flag & ARCHIVE_MATCH_OLDER)
1542 } else if (f->ctime_sec < sec) {
1543 if (f->flag & ARCHIVE_MATCH_NEWER)
1546 nsec = archive_entry_ctime_nsec(entry);
1547 if (f->ctime_nsec > nsec) {
1548 if (f->flag & ARCHIVE_MATCH_OLDER)
1550 } else if (f->ctime_nsec < nsec) {
1551 if (f->flag & ARCHIVE_MATCH_NEWER)
1553 } else if (f->flag & ARCHIVE_MATCH_EQUAL)
1557 if (f->flag & ARCHIVE_MATCH_MTIME) {
1558 sec = archive_entry_mtime(entry);
1559 if (f->mtime_sec > sec) {
1560 if (f->flag & ARCHIVE_MATCH_OLDER)
1562 } else if (f->mtime_sec < sec) {
1563 if (f->flag & ARCHIVE_MATCH_NEWER)
1566 nsec = archive_entry_mtime_nsec(entry);
1567 if (f->mtime_nsec > nsec) {
1568 if (f->flag & ARCHIVE_MATCH_OLDER)
1570 } else if (f->mtime_nsec < nsec) {
1571 if (f->flag & ARCHIVE_MATCH_NEWER)
1573 } else if (f->flag & ARCHIVE_MATCH_EQUAL)
1581 * Utility functions to manage inclusion owners
1585 archive_match_include_uid(struct archive *_a, la_int64_t uid)
1587 struct archive_match *a;
1589 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1590 ARCHIVE_STATE_NEW, "archive_match_include_uid");
1591 a = (struct archive_match *)_a;
1592 return (add_owner_id(a, &(a->inclusion_uids), uid));
1596 archive_match_include_gid(struct archive *_a, la_int64_t gid)
1598 struct archive_match *a;
1600 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1601 ARCHIVE_STATE_NEW, "archive_match_include_gid");
1602 a = (struct archive_match *)_a;
1603 return (add_owner_id(a, &(a->inclusion_gids), gid));
1607 archive_match_include_uname(struct archive *_a, const char *uname)
1609 struct archive_match *a;
1611 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1612 ARCHIVE_STATE_NEW, "archive_match_include_uname");
1613 a = (struct archive_match *)_a;
1614 return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
1618 archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
1620 struct archive_match *a;
1622 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1623 ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
1624 a = (struct archive_match *)_a;
1625 return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
1629 archive_match_include_gname(struct archive *_a, const char *gname)
1631 struct archive_match *a;
1633 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1634 ARCHIVE_STATE_NEW, "archive_match_include_gname");
1635 a = (struct archive_match *)_a;
1636 return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
1640 archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
1642 struct archive_match *a;
1644 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1645 ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
1646 a = (struct archive_match *)_a;
1647 return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
1651 * Test function for owner(uid, gid, uname, gname).
1653 * Returns 1 if archive entry is excluded.
1654 * Returns 0 if archive entry is not excluded.
1655 * Returns <0 if something error happened.
1658 archive_match_owner_excluded(struct archive *_a,
1659 struct archive_entry *entry)
1661 struct archive_match *a;
1663 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1664 ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
1666 a = (struct archive_match *)_a;
1667 if (entry == NULL) {
1668 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1669 return (ARCHIVE_FAILED);
1672 /* If we don't have inclusion id set at all, the entry is always
1674 if ((a->setflag & ID_IS_SET) == 0)
1676 return (owner_excluded(a, entry));
1680 add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
1684 if (ids->count + 1 >= ids->size) {
1691 p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
1693 return (error_nomem(a));
1694 ids->ids = (int64_t *)p;
1697 /* Find an insert point. */
1698 for (i = 0; i < ids->count; i++) {
1699 if (ids->ids[i] >= id)
1704 if (i == ids->count)
1705 ids->ids[ids->count++] = id;
1706 else if (ids->ids[i] != id) {
1707 memmove(&(ids->ids[i+1]), &(ids->ids[i]),
1708 (ids->count - i) * sizeof(ids->ids[0]));
1712 a->setflag |= ID_IS_SET;
1713 return (ARCHIVE_OK);
1717 match_owner_id(struct id_array *ids, int64_t id)
1722 b = (unsigned)ids->count;
1725 if (ids->ids[m] == id)
1727 if (ids->ids[m] < id)
1736 add_owner_name(struct archive_match *a, struct match_list *list,
1737 int mbs, const void *name)
1739 struct match *match;
1741 match = calloc(1, sizeof(*match));
1743 return (error_nomem(a));
1745 archive_mstring_copy_mbs(&(match->pattern), name);
1747 archive_mstring_copy_wcs(&(match->pattern), name);
1748 match_list_add(list, match);
1749 a->setflag |= ID_IS_SET;
1750 return (ARCHIVE_OK);
1753 #if !defined(_WIN32) || defined(__CYGWIN__)
1755 match_owner_name_mbs(struct archive_match *a, struct match_list *list,
1761 if (name == NULL || *name == '\0')
1763 for (m = list->first; m; m = m->next) {
1764 if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
1765 < 0 && errno == ENOMEM)
1766 return (error_nomem(a));
1767 if (p != NULL && strcmp(p, name) == 0) {
1776 match_owner_name_wcs(struct archive_match *a, struct match_list *list,
1777 const wchar_t *name)
1782 if (name == NULL || *name == L'\0')
1784 for (m = list->first; m; m = m->next) {
1785 if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
1786 < 0 && errno == ENOMEM)
1787 return (error_nomem(a));
1788 if (p != NULL && wcscmp(p, name) == 0) {
1798 * Test if entry is excluded by uid, gid, uname or gname.
1801 owner_excluded(struct archive_match *a, struct archive_entry *entry)
1805 if (a->inclusion_uids.count) {
1806 if (!match_owner_id(&(a->inclusion_uids),
1807 archive_entry_uid(entry)))
1811 if (a->inclusion_gids.count) {
1812 if (!match_owner_id(&(a->inclusion_gids),
1813 archive_entry_gid(entry)))
1817 if (a->inclusion_unames.count) {
1818 #if defined(_WIN32) && !defined(__CYGWIN__)
1819 r = match_owner_name_wcs(a, &(a->inclusion_unames),
1820 archive_entry_uname_w(entry));
1822 r = match_owner_name_mbs(a, &(a->inclusion_unames),
1823 archive_entry_uname(entry));
1831 if (a->inclusion_gnames.count) {
1832 #if defined(_WIN32) && !defined(__CYGWIN__)
1833 r = match_owner_name_wcs(a, &(a->inclusion_gnames),
1834 archive_entry_gname_w(entry));
1836 r = match_owner_name_mbs(a, &(a->inclusion_gnames),
1837 archive_entry_gname(entry));