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_pathmatch.h"
44 #include "archive_rb.h"
45 #include "archive_string.h"
50 struct archive_mstring pattern;
58 struct match *unmatched_next;
63 struct archive_rb_node node;
64 struct match_file *next;
65 struct archive_mstring pathname;
74 struct match_file *first;
75 struct match_file **last;
80 size_t size;/* Allocated size */
85 #define PATTERN_IS_SET 1
89 struct archive_match {
90 struct archive archive;
92 /* exclusion/inclusion set flag. */
96 * Matching filename patterns.
98 struct match_list exclusions;
99 struct match_list inclusions;
102 * Matching time stamps.
105 int newer_mtime_filter;
106 time_t newer_mtime_sec;
107 long newer_mtime_nsec;
108 int newer_ctime_filter;
109 time_t newer_ctime_sec;
110 long newer_ctime_nsec;
111 int older_mtime_filter;
112 time_t older_mtime_sec;
113 long older_mtime_nsec;
114 int older_ctime_filter;
115 time_t older_ctime_sec;
116 long older_ctime_nsec;
118 * Matching time stamps with its filename.
120 struct archive_rb_tree exclusion_tree;
121 struct entry_list exclusion_entry_list;
124 * Matching file owners.
126 struct id_array inclusion_uids;
127 struct id_array inclusion_gids;
128 struct match_list inclusion_unames;
129 struct match_list inclusion_gnames;
132 static int add_pattern_from_file(struct archive_match *,
133 struct match_list *, int, const void *, int);
134 static int add_entry(struct archive_match *, int,
135 struct archive_entry *);
136 static int add_owner_id(struct archive_match *, struct id_array *,
138 static int add_owner_name(struct archive_match *, struct match_list *,
140 static int add_pattern_mbs(struct archive_match *, struct match_list *,
142 static int add_pattern_wcs(struct archive_match *, struct match_list *,
144 static int cmp_key_mbs(const struct archive_rb_node *, const void *);
145 static int cmp_key_wcs(const struct archive_rb_node *, const void *);
146 static int cmp_node_mbs(const struct archive_rb_node *,
147 const struct archive_rb_node *);
148 static int cmp_node_wcs(const struct archive_rb_node *,
149 const struct archive_rb_node *);
150 static void entry_list_add(struct entry_list *, struct match_file *);
151 static void entry_list_free(struct entry_list *);
152 static void entry_list_init(struct entry_list *);
153 static int error_nomem(struct archive_match *);
154 static void match_list_add(struct match_list *, struct match *);
155 static void match_list_free(struct match_list *);
156 static void match_list_init(struct match_list *);
157 static int match_list_unmatched_inclusions_next(struct archive_match *,
158 struct match_list *, int, const void **);
159 static int match_owner_id(struct id_array *, int64_t);
160 #if !defined(_WIN32) || defined(__CYGWIN__)
161 static int match_owner_name_mbs(struct archive_match *,
162 struct match_list *, const char *);
164 static int match_owner_name_wcs(struct archive_match *,
165 struct match_list *, const wchar_t *);
167 static int match_path_exclusion(struct archive_match *,
168 struct match *, int, const void *);
169 static int match_path_inclusion(struct archive_match *,
170 struct match *, int, const void *);
171 static int owner_excluded(struct archive_match *,
172 struct archive_entry *);
173 static int path_excluded(struct archive_match *, int, const void *);
174 static int set_timefilter(struct archive_match *, int, time_t, long,
176 static int set_timefilter_pathname_mbs(struct archive_match *,
178 static int set_timefilter_pathname_wcs(struct archive_match *,
179 int, const wchar_t *);
180 static int set_timefilter_date(struct archive_match *, int, const char *);
181 static int set_timefilter_date_w(struct archive_match *, int,
183 static int time_excluded(struct archive_match *,
184 struct archive_entry *);
185 static int validate_time_flag(struct archive *, int, const char *);
187 time_t __archive_get_date(time_t now, 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 * Utilty 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 if (r != ARCHIVE_OK) {
584 archive_copy_error(&(a->archive), ar);
585 archive_read_free(ar);
589 r = archive_read_open_filename(ar, pathname, 512*20);
591 r = archive_read_open_filename_w(ar, pathname, 512*20);
592 if (r != ARCHIVE_OK) {
593 archive_copy_error(&(a->archive), ar);
594 archive_read_free(ar);
597 r = archive_read_next_header(ar, &ae);
598 if (r != ARCHIVE_OK) {
599 archive_copy_error(&(a->archive), ar);
600 archive_read_free(ar);
604 archive_string_init(&as);
606 while ((r = archive_read_data_block(ar, &buff, &size, &offset))
608 const char *b = (const char *)buff;
611 const char *s = (const char *)b;
613 int found_separator = 0;
615 while (length < size) {
622 if (*b == 0x0d || *b == 0x0a) {
630 if (!found_separator) {
631 archive_strncat(&as, s, length);
632 /* Read next data block. */
637 archive_strncat(&as, s, length);
639 /* If the line is not empty, add the pattern. */
640 if (archive_strlen(&as) > 0) {
642 r = add_pattern_mbs(a, mlist, as.s);
643 if (r != ARCHIVE_OK) {
644 archive_read_free(ar);
645 archive_string_free(&as);
648 archive_string_empty(&as);
653 /* If something error happend, report it immediately. */
654 if (r < ARCHIVE_OK) {
655 archive_copy_error(&(a->archive), ar);
656 archive_read_free(ar);
657 archive_string_free(&as);
661 /* If the line is not empty, add the pattern. */
662 if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
664 r = add_pattern_mbs(a, mlist, as.s);
665 if (r != ARCHIVE_OK) {
666 archive_read_free(ar);
667 archive_string_free(&as);
671 archive_read_free(ar);
672 archive_string_free(&as);
677 * Test if pathname is excluded by inclusion/exclusion patterns.
680 path_excluded(struct archive_match *a, int mbs, const void *pathname)
683 struct match *matched;
689 /* Mark off any unmatched inclusions. */
690 /* In particular, if a filename does appear in the archive and
691 * is explicitly included and excluded, then we don't report
692 * it as missing even though we don't extract it.
695 for (match = a->inclusions.first; match != NULL;
696 match = match->next){
697 if (match->matches == 0 &&
698 (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
701 a->inclusions.unmatched_count--;
707 /* Exclusions take priority */
708 for (match = a->exclusions.first; match != NULL;
709 match = match->next){
710 r = match_path_exclusion(a, match, mbs, pathname);
715 /* It's not excluded and we found an inclusion above, so it's
721 /* We didn't find an unmatched inclusion, check the remaining ones. */
722 for (match = a->inclusions.first; match != NULL;
723 match = match->next){
724 /* We looked at previously-unmatched inclusions already. */
725 if (match->matches > 0 &&
726 (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
734 /* If there were inclusions, default is to exclude. */
735 if (a->inclusions.first != NULL)
738 /* No explicit inclusions, default is to match. */
743 * This is a little odd, but it matches the default behavior of
744 * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
748 match_path_exclusion(struct archive_match *a, struct match *m,
749 int mbs, const void *pn)
751 int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
756 r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
758 return (archive_pathmatch(p, (const char *)pn, flag));
761 r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
763 return (archive_pathmatch_w(p, (const wchar_t *)pn,
767 return (error_nomem(a));
772 * Again, mimic gtar: inclusions are always anchored (have to match
773 * the beginning of the path) even though exclusions are not anchored.
776 match_path_inclusion(struct archive_match *a, struct match *m,
777 int mbs, const void *pn)
779 int flag = PATHMATCH_NO_ANCHOR_END;
784 r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
786 return (archive_pathmatch(p, (const char *)pn, flag));
789 r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
791 return (archive_pathmatch_w(p, (const wchar_t *)pn,
795 return (error_nomem(a));
800 match_list_init(struct match_list *list)
803 list->last = &(list->first);
808 match_list_free(struct match_list *list)
812 for (p = list->first; p != NULL; ) {
815 archive_mstring_clean(&(q->pattern));
821 match_list_add(struct match_list *list, struct match *m)
824 list->last = &(m->next);
826 list->unmatched_count++;
830 match_list_unmatched_inclusions_next(struct archive_match *a,
831 struct match_list *list, int mbs, const void **vp)
836 if (list->unmatched_eof) {
837 list->unmatched_eof = 0;
838 return (ARCHIVE_EOF);
840 if (list->unmatched_next == NULL) {
841 if (list->unmatched_count == 0)
842 return (ARCHIVE_EOF);
843 list->unmatched_next = list->first;
846 for (m = list->unmatched_next; m != NULL; m = m->next) {
853 r = archive_mstring_get_mbs(&(a->archive),
855 if (r < 0 && errno == ENOMEM)
856 return (error_nomem(a));
862 r = archive_mstring_get_wcs(&(a->archive),
864 if (r < 0 && errno == ENOMEM)
865 return (error_nomem(a));
870 list->unmatched_next = m->next;
871 if (list->unmatched_next == NULL)
872 /* To return EOF next time. */
873 list->unmatched_eof = 1;
876 list->unmatched_next = NULL;
877 return (ARCHIVE_EOF);
881 * Utility functions to manage inclusion timestamps.
884 archive_match_include_time(struct archive *_a, int flag, time_t sec,
889 r = validate_time_flag(_a, flag, "archive_match_include_time");
892 return set_timefilter((struct archive_match *)_a, flag,
893 sec, nsec, sec, nsec);
897 archive_match_include_date(struct archive *_a, int flag,
902 r = validate_time_flag(_a, flag, "archive_match_include_date");
905 return set_timefilter_date((struct archive_match *)_a, flag, datestr);
909 archive_match_include_date_w(struct archive *_a, int flag,
910 const wchar_t *datestr)
914 r = validate_time_flag(_a, flag, "archive_match_include_date_w");
918 return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
922 archive_match_include_file_time(struct archive *_a, int flag,
923 const char *pathname)
927 r = validate_time_flag(_a, flag, "archive_match_include_file_time");
930 return set_timefilter_pathname_mbs((struct archive_match *)_a,
935 archive_match_include_file_time_w(struct archive *_a, int flag,
936 const wchar_t *pathname)
940 r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
943 return set_timefilter_pathname_wcs((struct archive_match *)_a,
948 archive_match_exclude_entry(struct archive *_a, int flag,
949 struct archive_entry *entry)
951 struct archive_match *a;
954 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
955 ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
956 a = (struct archive_match *)_a;
959 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
960 return (ARCHIVE_FAILED);
962 r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
965 return (add_entry(a, flag, entry));
969 * Test function for time stamps.
971 * Returns 1 if archive entry is excluded.
972 * Returns 0 if archive entry is not excluded.
973 * Returns <0 if something error happened.
976 archive_match_time_excluded(struct archive *_a,
977 struct archive_entry *entry)
979 struct archive_match *a;
981 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
982 ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
984 a = (struct archive_match *)_a;
986 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
987 return (ARCHIVE_FAILED);
990 /* If we don't have inclusion time set at all, the entry is always
992 if ((a->setflag & TIME_IS_SET) == 0)
994 return (time_excluded(a, entry));
998 validate_time_flag(struct archive *_a, int flag, const char *_fn)
1000 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1001 ARCHIVE_STATE_NEW, _fn);
1003 /* Check a type of time. */
1005 ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
1006 archive_set_error(_a, EINVAL, "Invalid time flag");
1007 return (ARCHIVE_FAILED);
1009 if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
1010 archive_set_error(_a, EINVAL, "No time flag");
1011 return (ARCHIVE_FAILED);
1014 /* Check a type of comparison. */
1016 ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1017 | ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
1018 archive_set_error(_a, EINVAL, "Invalid comparison flag");
1019 return (ARCHIVE_FAILED);
1021 if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1022 | ARCHIVE_MATCH_EQUAL)) == 0) {
1023 archive_set_error(_a, EINVAL, "No comparison flag");
1024 return (ARCHIVE_FAILED);
1027 return (ARCHIVE_OK);
1030 #define JUST_EQUAL(t) (((t) & (ARCHIVE_MATCH_EQUAL |\
1031 ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
1033 set_timefilter(struct archive_match *a, int timetype,
1034 time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
1036 if (timetype & ARCHIVE_MATCH_MTIME) {
1037 if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1038 a->newer_mtime_filter = timetype;
1039 a->newer_mtime_sec = mtime_sec;
1040 a->newer_mtime_nsec = mtime_nsec;
1041 a->setflag |= TIME_IS_SET;
1043 if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1044 a->older_mtime_filter = timetype;
1045 a->older_mtime_sec = mtime_sec;
1046 a->older_mtime_nsec = mtime_nsec;
1047 a->setflag |= TIME_IS_SET;
1050 if (timetype & ARCHIVE_MATCH_CTIME) {
1051 if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1052 a->newer_ctime_filter = timetype;
1053 a->newer_ctime_sec = ctime_sec;
1054 a->newer_ctime_nsec = ctime_nsec;
1055 a->setflag |= TIME_IS_SET;
1057 if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1058 a->older_ctime_filter = timetype;
1059 a->older_ctime_sec = ctime_sec;
1060 a->older_ctime_nsec = ctime_nsec;
1061 a->setflag |= TIME_IS_SET;
1064 return (ARCHIVE_OK);
1068 set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
1072 if (datestr == NULL || *datestr == '\0') {
1073 archive_set_error(&(a->archive), EINVAL, "date is empty");
1074 return (ARCHIVE_FAILED);
1076 t = get_date(a->now, datestr);
1077 if (t == (time_t)-1) {
1078 archive_set_error(&(a->archive), EINVAL, "invalid date string");
1079 return (ARCHIVE_FAILED);
1081 return set_timefilter(a, timetype, t, 0, t, 0);
1085 set_timefilter_date_w(struct archive_match *a, int timetype,
1086 const wchar_t *datestr)
1088 struct archive_string as;
1091 if (datestr == NULL || *datestr == L'\0') {
1092 archive_set_error(&(a->archive), EINVAL, "date is empty");
1093 return (ARCHIVE_FAILED);
1096 archive_string_init(&as);
1097 if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
1098 archive_string_free(&as);
1099 if (errno == ENOMEM)
1100 return (error_nomem(a));
1101 archive_set_error(&(a->archive), -1,
1102 "Failed to convert WCS to MBS");
1103 return (ARCHIVE_FAILED);
1105 t = get_date(a->now, as.s);
1106 archive_string_free(&as);
1107 if (t == (time_t)-1) {
1108 archive_set_error(&(a->archive), EINVAL, "invalid date string");
1109 return (ARCHIVE_FAILED);
1111 return set_timefilter(a, timetype, t, 0, t, 0);
1114 #if defined(_WIN32) && !defined(__CYGWIN__)
1115 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1117 set_timefilter_find_data(struct archive_match *a, int timetype,
1118 DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
1119 DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
1122 time_t ctime_sec, mtime_sec;
1123 long ctime_ns, mtime_ns;
1125 utc.HighPart = ftCreationTime_dwHighDateTime;
1126 utc.LowPart = ftCreationTime_dwLowDateTime;
1127 if (utc.QuadPart >= EPOC_TIME) {
1128 utc.QuadPart -= EPOC_TIME;
1129 ctime_sec = (time_t)(utc.QuadPart / 10000000);
1130 ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
1135 utc.HighPart = ftLastWriteTime_dwHighDateTime;
1136 utc.LowPart = ftLastWriteTime_dwLowDateTime;
1137 if (utc.QuadPart >= EPOC_TIME) {
1138 utc.QuadPart -= EPOC_TIME;
1139 mtime_sec = (time_t)(utc.QuadPart / 10000000);
1140 mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
1145 return set_timefilter(a, timetype,
1146 mtime_sec, mtime_ns, ctime_sec, ctime_ns);
1150 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1153 /* NOTE: stat() on Windows cannot handle nano seconds. */
1157 if (path == NULL || *path == '\0') {
1158 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1159 return (ARCHIVE_FAILED);
1161 h = FindFirstFileA(path, &d);
1162 if (h == INVALID_HANDLE_VALUE) {
1163 la_dosmaperr(GetLastError());
1164 archive_set_error(&(a->archive), errno,
1165 "Failed to FindFirstFileA");
1166 return (ARCHIVE_FAILED);
1169 return set_timefilter_find_data(a, timetype,
1170 d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1171 d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1175 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1176 const wchar_t *path)
1181 if (path == NULL || *path == L'\0') {
1182 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1183 return (ARCHIVE_FAILED);
1185 h = FindFirstFileW(path, &d);
1186 if (h == INVALID_HANDLE_VALUE) {
1187 la_dosmaperr(GetLastError());
1188 archive_set_error(&(a->archive), errno,
1189 "Failed to FindFirstFile");
1190 return (ARCHIVE_FAILED);
1193 return set_timefilter_find_data(a, timetype,
1194 d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1195 d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1198 #else /* _WIN32 && !__CYGWIN__ */
1201 set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
1203 struct archive_entry *ae;
1204 time_t ctime_sec, mtime_sec;
1205 long ctime_ns, mtime_ns;
1207 ae = archive_entry_new();
1209 return (error_nomem(a));
1210 archive_entry_copy_stat(ae, st);
1211 ctime_sec = archive_entry_ctime(ae);
1212 ctime_ns = archive_entry_ctime_nsec(ae);
1213 mtime_sec = archive_entry_mtime(ae);
1214 mtime_ns = archive_entry_mtime_nsec(ae);
1215 archive_entry_free(ae);
1216 return set_timefilter(a, timetype, mtime_sec, mtime_ns,
1217 ctime_sec, ctime_ns);
1221 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1226 if (path == NULL || *path == '\0') {
1227 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1228 return (ARCHIVE_FAILED);
1230 if (stat(path, &st) != 0) {
1231 archive_set_error(&(a->archive), errno, "Failed to stat()");
1232 return (ARCHIVE_FAILED);
1234 return (set_timefilter_stat(a, timetype, &st));
1238 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1239 const wchar_t *path)
1241 struct archive_string as;
1244 if (path == NULL || *path == L'\0') {
1245 archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1246 return (ARCHIVE_FAILED);
1249 /* Convert WCS filename to MBS filename. */
1250 archive_string_init(&as);
1251 if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
1252 archive_string_free(&as);
1253 if (errno == ENOMEM)
1254 return (error_nomem(a));
1255 archive_set_error(&(a->archive), -1,
1256 "Failed to convert WCS to MBS");
1257 return (ARCHIVE_FAILED);
1260 r = set_timefilter_pathname_mbs(a, timetype, as.s);
1261 archive_string_free(&as);
1265 #endif /* _WIN32 && !__CYGWIN__ */
1268 * Call back funtions for archive_rb.
1271 cmp_node_mbs(const struct archive_rb_node *n1,
1272 const struct archive_rb_node *n2)
1274 struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1275 struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1276 const char *p1, *p2;
1278 archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
1279 archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
1284 return (strcmp(p1, p2));
1288 cmp_key_mbs(const struct archive_rb_node *n, const void *key)
1290 struct match_file *f = (struct match_file *)(uintptr_t)n;
1293 archive_mstring_get_mbs(NULL, &(f->pathname), &p);
1296 return (strcmp(p, (const char *)key));
1300 cmp_node_wcs(const struct archive_rb_node *n1,
1301 const struct archive_rb_node *n2)
1303 struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1304 struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1305 const wchar_t *p1, *p2;
1307 archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
1308 archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
1313 return (wcscmp(p1, p2));
1317 cmp_key_wcs(const struct archive_rb_node *n, const void *key)
1319 struct match_file *f = (struct match_file *)(uintptr_t)n;
1322 archive_mstring_get_wcs(NULL, &(f->pathname), &p);
1325 return (wcscmp(p, (const wchar_t *)key));
1329 entry_list_init(struct entry_list *list)
1332 list->last = &(list->first);
1337 entry_list_free(struct entry_list *list)
1339 struct match_file *p, *q;
1341 for (p = list->first; p != NULL; ) {
1344 archive_mstring_clean(&(q->pathname));
1350 entry_list_add(struct entry_list *list, struct match_file *file)
1353 list->last = &(file->next);
1358 add_entry(struct archive_match *a, int flag,
1359 struct archive_entry *entry)
1361 struct match_file *f;
1362 const void *pathname;
1365 f = calloc(1, sizeof(*f));
1367 return (error_nomem(a));
1369 #if defined(_WIN32) && !defined(__CYGWIN__)
1370 pathname = archive_entry_pathname_w(entry);
1371 if (pathname == NULL) {
1373 archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1374 return (ARCHIVE_FAILED);
1376 archive_mstring_copy_wcs(&(f->pathname), pathname);
1377 a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1380 pathname = archive_entry_pathname(entry);
1381 if (pathname == NULL) {
1383 archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1384 return (ARCHIVE_FAILED);
1386 archive_mstring_copy_mbs(&(f->pathname), pathname);
1387 a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1390 f->mtime_sec = archive_entry_mtime(entry);
1391 f->mtime_nsec = archive_entry_mtime_nsec(entry);
1392 f->ctime_sec = archive_entry_ctime(entry);
1393 f->ctime_nsec = archive_entry_ctime_nsec(entry);
1394 r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
1396 struct match_file *f2;
1398 /* Get the duplicated file. */
1399 f2 = (struct match_file *)__archive_rb_tree_find_node(
1400 &(a->exclusion_tree), pathname);
1403 * We always overwrite comparison condision.
1404 * If you do not want to overwrite it, you should not
1405 * call archive_match_exclude_entry(). We cannot know
1406 * what behavior you really expect since overwriting
1407 * condition might be different with the flag.
1411 f2->mtime_sec = f->mtime_sec;
1412 f2->mtime_nsec = f->mtime_nsec;
1413 f2->ctime_sec = f->ctime_sec;
1414 f2->ctime_nsec = f->ctime_nsec;
1416 /* Release the duplicated file. */
1417 archive_mstring_clean(&(f->pathname));
1419 return (ARCHIVE_OK);
1421 entry_list_add(&(a->exclusion_entry_list), f);
1422 a->setflag |= TIME_IS_SET;
1423 return (ARCHIVE_OK);
1427 * Test if entry is excluded by its timestamp.
1430 time_excluded(struct archive_match *a, struct archive_entry *entry)
1432 struct match_file *f;
1433 const void *pathname;
1438 * If this file/dir is excluded by a time comparison, skip it.
1440 if (a->newer_ctime_filter) {
1441 /* If ctime is not set, use mtime instead. */
1442 if (archive_entry_ctime_is_set(entry))
1443 sec = archive_entry_ctime(entry);
1445 sec = archive_entry_mtime(entry);
1446 if (sec < a->newer_ctime_sec)
1447 return (1); /* Too old, skip it. */
1448 if (sec == a->newer_ctime_sec) {
1449 if (archive_entry_ctime_is_set(entry))
1450 nsec = archive_entry_ctime_nsec(entry);
1452 nsec = archive_entry_mtime_nsec(entry);
1453 if (nsec < a->newer_ctime_nsec)
1454 return (1); /* Too old, skip it. */
1455 if (nsec == a->newer_ctime_nsec &&
1456 (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
1458 return (1); /* Equal, skip it. */
1461 if (a->older_ctime_filter) {
1462 /* If ctime is not set, use mtime instead. */
1463 if (archive_entry_ctime_is_set(entry))
1464 sec = archive_entry_ctime(entry);
1466 sec = archive_entry_mtime(entry);
1467 if (sec > a->older_ctime_sec)
1468 return (1); /* Too new, skip it. */
1469 if (sec == a->older_ctime_sec) {
1470 if (archive_entry_ctime_is_set(entry))
1471 nsec = archive_entry_ctime_nsec(entry);
1473 nsec = archive_entry_mtime_nsec(entry);
1474 if (nsec > a->older_ctime_nsec)
1475 return (1); /* Too new, skip it. */
1476 if (nsec == a->older_ctime_nsec &&
1477 (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
1479 return (1); /* Eeual, skip it. */
1482 if (a->newer_mtime_filter) {
1483 sec = archive_entry_mtime(entry);
1484 if (sec < a->newer_mtime_sec)
1485 return (1); /* Too old, skip it. */
1486 if (sec == a->newer_mtime_sec) {
1487 nsec = archive_entry_mtime_nsec(entry);
1488 if (nsec < a->newer_mtime_nsec)
1489 return (1); /* Too old, skip it. */
1490 if (nsec == a->newer_mtime_nsec &&
1491 (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
1493 return (1); /* Equal, skip it. */
1496 if (a->older_mtime_filter) {
1497 sec = archive_entry_mtime(entry);
1498 if (sec > a->older_mtime_sec)
1499 return (1); /* Too new, skip it. */
1500 nsec = archive_entry_mtime_nsec(entry);
1501 if (sec == a->older_mtime_sec) {
1502 if (nsec > a->older_mtime_nsec)
1503 return (1); /* Too new, skip it. */
1504 if (nsec == a->older_mtime_nsec &&
1505 (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
1507 return (1); /* Equal, skip it. */
1511 /* If there is no excluson list, include the file. */
1512 if (a->exclusion_entry_list.count == 0)
1515 #if defined(_WIN32) && !defined(__CYGWIN__)
1516 pathname = archive_entry_pathname_w(entry);
1517 a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1520 pathname = archive_entry_pathname(entry);
1521 a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1523 if (pathname == NULL)
1526 f = (struct match_file *)__archive_rb_tree_find_node(
1527 &(a->exclusion_tree), pathname);
1528 /* If the file wasn't rejected, include it. */
1532 if (f->flag & ARCHIVE_MATCH_CTIME) {
1533 sec = archive_entry_ctime(entry);
1534 if (f->ctime_sec > sec) {
1535 if (f->flag & ARCHIVE_MATCH_OLDER)
1537 } else if (f->ctime_sec < sec) {
1538 if (f->flag & ARCHIVE_MATCH_NEWER)
1541 nsec = archive_entry_ctime_nsec(entry);
1542 if (f->ctime_nsec > nsec) {
1543 if (f->flag & ARCHIVE_MATCH_OLDER)
1545 } else if (f->ctime_nsec < nsec) {
1546 if (f->flag & ARCHIVE_MATCH_NEWER)
1548 } else if (f->flag & ARCHIVE_MATCH_EQUAL)
1552 if (f->flag & ARCHIVE_MATCH_MTIME) {
1553 sec = archive_entry_mtime(entry);
1554 if (f->mtime_sec > sec) {
1555 if (f->flag & ARCHIVE_MATCH_OLDER)
1557 } else if (f->mtime_sec < sec) {
1558 if (f->flag & ARCHIVE_MATCH_NEWER)
1561 nsec = archive_entry_mtime_nsec(entry);
1562 if (f->mtime_nsec > nsec) {
1563 if (f->flag & ARCHIVE_MATCH_OLDER)
1565 } else if (f->mtime_nsec < nsec) {
1566 if (f->flag & ARCHIVE_MATCH_NEWER)
1568 } else if (f->flag & ARCHIVE_MATCH_EQUAL)
1576 * Utility functions to manage inclusion owners
1580 archive_match_include_uid(struct archive *_a, int64_t uid)
1582 struct archive_match *a;
1584 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1585 ARCHIVE_STATE_NEW, "archive_match_include_uid");
1586 a = (struct archive_match *)_a;
1587 return (add_owner_id(a, &(a->inclusion_uids), uid));
1591 archive_match_include_gid(struct archive *_a, int64_t gid)
1593 struct archive_match *a;
1595 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1596 ARCHIVE_STATE_NEW, "archive_match_include_gid");
1597 a = (struct archive_match *)_a;
1598 return (add_owner_id(a, &(a->inclusion_gids), gid));
1602 archive_match_include_uname(struct archive *_a, const char *uname)
1604 struct archive_match *a;
1606 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1607 ARCHIVE_STATE_NEW, "archive_match_include_uname");
1608 a = (struct archive_match *)_a;
1609 return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
1613 archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
1615 struct archive_match *a;
1617 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1618 ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
1619 a = (struct archive_match *)_a;
1620 return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
1624 archive_match_include_gname(struct archive *_a, const char *gname)
1626 struct archive_match *a;
1628 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1629 ARCHIVE_STATE_NEW, "archive_match_include_gname");
1630 a = (struct archive_match *)_a;
1631 return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
1635 archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
1637 struct archive_match *a;
1639 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1640 ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
1641 a = (struct archive_match *)_a;
1642 return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
1646 * Test function for owner(uid, gid, uname, gname).
1648 * Returns 1 if archive entry is excluded.
1649 * Returns 0 if archive entry is not excluded.
1650 * Returns <0 if something error happened.
1653 archive_match_owner_excluded(struct archive *_a,
1654 struct archive_entry *entry)
1656 struct archive_match *a;
1658 archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1659 ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
1661 a = (struct archive_match *)_a;
1662 if (entry == NULL) {
1663 archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1664 return (ARCHIVE_FAILED);
1667 /* If we don't have inclusion id set at all, the entry is always
1669 if ((a->setflag & ID_IS_SET) == 0)
1671 return (owner_excluded(a, entry));
1675 add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
1679 if (ids->count + 1 >= ids->size) {
1686 p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
1688 return (error_nomem(a));
1689 ids->ids = (int64_t *)p;
1692 /* Find an insert point. */
1693 for (i = 0; i < ids->count; i++) {
1694 if (ids->ids[i] >= id)
1698 /* Add oowner id. */
1699 if (i == ids->count)
1700 ids->ids[ids->count++] = id;
1701 else if (ids->ids[i] != id) {
1702 memmove(&(ids->ids[i+1]), &(ids->ids[i]),
1703 (ids->count - i) * sizeof(ids->ids[0]));
1707 a->setflag |= ID_IS_SET;
1708 return (ARCHIVE_OK);
1712 match_owner_id(struct id_array *ids, int64_t id)
1717 b = (unsigned)ids->count;
1720 if (ids->ids[m] == id)
1722 if (ids->ids[m] < id)
1731 add_owner_name(struct archive_match *a, struct match_list *list,
1732 int mbs, const void *name)
1734 struct match *match;
1736 match = calloc(1, sizeof(*match));
1738 return (error_nomem(a));
1740 archive_mstring_copy_mbs(&(match->pattern), name);
1742 archive_mstring_copy_wcs(&(match->pattern), name);
1743 match_list_add(list, match);
1744 a->setflag |= ID_IS_SET;
1745 return (ARCHIVE_OK);
1748 #if !defined(_WIN32) || defined(__CYGWIN__)
1750 match_owner_name_mbs(struct archive_match *a, struct match_list *list,
1756 if (name == NULL || *name == '\0')
1758 for (m = list->first; m; m = m->next) {
1759 if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
1760 < 0 && errno == ENOMEM)
1761 return (error_nomem(a));
1762 if (p != NULL && strcmp(p, name) == 0) {
1771 match_owner_name_wcs(struct archive_match *a, struct match_list *list,
1772 const wchar_t *name)
1777 if (name == NULL || *name == L'\0')
1779 for (m = list->first; m; m = m->next) {
1780 if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
1781 < 0 && errno == ENOMEM)
1782 return (error_nomem(a));
1783 if (p != NULL && wcscmp(p, name) == 0) {
1793 * Test if entry is excluded by uid, gid, uname or gname.
1796 owner_excluded(struct archive_match *a, struct archive_entry *entry)
1800 if (a->inclusion_uids.count) {
1801 if (!match_owner_id(&(a->inclusion_uids),
1802 archive_entry_uid(entry)))
1806 if (a->inclusion_gids.count) {
1807 if (!match_owner_id(&(a->inclusion_gids),
1808 archive_entry_gid(entry)))
1812 if (a->inclusion_unames.count) {
1813 #if defined(_WIN32) && !defined(__CYGWIN__)
1814 r = match_owner_name_wcs(a, &(a->inclusion_unames),
1815 archive_entry_uname_w(entry));
1817 r = match_owner_name_mbs(a, &(a->inclusion_unames),
1818 archive_entry_uname(entry));
1826 if (a->inclusion_gnames.count) {
1827 #if defined(_WIN32) && !defined(__CYGWIN__)
1828 r = match_owner_name_wcs(a, &(a->inclusion_gnames),
1829 archive_entry_gname_w(entry));
1831 r = match_owner_name_mbs(a, &(a->inclusion_gnames),
1832 archive_entry_gname(entry));