Coverage Report

Created: 2026-09-14 06:43

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