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