xref: /freebsd/contrib/libarchive/libarchive/archive_match.c (revision 2e113ef82465598b8c26e0ca415fbe90677fbd47)
1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * Copyright (c) 2012 Michihiro NAKAJIMA
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
14  *
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.
25  */
26 
27 #include "archive_platform.h"
28 
29 #ifdef HAVE_ERRNO_H
30 #include <errno.h>
31 #endif
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h>
34 #endif
35 #ifdef HAVE_STRING_H
36 #include <string.h>
37 #endif
38 #ifdef HAVE_LIMITS_H
39 #include <limits.h>
40 #endif
41 
42 #include "archive.h"
43 #include "archive_private.h"
44 #include "archive_entry.h"
45 #include "archive_pathmatch.h"
46 #include "archive_rb.h"
47 #include "archive_string.h"
48 #include "archive_time_private.h"
49 
50 struct match {
51 	struct match		*next;
52 	int			 matched;
53 	struct archive_mstring	 pattern;
54 };
55 
56 struct match_list {
57 	struct match		*first;
58 	struct match		**last;
59 	size_t			 unmatched_count;
60 	struct match		*unmatched_next;
61 	int			 unmatched_eof;
62 };
63 
64 struct match_file {
65 	struct archive_rb_node	 node;
66 	struct match_file	*next;
67 	struct archive_mstring	 pathname;
68 	int			 flag;
69 	time_t			 mtime_sec;
70 	long			 mtime_nsec;
71 	time_t			 ctime_sec;
72 	long			 ctime_nsec;
73 };
74 
75 struct entry_list {
76 	struct match_file	*first;
77 	struct match_file	**last;
78 };
79 
80 struct id_array {
81 	size_t			 size;/* Allocated size */
82 	size_t			 count;
83 	int64_t			*ids;
84 };
85 
86 #define PATTERN_IS_SET		1
87 #define TIME_IS_SET		2
88 #define ID_IS_SET		4
89 
90 struct archive_match {
91 	struct archive		 archive;
92 
93 	/* exclusion/inclusion set flag. */
94 	int			 setflag;
95 
96 	/* Recursively include directory content? */
97 	int			 recursive_include;
98 
99 	/*
100 	 * Matching filename patterns.
101 	 */
102 	struct match_list	 exclusions;
103 	struct match_list	 inclusions;
104 
105 	/*
106 	 * Matching time stamps.
107 	 */
108 	time_t			 now;
109 	int			 newer_mtime_filter;
110 	time_t			 newer_mtime_sec;
111 	long			 newer_mtime_nsec;
112 	int			 newer_ctime_filter;
113 	time_t			 newer_ctime_sec;
114 	long			 newer_ctime_nsec;
115 	int			 older_mtime_filter;
116 	time_t			 older_mtime_sec;
117 	long			 older_mtime_nsec;
118 	int			 older_ctime_filter;
119 	time_t			 older_ctime_sec;
120 	long			 older_ctime_nsec;
121 	/*
122 	 * Matching time stamps with its filename.
123 	 */
124 	struct archive_rb_tree	 exclusion_tree;
125 	struct entry_list 	 exclusion_entry_list;
126 
127 	/*
128 	 * Matching file owners.
129 	 */
130 	struct id_array 	 inclusion_uids;
131 	struct id_array 	 inclusion_gids;
132 	struct match_list	 inclusion_unames;
133 	struct match_list	 inclusion_gnames;
134 };
135 
136 static int	add_pattern_from_file(struct archive_match *,
137 		    struct match_list *, int, const void *, int);
138 static int	add_entry(struct archive_match *, int,
139 		    struct archive_entry *);
140 static int	add_owner_id(struct archive_match *, struct id_array *,
141 		    int64_t);
142 static int	add_owner_name(struct archive_match *, struct match_list *,
143 		    int, const void *);
144 static int	add_pattern_mbs(struct archive_match *, struct match_list *,
145 		    const char *);
146 static int	add_pattern_wcs(struct archive_match *, struct match_list *,
147 		    const wchar_t *);
148 #if !defined(_WIN32) || defined(__CYGWIN__)
149 static int	cmp_key_mbs(const struct archive_rb_node *, const void *);
150 static int	cmp_node_mbs(const struct archive_rb_node *,
151 		    const struct archive_rb_node *);
152 #else
153 static int	cmp_key_wcs(const struct archive_rb_node *, const void *);
154 static int	cmp_node_wcs(const struct archive_rb_node *,
155 		    const struct archive_rb_node *);
156 #endif
157 static void	entry_list_add(struct entry_list *, struct match_file *);
158 static void	entry_list_free(struct entry_list *);
159 static void	entry_list_init(struct entry_list *);
160 static int	error_nomem(struct archive_match *);
161 static void	match_list_add(struct match_list *, struct match *);
162 static void	match_list_free(struct match_list *);
163 static void	match_list_init(struct match_list *);
164 static int	match_list_unmatched_inclusions_next(struct archive_match *,
165 		    struct match_list *, int, const void **);
166 static int	match_owner_id(struct id_array *, int64_t);
167 #if !defined(_WIN32) || defined(__CYGWIN__)
168 static int	match_owner_name_mbs(struct archive_match *,
169 		    struct match_list *, const char *);
170 #else
171 static int	match_owner_name_wcs(struct archive_match *,
172 		    struct match_list *, const wchar_t *);
173 #endif
174 static int	match_path_exclusion(struct archive_match *,
175 		    struct match *, int, const void *);
176 static int	match_path_inclusion(struct archive_match *,
177 		    struct match *, int, const void *);
178 static int	owner_excluded(struct archive_match *,
179 		    struct archive_entry *);
180 static int	path_excluded(struct archive_match *, int, const void *);
181 static int	set_timefilter(struct archive_match *, int, time_t, long,
182 		    time_t, long);
183 static int	set_timefilter_pathname_mbs(struct archive_match *,
184 		    int, const char *);
185 static int	set_timefilter_pathname_wcs(struct archive_match *,
186 		    int, const wchar_t *);
187 static int	set_timefilter_date(struct archive_match *, int, const char *);
188 static int	set_timefilter_date_w(struct archive_match *, int,
189 		    const wchar_t *);
190 static int	time_excluded(struct archive_match *,
191 		    struct archive_entry *);
192 static int	validate_time_flag(struct archive *, int, const char *);
193 
194 #define get_date archive_parse_date
195 
196 static const struct archive_rb_tree_ops rb_ops = {
197 #if !defined(_WIN32) || defined(__CYGWIN__)
198 	cmp_node_mbs, cmp_key_mbs
199 #else
200 	cmp_node_wcs, cmp_key_wcs
201 #endif
202 };
203 
204 /*
205  * The matching logic here needs to be re-thought.  I started out to
206  * try to mimic gtar's matching logic, but it's not entirely
207  * consistent.  In particular 'tar -t' and 'tar -x' interpret patterns
208  * on the command line as anchored, but --exclude doesn't.
209  */
210 
211 static int
error_nomem(struct archive_match * a)212 error_nomem(struct archive_match *a)
213 {
214 	archive_set_error(&(a->archive), ENOMEM, "No memory");
215 	a->archive.state = ARCHIVE_STATE_FATAL;
216 	return (ARCHIVE_FATAL);
217 }
218 
219 /*
220  * Create an ARCHIVE_MATCH object.
221  */
222 struct archive *
archive_match_new(void)223 archive_match_new(void)
224 {
225 	struct archive_match *a;
226 
227 	a = calloc(1, sizeof(*a));
228 	if (a == NULL)
229 		return (NULL);
230 	a->archive.magic = ARCHIVE_MATCH_MAGIC;
231 	a->archive.state = ARCHIVE_STATE_NEW;
232 	a->recursive_include = 1;
233 	match_list_init(&(a->inclusions));
234 	match_list_init(&(a->exclusions));
235 	__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops);
236 	entry_list_init(&(a->exclusion_entry_list));
237 	match_list_init(&(a->inclusion_unames));
238 	match_list_init(&(a->inclusion_gnames));
239 	time(&a->now);
240 	return (&(a->archive));
241 }
242 
243 /*
244  * Free an ARCHIVE_MATCH object.
245  */
246 int
archive_match_free(struct archive * _a)247 archive_match_free(struct archive *_a)
248 {
249 	struct archive_match *a;
250 
251 	if (_a == NULL)
252 		return (ARCHIVE_OK);
253 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
254 	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free");
255 	a = (struct archive_match *)_a;
256 	match_list_free(&(a->inclusions));
257 	match_list_free(&(a->exclusions));
258 	entry_list_free(&(a->exclusion_entry_list));
259 	free(a->inclusion_uids.ids);
260 	free(a->inclusion_gids.ids);
261 	match_list_free(&(a->inclusion_unames));
262 	match_list_free(&(a->inclusion_gnames));
263 	free(a);
264 	return (ARCHIVE_OK);
265 }
266 
267 /*
268  * Convenience function to perform all exclusion tests.
269  *
270  * Returns 1 if archive entry is excluded.
271  * Returns 0 if archive entry is not excluded.
272  * Returns <0 if something error happened.
273  */
274 int
archive_match_excluded(struct archive * _a,struct archive_entry * entry)275 archive_match_excluded(struct archive *_a, struct archive_entry *entry)
276 {
277 	struct archive_match *a;
278 	int r;
279 
280 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
281 	    ARCHIVE_STATE_NEW, "archive_match_excluded_ae");
282 
283 	a = (struct archive_match *)_a;
284 	if (entry == NULL) {
285 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
286 		return (ARCHIVE_FAILED);
287 	}
288 
289 	r = 0;
290 	if (a->setflag & PATTERN_IS_SET) {
291 #if defined(_WIN32) && !defined(__CYGWIN__)
292 		r = path_excluded(a, 0, archive_entry_pathname_w(entry));
293 #else
294 		r = path_excluded(a, 1, archive_entry_pathname(entry));
295 #endif
296 		if (r != 0)
297 			return (r);
298 	}
299 
300 	if (a->setflag & TIME_IS_SET) {
301 		r = time_excluded(a, entry);
302 		if (r != 0)
303 			return (r);
304 	}
305 
306 	if (a->setflag & ID_IS_SET)
307 		r = owner_excluded(a, entry);
308 	return (r);
309 }
310 
311 /*
312  * Utility functions to manage exclusion/inclusion patterns
313  */
314 
315 int
archive_match_exclude_pattern(struct archive * _a,const char * pattern)316 archive_match_exclude_pattern(struct archive *_a, const char *pattern)
317 {
318 	struct archive_match *a;
319 	int r;
320 
321 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
322 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern");
323 	a = (struct archive_match *)_a;
324 
325 	if (pattern == NULL || *pattern == '\0') {
326 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
327 		return (ARCHIVE_FAILED);
328 	}
329 	if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
330 		return (r);
331 	return (ARCHIVE_OK);
332 }
333 
334 int
archive_match_exclude_pattern_w(struct archive * _a,const wchar_t * pattern)335 archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern)
336 {
337 	struct archive_match *a;
338 	int r;
339 
340 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
341 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w");
342 	a = (struct archive_match *)_a;
343 
344 	if (pattern == NULL || *pattern == L'\0') {
345 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
346 		return (ARCHIVE_FAILED);
347 	}
348 	if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
349 		return (r);
350 	return (ARCHIVE_OK);
351 }
352 
353 int
archive_match_exclude_pattern_from_file(struct archive * _a,const char * pathname,int nullSeparator)354 archive_match_exclude_pattern_from_file(struct archive *_a,
355     const char *pathname, int nullSeparator)
356 {
357 	struct archive_match *a;
358 
359 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
360 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file");
361 	a = (struct archive_match *)_a;
362 
363 	return add_pattern_from_file(a, &(a->exclusions), 1, pathname,
364 		nullSeparator);
365 }
366 
367 int
archive_match_exclude_pattern_from_file_w(struct archive * _a,const wchar_t * pathname,int nullSeparator)368 archive_match_exclude_pattern_from_file_w(struct archive *_a,
369     const wchar_t *pathname, int nullSeparator)
370 {
371 	struct archive_match *a;
372 
373 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
374 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w");
375 	a = (struct archive_match *)_a;
376 
377 	return add_pattern_from_file(a, &(a->exclusions), 0, pathname,
378 		nullSeparator);
379 }
380 
381 int
archive_match_include_pattern(struct archive * _a,const char * pattern)382 archive_match_include_pattern(struct archive *_a, const char *pattern)
383 {
384 	struct archive_match *a;
385 	int r;
386 
387 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
388 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern");
389 	a = (struct archive_match *)_a;
390 
391 	if (pattern == NULL || *pattern == '\0') {
392 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
393 		return (ARCHIVE_FAILED);
394 	}
395 	if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
396 		return (r);
397 	return (ARCHIVE_OK);
398 }
399 
400 int
archive_match_include_pattern_w(struct archive * _a,const wchar_t * pattern)401 archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern)
402 {
403 	struct archive_match *a;
404 	int r;
405 
406 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
407 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_w");
408 	a = (struct archive_match *)_a;
409 
410 	if (pattern == NULL || *pattern == L'\0') {
411 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
412 		return (ARCHIVE_FAILED);
413 	}
414 	if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
415 		return (r);
416 	return (ARCHIVE_OK);
417 }
418 
419 int
archive_match_include_pattern_from_file(struct archive * _a,const char * pathname,int nullSeparator)420 archive_match_include_pattern_from_file(struct archive *_a,
421     const char *pathname, int nullSeparator)
422 {
423 	struct archive_match *a;
424 
425 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
426 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file");
427 	a = (struct archive_match *)_a;
428 
429 	return add_pattern_from_file(a, &(a->inclusions), 1, pathname,
430 		nullSeparator);
431 }
432 
433 int
archive_match_include_pattern_from_file_w(struct archive * _a,const wchar_t * pathname,int nullSeparator)434 archive_match_include_pattern_from_file_w(struct archive *_a,
435     const wchar_t *pathname, int nullSeparator)
436 {
437 	struct archive_match *a;
438 
439 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
440 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w");
441 	a = (struct archive_match *)_a;
442 
443 	return add_pattern_from_file(a, &(a->inclusions), 0, pathname,
444 		nullSeparator);
445 }
446 
447 /*
448  * Test functions for pathname patterns.
449  *
450  * Returns 1 if archive entry is excluded.
451  * Returns 0 if archive entry is not excluded.
452  * Returns <0 if something error happened.
453  */
454 int
archive_match_path_excluded(struct archive * _a,struct archive_entry * entry)455 archive_match_path_excluded(struct archive *_a,
456     struct archive_entry *entry)
457 {
458 	struct archive_match *a;
459 
460 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
461 	    ARCHIVE_STATE_NEW, "archive_match_path_excluded");
462 
463 	a = (struct archive_match *)_a;
464 	if (entry == NULL) {
465 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
466 		return (ARCHIVE_FAILED);
467 	}
468 
469 	/* If we don't have exclusion/inclusion pattern set at all,
470 	 * the entry is always not excluded. */
471 	if ((a->setflag & PATTERN_IS_SET) == 0)
472 		return (0);
473 #if defined(_WIN32) && !defined(__CYGWIN__)
474 	return (path_excluded(a, 0, archive_entry_pathname_w(entry)));
475 #else
476 	return (path_excluded(a, 1, archive_entry_pathname(entry)));
477 #endif
478 }
479 
480 /*
481  * When recursive inclusion of directory content is enabled,
482  * an inclusion pattern that matches a directory will also
483  * include everything beneath that directory. Enabled by default.
484  *
485  * For compatibility with GNU tar, exclusion patterns always
486  * match if a subset of the full patch matches (i.e., they are
487  * are not rooted at the beginning of the path) and thus there
488  * is no corresponding non-recursive exclusion mode.
489  */
490 int
archive_match_set_inclusion_recursion(struct archive * _a,int enabled)491 archive_match_set_inclusion_recursion(struct archive *_a, int enabled)
492 {
493 	struct archive_match *a;
494 
495 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
496 	    ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion");
497 	a = (struct archive_match *)_a;
498 	a->recursive_include = enabled;
499 	return (ARCHIVE_OK);
500 }
501 
502 /*
503  * Utility functions to get statistic information for inclusion patterns.
504  */
505 int
archive_match_path_unmatched_inclusions(struct archive * _a)506 archive_match_path_unmatched_inclusions(struct archive *_a)
507 {
508 	struct archive_match *a;
509 
510 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
511 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
512 	a = (struct archive_match *)_a;
513 
514 	if (a->inclusions.unmatched_count > (size_t)INT_MAX)
515 		return INT_MAX;
516 	return (int)(a->inclusions.unmatched_count);
517 }
518 
519 int
archive_match_path_unmatched_inclusions_next(struct archive * _a,const char ** _p)520 archive_match_path_unmatched_inclusions_next(struct archive *_a,
521     const char **_p)
522 {
523 	struct archive_match *a;
524 	const void *v;
525 	int r;
526 
527 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
528 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next");
529 	a = (struct archive_match *)_a;
530 
531 	r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v);
532 	*_p = (const char *)v;
533 	return (r);
534 }
535 
536 int
archive_match_path_unmatched_inclusions_next_w(struct archive * _a,const wchar_t ** _p)537 archive_match_path_unmatched_inclusions_next_w(struct archive *_a,
538     const wchar_t **_p)
539 {
540 	struct archive_match *a;
541 	const void *v;
542 	int r;
543 
544 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
545 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w");
546 	a = (struct archive_match *)_a;
547 
548 	r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v);
549 	*_p = (const wchar_t *)v;
550 	return (r);
551 }
552 
553 /*
554  * Add inclusion/exclusion patterns.
555  */
556 static int
add_pattern_mbs(struct archive_match * a,struct match_list * list,const char * pattern)557 add_pattern_mbs(struct archive_match *a, struct match_list *list,
558     const char *pattern)
559 {
560 	struct match *match;
561 	size_t len;
562 
563 	match = calloc(1, sizeof(*match));
564 	if (match == NULL)
565 		return (error_nomem(a));
566 	/* Both "foo/" and "foo" should match "foo/bar". */
567 	len = strlen(pattern);
568 	if (len && pattern[len - 1] == '/')
569 		--len;
570 	archive_mstring_copy_mbs_len(&(match->pattern), pattern, len);
571 	match_list_add(list, match);
572 	a->setflag |= PATTERN_IS_SET;
573 	return (ARCHIVE_OK);
574 }
575 
576 static int
add_pattern_wcs(struct archive_match * a,struct match_list * list,const wchar_t * pattern)577 add_pattern_wcs(struct archive_match *a, struct match_list *list,
578     const wchar_t *pattern)
579 {
580 	struct match *match;
581 	size_t len;
582 
583 	match = calloc(1, sizeof(*match));
584 	if (match == NULL)
585 		return (error_nomem(a));
586 	/* Both "foo/" and "foo" should match "foo/bar". */
587 	len = wcslen(pattern);
588 	if (len && pattern[len - 1] == L'/')
589 		--len;
590 	archive_mstring_copy_wcs_len(&(match->pattern), pattern, len);
591 	match_list_add(list, match);
592 	a->setflag |= PATTERN_IS_SET;
593 	return (ARCHIVE_OK);
594 }
595 
596 static int
add_pattern_from_file(struct archive_match * a,struct match_list * mlist,int mbs,const void * pathname,int nullSeparator)597 add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
598     int mbs, const void *pathname, int nullSeparator)
599 {
600 	struct archive *ar;
601 	struct archive_entry *ae;
602 	struct archive_string as;
603 	const void *buff;
604 	size_t size;
605 	int64_t offset;
606 	int r;
607 
608 	ar = archive_read_new();
609 	if (ar == NULL) {
610 		archive_set_error(&(a->archive), ENOMEM, "No memory");
611 		return (ARCHIVE_FATAL);
612 	}
613 	r = archive_read_support_format_raw(ar);
614 	if (r == ARCHIVE_OK)
615 		r = archive_read_support_format_empty(ar);
616 	if (r != ARCHIVE_OK) {
617 		archive_copy_error(&(a->archive), ar);
618 		archive_read_free(ar);
619 		return (r);
620 	}
621 	if (mbs)
622 		r = archive_read_open_filename(ar, pathname, 512*20);
623 	else
624 		r = archive_read_open_filename_w(ar, pathname, 512*20);
625 	if (r != ARCHIVE_OK) {
626 		archive_copy_error(&(a->archive), ar);
627 		archive_read_free(ar);
628 		return (r);
629 	}
630 	r = archive_read_next_header(ar, &ae);
631 	if (r != ARCHIVE_OK) {
632 		archive_read_free(ar);
633 		if (r == ARCHIVE_EOF) {
634 			return (ARCHIVE_OK);
635 		} else {
636 			archive_copy_error(&(a->archive), ar);
637 			return (r);
638 		}
639 	}
640 
641 	archive_string_init(&as);
642 
643 	while ((r = archive_read_data_block(ar, &buff, &size, &offset))
644 	    == ARCHIVE_OK) {
645 		const char *b = (const char *)buff;
646 
647 		while (size) {
648 			const char *s = (const char *)b;
649 			size_t length = 0;
650 			int found_separator = 0;
651 
652 			while (length < size) {
653 				if (nullSeparator) {
654 					if (*b == '\0') {
655 						found_separator = 1;
656 						break;
657 					}
658 				} else {
659 					if (*b == 0x0d || *b == 0x0a) {
660 						found_separator = 1;
661 						break;
662 					}
663 				}
664 				b++;
665 				length++;
666 			}
667 			if (!found_separator) {
668 				archive_strncat(&as, s, length);
669 				/* Read next data block. */
670 				break;
671 			}
672 			b++;
673 			size -= length + 1;
674 			archive_strncat(&as, s, length);
675 
676 			/* If the line is not empty, add the pattern. */
677 			if (archive_strlen(&as) > 0) {
678 				/* Add pattern. */
679 				r = add_pattern_mbs(a, mlist, as.s);
680 				if (r != ARCHIVE_OK) {
681 					archive_read_free(ar);
682 					archive_string_free(&as);
683 					return (r);
684 				}
685 				archive_string_empty(&as);
686 			}
687 		}
688 	}
689 
690 	/* If an error occurred, report it immediately. */
691 	if (r < ARCHIVE_OK) {
692 		archive_copy_error(&(a->archive), ar);
693 		archive_read_free(ar);
694 		archive_string_free(&as);
695 		return (r);
696 	}
697 
698 	/* If the line is not empty, add the pattern. */
699 	if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
700 		/* Add pattern. */
701 		r = add_pattern_mbs(a, mlist, as.s);
702 		if (r != ARCHIVE_OK) {
703 			archive_read_free(ar);
704 			archive_string_free(&as);
705 			return (r);
706 		}
707 	}
708 	archive_read_free(ar);
709 	archive_string_free(&as);
710 	return (ARCHIVE_OK);
711 }
712 
713 /*
714  * Test if pathname is excluded by inclusion/exclusion patterns.
715  */
716 static int
path_excluded(struct archive_match * a,int mbs,const void * pathname)717 path_excluded(struct archive_match *a, int mbs, const void *pathname)
718 {
719 	struct match *match;
720 	struct match *matched;
721 	int r;
722 
723 	if (a == NULL)
724 		return (0);
725 
726 	/* Mark off any unmatched inclusions. */
727 	/* In particular, if a filename does appear in the archive and
728 	 * is explicitly included and excluded, then we don't report
729 	 * it as missing even though we don't extract it.
730 	 */
731 	matched = NULL;
732 	for (match = a->inclusions.first; match != NULL;
733 	    match = match->next){
734 		if (!match->matched &&
735 		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
736 			if (r < 0)
737 				return (r);
738 			a->inclusions.unmatched_count--;
739 			match->matched = 1;
740 			matched = match;
741 		}
742 	}
743 
744 	/* Exclusions take priority. */
745 	for (match = a->exclusions.first; match != NULL;
746 	    match = match->next){
747 		r = match_path_exclusion(a, match, mbs, pathname);
748 		if (r)
749 			return (r);
750 	}
751 
752 	/* It's not excluded and we found an inclusion above, so it's
753 	 * included. */
754 	if (matched != NULL)
755 		return (0);
756 
757 
758 	/* We didn't find an unmatched inclusion, check the remaining ones. */
759 	for (match = a->inclusions.first; match != NULL;
760 	    match = match->next){
761 		/* We looked at previously-unmatched inclusions already. */
762 		if (match->matched &&
763 		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
764 			if (r < 0)
765 				return (r);
766 			return (0);
767 		}
768 	}
769 
770 	/* If there were inclusions, default is to exclude. */
771 	if (a->inclusions.first != NULL)
772 	    return (1);
773 
774 	/* No explicit inclusions, default is to match. */
775 	return (0);
776 }
777 
778 /*
779  * This is a little odd, but it matches the default behavior of
780  * gtar.  In particular, 'a*b' will match 'foo/a1111/222b/bar'
781  *
782  */
783 static int
match_path_exclusion(struct archive_match * a,struct match * m,int mbs,const void * pn)784 match_path_exclusion(struct archive_match *a, struct match *m,
785     int mbs, const void *pn)
786 {
787 	int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
788 	int r;
789 
790 	if (mbs) {
791 		const char *p;
792 		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
793 		if (r == 0)
794 			return (archive_pathmatch(p, (const char *)pn, flag));
795 	} else {
796 		const wchar_t *p;
797 		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
798 		if (r == 0)
799 			return (archive_pathmatch_w(p, (const wchar_t *)pn,
800 				flag));
801 	}
802 	if (errno == ENOMEM)
803 		return (error_nomem(a));
804 	return (0);
805 }
806 
807 /*
808  * Again, mimic gtar:  inclusions are always anchored (have to match
809  * the beginning of the path) even though exclusions are not anchored.
810  */
811 static int
match_path_inclusion(struct archive_match * a,struct match * m,int mbs,const void * pn)812 match_path_inclusion(struct archive_match *a, struct match *m,
813     int mbs, const void *pn)
814 {
815 	/* Recursive operation requires only a prefix match. */
816 	int flag = a->recursive_include ?
817 		PATHMATCH_NO_ANCHOR_END :
818 		0;
819 	int r;
820 
821 	if (mbs) {
822 		const char *p;
823 		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
824 		if (r == 0)
825 			return (archive_pathmatch(p, (const char *)pn, flag));
826 	} else {
827 		const wchar_t *p;
828 		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
829 		if (r == 0)
830 			return (archive_pathmatch_w(p, (const wchar_t *)pn,
831 				flag));
832 	}
833 	if (errno == ENOMEM)
834 		return (error_nomem(a));
835 	return (0);
836 }
837 
838 static void
match_list_init(struct match_list * list)839 match_list_init(struct match_list *list)
840 {
841 	list->first = NULL;
842 	list->last = &(list->first);
843 }
844 
845 static void
match_list_free(struct match_list * list)846 match_list_free(struct match_list *list)
847 {
848 	struct match *p, *q;
849 
850 	for (p = list->first; p != NULL; ) {
851 		q = p;
852 		p = p->next;
853 		archive_mstring_clean(&(q->pattern));
854 		free(q);
855 	}
856 }
857 
858 static void
match_list_add(struct match_list * list,struct match * m)859 match_list_add(struct match_list *list, struct match *m)
860 {
861 	*list->last = m;
862 	list->last = &(m->next);
863 	list->unmatched_count++;
864 }
865 
866 static int
match_list_unmatched_inclusions_next(struct archive_match * a,struct match_list * list,int mbs,const void ** vp)867 match_list_unmatched_inclusions_next(struct archive_match *a,
868     struct match_list *list, int mbs, const void **vp)
869 {
870 	struct match *m;
871 
872 	*vp = NULL;
873 	if (list->unmatched_eof) {
874 		list->unmatched_eof = 0;
875 		return (ARCHIVE_EOF);
876 	}
877 	if (list->unmatched_next == NULL) {
878 		if (list->unmatched_count == 0)
879 			return (ARCHIVE_EOF);
880 		list->unmatched_next = list->first;
881 	}
882 
883 	for (m = list->unmatched_next; m != NULL; m = m->next) {
884 		int r;
885 
886 		if (m->matched)
887 			continue;
888 		if (mbs) {
889 			const char *p;
890 			r = archive_mstring_get_mbs(&(a->archive),
891 				&(m->pattern), &p);
892 			if (r < 0 && errno == ENOMEM)
893 				return (error_nomem(a));
894 			if (p == NULL)
895 				p = "";
896 			*vp = p;
897 		} else {
898 			const wchar_t *p;
899 			r = archive_mstring_get_wcs(&(a->archive),
900 				&(m->pattern), &p);
901 			if (r < 0 && errno == ENOMEM)
902 				return (error_nomem(a));
903 			if (p == NULL)
904 				p = L"";
905 			*vp = p;
906 		}
907 		list->unmatched_next = m->next;
908 		if (list->unmatched_next == NULL)
909 			/* To return EOF next time. */
910 			list->unmatched_eof = 1;
911 		return (ARCHIVE_OK);
912 	}
913 	list->unmatched_next = NULL;
914 	return (ARCHIVE_EOF);
915 }
916 
917 /*
918  * Utility functions to manage inclusion timestamps.
919  */
920 int
archive_match_include_time(struct archive * _a,int flag,time_t sec,long nsec)921 archive_match_include_time(struct archive *_a, int flag, time_t sec,
922     long nsec)
923 {
924 	int r;
925 
926 	r = validate_time_flag(_a, flag, "archive_match_include_time");
927 	if (r != ARCHIVE_OK)
928 		return (r);
929 	return set_timefilter((struct archive_match *)_a, flag,
930 			sec, nsec, sec, nsec);
931 }
932 
933 int
archive_match_include_date(struct archive * _a,int flag,const char * datestr)934 archive_match_include_date(struct archive *_a, int flag,
935     const char *datestr)
936 {
937 	int r;
938 
939 	r = validate_time_flag(_a, flag, "archive_match_include_date");
940 	if (r != ARCHIVE_OK)
941 		return (r);
942 	return set_timefilter_date((struct archive_match *)_a, flag, datestr);
943 }
944 
945 int
archive_match_include_date_w(struct archive * _a,int flag,const wchar_t * datestr)946 archive_match_include_date_w(struct archive *_a, int flag,
947     const wchar_t *datestr)
948 {
949 	int r;
950 
951 	r = validate_time_flag(_a, flag, "archive_match_include_date_w");
952 	if (r != ARCHIVE_OK)
953 		return (r);
954 
955 	return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
956 }
957 
958 int
archive_match_include_file_time(struct archive * _a,int flag,const char * pathname)959 archive_match_include_file_time(struct archive *_a, int flag,
960     const char *pathname)
961 {
962 	int r;
963 
964 	r = validate_time_flag(_a, flag, "archive_match_include_file_time");
965 	if (r != ARCHIVE_OK)
966 		return (r);
967 	return set_timefilter_pathname_mbs((struct archive_match *)_a,
968 			flag, pathname);
969 }
970 
971 int
archive_match_include_file_time_w(struct archive * _a,int flag,const wchar_t * pathname)972 archive_match_include_file_time_w(struct archive *_a, int flag,
973     const wchar_t *pathname)
974 {
975 	int r;
976 
977 	r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
978 	if (r != ARCHIVE_OK)
979 		return (r);
980 	return set_timefilter_pathname_wcs((struct archive_match *)_a,
981 			flag, pathname);
982 }
983 
984 int
archive_match_exclude_entry(struct archive * _a,int flag,struct archive_entry * entry)985 archive_match_exclude_entry(struct archive *_a, int flag,
986     struct archive_entry *entry)
987 {
988 	struct archive_match *a;
989 	int r;
990 
991 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
992 	    ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
993 	a = (struct archive_match *)_a;
994 
995 	if (entry == NULL) {
996 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
997 		return (ARCHIVE_FAILED);
998 	}
999 	r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
1000 	if (r != ARCHIVE_OK)
1001 		return (r);
1002 	return (add_entry(a, flag, entry));
1003 }
1004 
1005 /*
1006  * Test function for time stamps.
1007  *
1008  * Returns 1 if archive entry is excluded.
1009  * Returns 0 if archive entry is not excluded.
1010  * Returns <0 if something error happened.
1011  */
1012 int
archive_match_time_excluded(struct archive * _a,struct archive_entry * entry)1013 archive_match_time_excluded(struct archive *_a,
1014     struct archive_entry *entry)
1015 {
1016 	struct archive_match *a;
1017 
1018 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1019 	    ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
1020 
1021 	a = (struct archive_match *)_a;
1022 	if (entry == NULL) {
1023 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1024 		return (ARCHIVE_FAILED);
1025 	}
1026 
1027 	/* If we don't have inclusion time set at all, the entry is always
1028 	 * not excluded. */
1029 	if ((a->setflag & TIME_IS_SET) == 0)
1030 		return (0);
1031 	return (time_excluded(a, entry));
1032 }
1033 
1034 static int
validate_time_flag(struct archive * _a,int flag,const char * _fn)1035 validate_time_flag(struct archive *_a, int flag, const char *_fn)
1036 {
1037 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1038 	    ARCHIVE_STATE_NEW, _fn);
1039 
1040 	/* Check a type of time. */
1041 	if (flag &
1042 	   ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
1043 		archive_set_error(_a, EINVAL, "Invalid time flag");
1044 		return (ARCHIVE_FAILED);
1045 	}
1046 	if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
1047 		archive_set_error(_a, EINVAL, "No time flag");
1048 		return (ARCHIVE_FAILED);
1049 	}
1050 
1051 	/* Check a type of comparison. */
1052 	if (flag &
1053 	   ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1054 			| ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
1055 		archive_set_error(_a, EINVAL, "Invalid comparison flag");
1056 		return (ARCHIVE_FAILED);
1057 	}
1058 	if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1059 	    | ARCHIVE_MATCH_EQUAL)) == 0) {
1060 		archive_set_error(_a, EINVAL, "No comparison flag");
1061 		return (ARCHIVE_FAILED);
1062 	}
1063 
1064 	return (ARCHIVE_OK);
1065 }
1066 
1067 #define JUST_EQUAL(t) (((t) &  (ARCHIVE_MATCH_EQUAL |\
1068 	ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
1069 static int
set_timefilter(struct archive_match * a,int timetype,time_t mtime_sec,long mtime_nsec,time_t ctime_sec,long ctime_nsec)1070 set_timefilter(struct archive_match *a, int timetype,
1071     time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
1072 {
1073 	if (timetype & ARCHIVE_MATCH_MTIME) {
1074 		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1075 			a->newer_mtime_filter = timetype;
1076 			a->newer_mtime_sec = mtime_sec;
1077 			a->newer_mtime_nsec = mtime_nsec;
1078 			a->setflag |= TIME_IS_SET;
1079 		}
1080 		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1081 			a->older_mtime_filter = timetype;
1082 			a->older_mtime_sec = mtime_sec;
1083 			a->older_mtime_nsec = mtime_nsec;
1084 			a->setflag |= TIME_IS_SET;
1085 		}
1086 	}
1087 	if (timetype & ARCHIVE_MATCH_CTIME) {
1088 		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1089 			a->newer_ctime_filter = timetype;
1090 			a->newer_ctime_sec = ctime_sec;
1091 			a->newer_ctime_nsec = ctime_nsec;
1092 			a->setflag |= TIME_IS_SET;
1093 		}
1094 		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1095 			a->older_ctime_filter = timetype;
1096 			a->older_ctime_sec = ctime_sec;
1097 			a->older_ctime_nsec = ctime_nsec;
1098 			a->setflag |= TIME_IS_SET;
1099 		}
1100 	}
1101 	return (ARCHIVE_OK);
1102 }
1103 
1104 static int
set_timefilter_date(struct archive_match * a,int timetype,const char * datestr)1105 set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
1106 {
1107 	time_t t;
1108 
1109 	if (datestr == NULL || *datestr == '\0') {
1110 		archive_set_error(&(a->archive), EINVAL, "date is empty");
1111 		return (ARCHIVE_FAILED);
1112 	}
1113 	t = get_date(a->now, datestr);
1114 	if (t == (time_t)-1) {
1115 		archive_set_error(&(a->archive), EINVAL, "invalid date string");
1116 		return (ARCHIVE_FAILED);
1117 	}
1118 	return set_timefilter(a, timetype, t, 0, t, 0);
1119 }
1120 
1121 static int
set_timefilter_date_w(struct archive_match * a,int timetype,const wchar_t * datestr)1122 set_timefilter_date_w(struct archive_match *a, int timetype,
1123     const wchar_t *datestr)
1124 {
1125 	struct archive_string as;
1126 	time_t t;
1127 
1128 	if (datestr == NULL || *datestr == L'\0') {
1129 		archive_set_error(&(a->archive), EINVAL, "date is empty");
1130 		return (ARCHIVE_FAILED);
1131 	}
1132 
1133 	archive_string_init(&as);
1134 	if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
1135 		archive_string_free(&as);
1136 		if (errno == ENOMEM)
1137 			return (error_nomem(a));
1138 		archive_set_error(&(a->archive), -1,
1139 		    "Failed to convert WCS to MBS");
1140 		return (ARCHIVE_FAILED);
1141 	}
1142 	t = get_date(a->now, as.s);
1143 	archive_string_free(&as);
1144 	if (t == (time_t)-1) {
1145 		archive_set_error(&(a->archive), EINVAL, "invalid date string");
1146 		return (ARCHIVE_FAILED);
1147 	}
1148 	return set_timefilter(a, timetype, t, 0, t, 0);
1149 }
1150 
1151 #if defined(_WIN32) && !defined(__CYGWIN__)
1152 static int
set_timefilter_find_data(struct archive_match * a,int timetype,const FILETIME * ftLastWriteTime,const FILETIME * ftCreationTime)1153 set_timefilter_find_data(struct archive_match *a, int timetype,
1154     const FILETIME* ftLastWriteTime, const FILETIME* ftCreationTime)
1155 {
1156 	time_t ctime_sec, mtime_sec;
1157 	uint32_t ctime_ns, mtime_ns;
1158 
1159 	ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
1160 	ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
1161 	return set_timefilter(a, timetype,
1162 			mtime_sec, mtime_ns, ctime_sec, ctime_ns);
1163 }
1164 
1165 static int
set_timefilter_pathname_mbs(struct archive_match * a,int timetype,const char * path)1166 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1167     const char *path)
1168 {
1169 	/* NOTE: stat() on Windows cannot handle nano seconds. */
1170 	HANDLE h;
1171 	WIN32_FIND_DATAA d;
1172 
1173 	if (path == NULL || *path == '\0') {
1174 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1175 		return (ARCHIVE_FAILED);
1176 	}
1177 	h = FindFirstFileA(path, &d);
1178 	if (h == INVALID_HANDLE_VALUE) {
1179 		la_dosmaperr(GetLastError());
1180 		archive_set_error(&(a->archive), errno,
1181 		    "Failed to FindFirstFileA");
1182 		return (ARCHIVE_FAILED);
1183 	}
1184 	FindClose(h);
1185 	return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
1186 }
1187 
1188 static int
set_timefilter_pathname_wcs(struct archive_match * a,int timetype,const wchar_t * path)1189 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1190     const wchar_t *path)
1191 {
1192 	HANDLE h;
1193 	WIN32_FIND_DATAW d;
1194 
1195 	if (path == NULL || *path == L'\0') {
1196 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1197 		return (ARCHIVE_FAILED);
1198 	}
1199 	h = FindFirstFileW(path, &d);
1200 	if (h == INVALID_HANDLE_VALUE) {
1201 		la_dosmaperr(GetLastError());
1202 		archive_set_error(&(a->archive), errno,
1203 		    "Failed to FindFirstFile");
1204 		return (ARCHIVE_FAILED);
1205 	}
1206 	FindClose(h);
1207 	return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
1208 }
1209 
1210 #else /* _WIN32 && !__CYGWIN__ */
1211 
1212 static int
set_timefilter_stat(struct archive_match * a,int timetype,struct stat * st)1213 set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
1214 {
1215 	struct archive_entry *ae;
1216 	time_t ctime_sec, mtime_sec;
1217 	long ctime_ns, mtime_ns;
1218 
1219 	ae = archive_entry_new();
1220 	if (ae == NULL)
1221 		return (error_nomem(a));
1222 	archive_entry_copy_stat(ae, st);
1223 	ctime_sec = archive_entry_ctime(ae);
1224 	ctime_ns = archive_entry_ctime_nsec(ae);
1225 	mtime_sec = archive_entry_mtime(ae);
1226 	mtime_ns = archive_entry_mtime_nsec(ae);
1227 	archive_entry_free(ae);
1228 	return set_timefilter(a, timetype, mtime_sec, mtime_ns,
1229 			ctime_sec, ctime_ns);
1230 }
1231 
1232 static int
set_timefilter_pathname_mbs(struct archive_match * a,int timetype,const char * path)1233 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1234     const char *path)
1235 {
1236 	struct stat st;
1237 
1238 	if (path == NULL || *path == '\0') {
1239 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1240 		return (ARCHIVE_FAILED);
1241 	}
1242 	if (la_stat(path, &st) != 0) {
1243 		archive_set_error(&(a->archive), errno, "Failed to stat()");
1244 		return (ARCHIVE_FAILED);
1245 	}
1246 	return (set_timefilter_stat(a, timetype, &st));
1247 }
1248 
1249 static int
set_timefilter_pathname_wcs(struct archive_match * a,int timetype,const wchar_t * path)1250 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1251     const wchar_t *path)
1252 {
1253 	struct archive_string as;
1254 	int r;
1255 
1256 	if (path == NULL || *path == L'\0') {
1257 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1258 		return (ARCHIVE_FAILED);
1259 	}
1260 
1261 	/* Convert WCS filename to MBS filename. */
1262 	archive_string_init(&as);
1263 	if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
1264 		archive_string_free(&as);
1265 		if (errno == ENOMEM)
1266 			return (error_nomem(a));
1267 		archive_set_error(&(a->archive), -1,
1268 		    "Failed to convert WCS to MBS");
1269 		return (ARCHIVE_FAILED);
1270 	}
1271 
1272 	r = set_timefilter_pathname_mbs(a, timetype, as.s);
1273 	archive_string_free(&as);
1274 
1275 	return (r);
1276 }
1277 #endif /* _WIN32 && !__CYGWIN__ */
1278 
1279 /*
1280  * Call back functions for archive_rb.
1281  */
1282 #if !defined(_WIN32) || defined(__CYGWIN__)
1283 static int
cmp_node_mbs(const struct archive_rb_node * n1,const struct archive_rb_node * n2)1284 cmp_node_mbs(const struct archive_rb_node *n1,
1285     const struct archive_rb_node *n2)
1286 {
1287 	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1288 	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1289 	const char *p1, *p2;
1290 
1291 	archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
1292 	archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
1293 	if (p1 == NULL)
1294 		return (1);
1295 	if (p2 == NULL)
1296 		return (-1);
1297 	return (strcmp(p1, p2));
1298 }
1299 
1300 static int
cmp_key_mbs(const struct archive_rb_node * n,const void * key)1301 cmp_key_mbs(const struct archive_rb_node *n, const void *key)
1302 {
1303 	struct match_file *f = (struct match_file *)(uintptr_t)n;
1304 	const char *p;
1305 
1306 	archive_mstring_get_mbs(NULL, &(f->pathname), &p);
1307 	if (p == NULL)
1308 		return (-1);
1309 	return (strcmp(p, (const char *)key));
1310 }
1311 #else
1312 static int
cmp_node_wcs(const struct archive_rb_node * n1,const struct archive_rb_node * n2)1313 cmp_node_wcs(const struct archive_rb_node *n1,
1314     const struct archive_rb_node *n2)
1315 {
1316 	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1317 	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1318 	const wchar_t *p1, *p2;
1319 
1320 	archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
1321 	archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
1322 	if (p1 == NULL)
1323 		return (1);
1324 	if (p2 == NULL)
1325 		return (-1);
1326 	return (wcscmp(p1, p2));
1327 }
1328 
1329 static int
cmp_key_wcs(const struct archive_rb_node * n,const void * key)1330 cmp_key_wcs(const struct archive_rb_node *n, const void *key)
1331 {
1332 	struct match_file *f = (struct match_file *)(uintptr_t)n;
1333 	const wchar_t *p;
1334 
1335 	archive_mstring_get_wcs(NULL, &(f->pathname), &p);
1336 	if (p == NULL)
1337 		return (-1);
1338 	return (wcscmp(p, (const wchar_t *)key));
1339 }
1340 #endif
1341 
1342 static void
entry_list_init(struct entry_list * list)1343 entry_list_init(struct entry_list *list)
1344 {
1345 	list->first = NULL;
1346 	list->last = &(list->first);
1347 }
1348 
1349 static void
entry_list_free(struct entry_list * list)1350 entry_list_free(struct entry_list *list)
1351 {
1352 	struct match_file *p, *q;
1353 
1354 	for (p = list->first; p != NULL; ) {
1355 		q = p;
1356 		p = p->next;
1357 		archive_mstring_clean(&(q->pathname));
1358 		free(q);
1359 	}
1360 }
1361 
1362 static void
entry_list_add(struct entry_list * list,struct match_file * file)1363 entry_list_add(struct entry_list *list, struct match_file *file)
1364 {
1365 	*list->last = file;
1366 	list->last = &(file->next);
1367 }
1368 
1369 static int
add_entry(struct archive_match * a,int flag,struct archive_entry * entry)1370 add_entry(struct archive_match *a, int flag,
1371     struct archive_entry *entry)
1372 {
1373 	struct match_file *f;
1374 	const void *pathname;
1375 	int r;
1376 
1377 	f = calloc(1, sizeof(*f));
1378 	if (f == NULL)
1379 		return (error_nomem(a));
1380 
1381 #if defined(_WIN32) && !defined(__CYGWIN__)
1382 	pathname = archive_entry_pathname_w(entry);
1383 	if (pathname == NULL) {
1384 		free(f);
1385 		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1386 		return (ARCHIVE_FAILED);
1387 	}
1388 	archive_mstring_copy_wcs(&(f->pathname), pathname);
1389 #else
1390 	pathname = archive_entry_pathname(entry);
1391 	if (pathname == NULL) {
1392 		free(f);
1393 		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1394 		return (ARCHIVE_FAILED);
1395 	}
1396 	archive_mstring_copy_mbs(&(f->pathname), pathname);
1397 #endif
1398 	f->flag = flag;
1399 	f->mtime_sec = archive_entry_mtime(entry);
1400 	f->mtime_nsec = archive_entry_mtime_nsec(entry);
1401 	f->ctime_sec = archive_entry_ctime(entry);
1402 	f->ctime_nsec = archive_entry_ctime_nsec(entry);
1403 	r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
1404 	if (!r) {
1405 		struct match_file *f2;
1406 
1407 		/* Get the duplicated file. */
1408 		f2 = (struct match_file *)__archive_rb_tree_find_node(
1409 			&(a->exclusion_tree), pathname);
1410 
1411 		/*
1412 		 * We always overwrite comparison condition.
1413 		 * If you do not want to overwrite it, you should not
1414 		 * call archive_match_exclude_entry(). We cannot know
1415 		 * what behavior you really expect since overwriting
1416 		 * condition might be different with the flag.
1417 		 */
1418 		if (f2 != NULL) {
1419 			f2->flag = f->flag;
1420 			f2->mtime_sec = f->mtime_sec;
1421 			f2->mtime_nsec = f->mtime_nsec;
1422 			f2->ctime_sec = f->ctime_sec;
1423 			f2->ctime_nsec = f->ctime_nsec;
1424 		}
1425 		/* Release the duplicated file. */
1426 		archive_mstring_clean(&(f->pathname));
1427 		free(f);
1428 		return (ARCHIVE_OK);
1429 	}
1430 	entry_list_add(&(a->exclusion_entry_list), f);
1431 	a->setflag |= TIME_IS_SET;
1432 	return (ARCHIVE_OK);
1433 }
1434 
1435 /*
1436  * Test if entry is excluded by its timestamp.
1437  */
1438 static int
time_excluded(struct archive_match * a,struct archive_entry * entry)1439 time_excluded(struct archive_match *a, struct archive_entry *entry)
1440 {
1441 	struct match_file *f;
1442 	const void *pathname;
1443 	time_t sec;
1444 	long nsec;
1445 
1446 	/*
1447 	 * If this file/dir is excluded by a time comparison, skip it.
1448 	 */
1449 	if (a->newer_ctime_filter) {
1450 		/* If ctime is not set, use mtime instead. */
1451 		if (archive_entry_ctime_is_set(entry))
1452 			sec = archive_entry_ctime(entry);
1453 		else
1454 			sec = archive_entry_mtime(entry);
1455 		if (sec < a->newer_ctime_sec)
1456 			return (1); /* Too old, skip it. */
1457 		if (sec == a->newer_ctime_sec) {
1458 			if (archive_entry_ctime_is_set(entry))
1459 				nsec = archive_entry_ctime_nsec(entry);
1460 			else
1461 				nsec = archive_entry_mtime_nsec(entry);
1462 			if (nsec < a->newer_ctime_nsec)
1463 				return (1); /* Too old, skip it. */
1464 			if (nsec == a->newer_ctime_nsec &&
1465 			    (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
1466 			      == 0)
1467 				return (1); /* Equal, skip it. */
1468 		}
1469 	}
1470 	if (a->older_ctime_filter) {
1471 		/* If ctime is not set, use mtime instead. */
1472 		if (archive_entry_ctime_is_set(entry))
1473 			sec = archive_entry_ctime(entry);
1474 		else
1475 			sec = archive_entry_mtime(entry);
1476 		if (sec > a->older_ctime_sec)
1477 			return (1); /* Too new, skip it. */
1478 		if (sec == a->older_ctime_sec) {
1479 			if (archive_entry_ctime_is_set(entry))
1480 				nsec = archive_entry_ctime_nsec(entry);
1481 			else
1482 				nsec = archive_entry_mtime_nsec(entry);
1483 			if (nsec > a->older_ctime_nsec)
1484 				return (1); /* Too new, skip it. */
1485 			if (nsec == a->older_ctime_nsec &&
1486 			    (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
1487 			      == 0)
1488 				return (1); /* Equal, skip it. */
1489 		}
1490 	}
1491 	if (a->newer_mtime_filter) {
1492 		sec = archive_entry_mtime(entry);
1493 		if (sec < a->newer_mtime_sec)
1494 			return (1); /* Too old, skip it. */
1495 		if (sec == a->newer_mtime_sec) {
1496 			nsec = archive_entry_mtime_nsec(entry);
1497 			if (nsec < a->newer_mtime_nsec)
1498 				return (1); /* Too old, skip it. */
1499 			if (nsec == a->newer_mtime_nsec &&
1500 			    (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
1501 			       == 0)
1502 				return (1); /* Equal, skip it. */
1503 		}
1504 	}
1505 	if (a->older_mtime_filter) {
1506 		sec = archive_entry_mtime(entry);
1507 		if (sec > a->older_mtime_sec)
1508 			return (1); /* Too new, skip it. */
1509 		nsec = archive_entry_mtime_nsec(entry);
1510 		if (sec == a->older_mtime_sec) {
1511 			if (nsec > a->older_mtime_nsec)
1512 				return (1); /* Too new, skip it. */
1513 			if (nsec == a->older_mtime_nsec &&
1514 			    (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
1515 			       == 0)
1516 				return (1); /* Equal, skip it. */
1517 		}
1518 	}
1519 
1520 	/* If there is no exclusion list, include the file. */
1521 	if (a->exclusion_entry_list.first == NULL)
1522 		return (0);
1523 
1524 #if defined(_WIN32) && !defined(__CYGWIN__)
1525 	pathname = archive_entry_pathname_w(entry);
1526 #else
1527 	pathname = archive_entry_pathname(entry);
1528 #endif
1529 	if (pathname == NULL)
1530 		return (0);
1531 
1532 	f = (struct match_file *)__archive_rb_tree_find_node(
1533 		&(a->exclusion_tree), pathname);
1534 	/* If the file wasn't rejected, include it. */
1535 	if (f == NULL)
1536 		return (0);
1537 
1538 	if (f->flag & ARCHIVE_MATCH_CTIME) {
1539 		sec = archive_entry_ctime(entry);
1540 		if (f->ctime_sec > sec) {
1541 			if (f->flag & ARCHIVE_MATCH_OLDER)
1542 				return (1);
1543 		} else if (f->ctime_sec < sec) {
1544 			if (f->flag & ARCHIVE_MATCH_NEWER)
1545 				return (1);
1546 		} else {
1547 			nsec = archive_entry_ctime_nsec(entry);
1548 			if (f->ctime_nsec > nsec) {
1549 				if (f->flag & ARCHIVE_MATCH_OLDER)
1550 					return (1);
1551 			} else if (f->ctime_nsec < nsec) {
1552 				if (f->flag & ARCHIVE_MATCH_NEWER)
1553 					return (1);
1554 			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1555 				return (1);
1556 		}
1557 	}
1558 	if (f->flag & ARCHIVE_MATCH_MTIME) {
1559 		sec = archive_entry_mtime(entry);
1560 		if (f->mtime_sec > sec) {
1561 			if (f->flag & ARCHIVE_MATCH_OLDER)
1562 				return (1);
1563 		} else if (f->mtime_sec < sec) {
1564 			if (f->flag & ARCHIVE_MATCH_NEWER)
1565 				return (1);
1566 		} else {
1567 			nsec = archive_entry_mtime_nsec(entry);
1568 			if (f->mtime_nsec > nsec) {
1569 				if (f->flag & ARCHIVE_MATCH_OLDER)
1570 					return (1);
1571 			} else if (f->mtime_nsec < nsec) {
1572 				if (f->flag & ARCHIVE_MATCH_NEWER)
1573 					return (1);
1574 			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1575 				return (1);
1576 		}
1577 	}
1578 	return (0);
1579 }
1580 
1581 /*
1582  * Utility functions to manage inclusion owners
1583  */
1584 
1585 int
archive_match_include_uid(struct archive * _a,la_int64_t uid)1586 archive_match_include_uid(struct archive *_a, la_int64_t uid)
1587 {
1588 	struct archive_match *a;
1589 
1590 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1591 	    ARCHIVE_STATE_NEW, "archive_match_include_uid");
1592 	a = (struct archive_match *)_a;
1593 	return (add_owner_id(a, &(a->inclusion_uids), uid));
1594 }
1595 
1596 int
archive_match_include_gid(struct archive * _a,la_int64_t gid)1597 archive_match_include_gid(struct archive *_a, la_int64_t gid)
1598 {
1599 	struct archive_match *a;
1600 
1601 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1602 	    ARCHIVE_STATE_NEW, "archive_match_include_gid");
1603 	a = (struct archive_match *)_a;
1604 	return (add_owner_id(a, &(a->inclusion_gids), gid));
1605 }
1606 
1607 int
archive_match_include_uname(struct archive * _a,const char * uname)1608 archive_match_include_uname(struct archive *_a, const char *uname)
1609 {
1610 	struct archive_match *a;
1611 
1612 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1613 	    ARCHIVE_STATE_NEW, "archive_match_include_uname");
1614 	a = (struct archive_match *)_a;
1615 	return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
1616 }
1617 
1618 int
archive_match_include_uname_w(struct archive * _a,const wchar_t * uname)1619 archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
1620 {
1621 	struct archive_match *a;
1622 
1623 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1624 	    ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
1625 	a = (struct archive_match *)_a;
1626 	return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
1627 }
1628 
1629 int
archive_match_include_gname(struct archive * _a,const char * gname)1630 archive_match_include_gname(struct archive *_a, const char *gname)
1631 {
1632 	struct archive_match *a;
1633 
1634 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1635 	    ARCHIVE_STATE_NEW, "archive_match_include_gname");
1636 	a = (struct archive_match *)_a;
1637 	return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
1638 }
1639 
1640 int
archive_match_include_gname_w(struct archive * _a,const wchar_t * gname)1641 archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
1642 {
1643 	struct archive_match *a;
1644 
1645 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1646 	    ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
1647 	a = (struct archive_match *)_a;
1648 	return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
1649 }
1650 
1651 /*
1652  * Test function for owner(uid, gid, uname, gname).
1653  *
1654  * Returns 1 if archive entry is excluded.
1655  * Returns 0 if archive entry is not excluded.
1656  * Returns <0 if something error happened.
1657  */
1658 int
archive_match_owner_excluded(struct archive * _a,struct archive_entry * entry)1659 archive_match_owner_excluded(struct archive *_a,
1660     struct archive_entry *entry)
1661 {
1662 	struct archive_match *a;
1663 
1664 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1665 	    ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
1666 
1667 	a = (struct archive_match *)_a;
1668 	if (entry == NULL) {
1669 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1670 		return (ARCHIVE_FAILED);
1671 	}
1672 
1673 	/* If we don't have inclusion id set at all, the entry is always
1674 	 * not excluded. */
1675 	if ((a->setflag & ID_IS_SET) == 0)
1676 		return (0);
1677 	return (owner_excluded(a, entry));
1678 }
1679 
1680 static int
add_owner_id(struct archive_match * a,struct id_array * ids,int64_t id)1681 add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
1682 {
1683 	size_t i;
1684 
1685 	if (ids->count + 1 >= ids->size) {
1686 		void *p;
1687 
1688 		if (ids->size == 0)
1689 			ids->size = 8;
1690 		else
1691 			ids->size *= 2;
1692 		p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
1693 		if (p == NULL)
1694 			return (error_nomem(a));
1695 		ids->ids = (int64_t *)p;
1696 	}
1697 
1698 	/* Find an insert point. */
1699 	for (i = 0; i < ids->count; i++) {
1700 		if (ids->ids[i] >= id)
1701 			break;
1702 	}
1703 
1704 	/* Add owner id. */
1705 	if (i == ids->count)
1706 		ids->ids[ids->count++] = id;
1707 	else if (ids->ids[i] != id) {
1708 		memmove(&(ids->ids[i+1]), &(ids->ids[i]),
1709 		    (ids->count - i) * sizeof(ids->ids[0]));
1710 		ids->ids[i] = id;
1711 		ids->count++;
1712 	}
1713 	a->setflag |= ID_IS_SET;
1714 	return (ARCHIVE_OK);
1715 }
1716 
1717 static int
match_owner_id(struct id_array * ids,int64_t id)1718 match_owner_id(struct id_array *ids, int64_t id)
1719 {
1720 	size_t b, m, t;
1721 
1722 	t = 0;
1723 	b = ids->count;
1724 	while (t < b) {
1725 		m = (t + b)>>1;
1726 		if (ids->ids[m] == id)
1727 			return (1);
1728 		if (ids->ids[m] < id)
1729 			t = m + 1;
1730 		else
1731 			b = m;
1732 	}
1733 	return (0);
1734 }
1735 
1736 static int
add_owner_name(struct archive_match * a,struct match_list * list,int mbs,const void * name)1737 add_owner_name(struct archive_match *a, struct match_list *list,
1738     int mbs, const void *name)
1739 {
1740 	struct match *match;
1741 
1742 	match = calloc(1, sizeof(*match));
1743 	if (match == NULL)
1744 		return (error_nomem(a));
1745 	if (mbs)
1746 		archive_mstring_copy_mbs(&(match->pattern), name);
1747 	else
1748 		archive_mstring_copy_wcs(&(match->pattern), name);
1749 	match_list_add(list, match);
1750 	a->setflag |= ID_IS_SET;
1751 	return (ARCHIVE_OK);
1752 }
1753 
1754 #if !defined(_WIN32) || defined(__CYGWIN__)
1755 static int
match_owner_name_mbs(struct archive_match * a,struct match_list * list,const char * name)1756 match_owner_name_mbs(struct archive_match *a, struct match_list *list,
1757     const char *name)
1758 {
1759 	struct match *m;
1760 	const char *p;
1761 
1762 	if (name == NULL || *name == '\0')
1763 		return (0);
1764 	for (m = list->first; m; m = m->next) {
1765 		if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
1766 		    < 0 && errno == ENOMEM)
1767 			return (error_nomem(a));
1768 		if (p != NULL && strcmp(p, name) == 0) {
1769 			m->matched = 1;
1770 			return (1);
1771 		}
1772 	}
1773 	return (0);
1774 }
1775 #else
1776 static int
match_owner_name_wcs(struct archive_match * a,struct match_list * list,const wchar_t * name)1777 match_owner_name_wcs(struct archive_match *a, struct match_list *list,
1778     const wchar_t *name)
1779 {
1780 	struct match *m;
1781 	const wchar_t *p;
1782 
1783 	if (name == NULL || *name == L'\0')
1784 		return (0);
1785 	for (m = list->first; m; m = m->next) {
1786 		if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
1787 		    < 0 && errno == ENOMEM)
1788 			return (error_nomem(a));
1789 		if (p != NULL && wcscmp(p, name) == 0) {
1790 			m->matched = 1;
1791 			return (1);
1792 		}
1793 	}
1794 	return (0);
1795 }
1796 #endif
1797 
1798 /*
1799  * Test if entry is excluded by uid, gid, uname or gname.
1800  */
1801 static int
owner_excluded(struct archive_match * a,struct archive_entry * entry)1802 owner_excluded(struct archive_match *a, struct archive_entry *entry)
1803 {
1804 	int r;
1805 
1806 	if (a->inclusion_uids.count) {
1807 		if (!match_owner_id(&(a->inclusion_uids),
1808 		    archive_entry_uid(entry)))
1809 			return (1);
1810 	}
1811 
1812 	if (a->inclusion_gids.count) {
1813 		if (!match_owner_id(&(a->inclusion_gids),
1814 		    archive_entry_gid(entry)))
1815 			return (1);
1816 	}
1817 
1818 	if (a->inclusion_unames.first != NULL) {
1819 #if defined(_WIN32) && !defined(__CYGWIN__)
1820 		r = match_owner_name_wcs(a, &(a->inclusion_unames),
1821 			archive_entry_uname_w(entry));
1822 #else
1823 		r = match_owner_name_mbs(a, &(a->inclusion_unames),
1824 			archive_entry_uname(entry));
1825 #endif
1826 		if (!r)
1827 			return (1);
1828 		else if (r < 0)
1829 			return (r);
1830 	}
1831 
1832 	if (a->inclusion_gnames.first != NULL) {
1833 #if defined(_WIN32) && !defined(__CYGWIN__)
1834 		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
1835 			archive_entry_gname_w(entry));
1836 #else
1837 		r = match_owner_name_mbs(a, &(a->inclusion_gnames),
1838 			archive_entry_gname(entry));
1839 #endif
1840 		if (!r)
1841 			return (1);
1842 		else if (r < 0)
1843 			return (r);
1844 	}
1845 	return (0);
1846 }
1847