Coverage Report

Created: 2024-05-20 06:31

/src/libarchive/libarchive/archive_read_support_format_mtree.c
Line
Count
Source (jump to first uncovered line)
1
/*-
2
 * Copyright (c) 2003-2007 Tim Kientzle
3
 * Copyright (c) 2008 Joerg Sonnenberger
4
 * Copyright (c) 2011-2012 Michihiro NAKAJIMA
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
#include "archive_platform.h"
29
30
#ifdef HAVE_SYS_STAT_H
31
#include <sys/stat.h>
32
#endif
33
#ifdef HAVE_ERRNO_H
34
#include <errno.h>
35
#endif
36
#ifdef HAVE_FCNTL_H
37
#include <fcntl.h>
38
#endif
39
#include <stddef.h>
40
/* #include <stdint.h> */ /* See archive_platform.h */
41
#ifdef HAVE_STDLIB_H
42
#include <stdlib.h>
43
#endif
44
#ifdef HAVE_STRING_H
45
#include <string.h>
46
#endif
47
#ifdef HAVE_CTYPE_H
48
#include <ctype.h>
49
#endif
50
51
#include "archive.h"
52
#include "archive_entry.h"
53
#include "archive_entry_private.h"
54
#include "archive_private.h"
55
#include "archive_rb.h"
56
#include "archive_read_private.h"
57
#include "archive_string.h"
58
#include "archive_pack_dev.h"
59
60
#ifndef O_BINARY
61
0
#define O_BINARY 0
62
#endif
63
#ifndef O_CLOEXEC
64
#define O_CLOEXEC 0
65
#endif
66
67
0
#define MTREE_HAS_DEVICE  0x0001
68
0
#define MTREE_HAS_FFLAGS  0x0002
69
0
#define MTREE_HAS_GID   0x0004
70
0
#define MTREE_HAS_GNAME   0x0008
71
0
#define MTREE_HAS_MTIME   0x0010
72
0
#define MTREE_HAS_NLINK   0x0020
73
0
#define MTREE_HAS_PERM    0x0040
74
0
#define MTREE_HAS_SIZE    0x0080
75
0
#define MTREE_HAS_TYPE    0x0100
76
0
#define MTREE_HAS_UID   0x0200
77
0
#define MTREE_HAS_UNAME   0x0400
78
79
0
#define MTREE_HAS_OPTIONAL  0x0800
80
0
#define MTREE_HAS_NOCHANGE  0x1000 /* FreeBSD specific */
81
82
2.40k
#define MAX_LINE_LEN    (1024 * 1024)
83
84
struct mtree_option {
85
  struct mtree_option *next;
86
  char *value;
87
};
88
89
struct mtree_entry {
90
  struct archive_rb_node rbnode;
91
  struct mtree_entry *next_dup;
92
  struct mtree_entry *next;
93
  struct mtree_option *options;
94
  char *name;
95
  char full;
96
  char used;
97
};
98
99
struct mtree {
100
  struct archive_string  line;
101
  size_t       buffsize;
102
  char      *buff;
103
  int64_t      offset;
104
  int      fd;
105
  int      archive_format;
106
  const char    *archive_format_name;
107
  struct mtree_entry  *entries;
108
  struct mtree_entry  *this_entry;
109
  struct archive_rb_tree   entry_rbtree;
110
  struct archive_string  current_dir;
111
  struct archive_string  contents_name;
112
113
  struct archive_entry_linkresolver *resolver;
114
  struct archive_rb_tree rbtree;
115
116
  int64_t      cur_size;
117
  char checkfs;
118
};
119
120
static int  bid_keycmp(const char *, const char *, ssize_t);
121
static int  cleanup(struct archive_read *);
122
static int  detect_form(struct archive_read *, int *);
123
static int  mtree_bid(struct archive_read *, int);
124
static int  parse_file(struct archive_read *, struct archive_entry *,
125
        struct mtree *, struct mtree_entry *, int *);
126
static void parse_escapes(char *, struct mtree_entry *);
127
static int  parse_line(struct archive_read *, struct archive_entry *,
128
        struct mtree *, struct mtree_entry *, int *);
129
static int  parse_keyword(struct archive_read *, struct mtree *,
130
        struct archive_entry *, struct mtree_option *, int *);
131
static int  read_data(struct archive_read *a,
132
        const void **buff, size_t *size, int64_t *offset);
133
static ssize_t  readline(struct archive_read *, struct mtree *, char **, ssize_t);
134
static int  skip(struct archive_read *a);
135
static int  read_header(struct archive_read *,
136
        struct archive_entry *);
137
static int64_t  mtree_atol(char **, int base);
138
#ifndef HAVE_STRNLEN
139
static size_t mtree_strnlen(const char *, size_t);
140
#endif
141
142
/*
143
 * There's no standard for TIME_T_MAX/TIME_T_MIN.  So we compute them
144
 * here.  TODO: Move this to configure time, but be careful
145
 * about cross-compile environments.
146
 */
147
static int64_t
148
get_time_t_max(void)
149
0
{
150
#if defined(TIME_T_MAX)
151
  return TIME_T_MAX;
152
#else
153
  /* ISO C allows time_t to be a floating-point type,
154
     but POSIX requires an integer type.  The following
155
     should work on any system that follows the POSIX
156
     conventions. */
157
0
  if (((time_t)0) < ((time_t)-1)) {
158
    /* Time_t is unsigned */
159
0
    return (~(time_t)0);
160
0
  } else {
161
    /* Time_t is signed. */
162
    /* Assume it's the same as int64_t or int32_t */
163
0
    if (sizeof(time_t) == sizeof(int64_t)) {
164
0
      return (time_t)INT64_MAX;
165
0
    } else {
166
0
      return (time_t)INT32_MAX;
167
0
    }
168
0
  }
169
0
#endif
170
0
}
171
172
static int64_t
173
get_time_t_min(void)
174
0
{
175
#if defined(TIME_T_MIN)
176
  return TIME_T_MIN;
177
#else
178
0
  if (((time_t)0) < ((time_t)-1)) {
179
    /* Time_t is unsigned */
180
0
    return (time_t)0;
181
0
  } else {
182
    /* Time_t is signed. */
183
0
    if (sizeof(time_t) == sizeof(int64_t)) {
184
0
      return (time_t)INT64_MIN;
185
0
    } else {
186
0
      return (time_t)INT32_MIN;
187
0
    }
188
0
  }
189
0
#endif
190
0
}
191
192
#ifdef HAVE_STRNLEN
193
0
#define mtree_strnlen(a,b) strnlen(a,b)
194
#else
195
static size_t
196
mtree_strnlen(const char *p, size_t maxlen)
197
{
198
  size_t i;
199
200
  for (i = 0; i <= maxlen; i++) {
201
    if (p[i] == 0)
202
      break;
203
  }
204
  if (i > maxlen)
205
    return (-1);/* invalid */
206
  return (i);
207
}
208
#endif
209
210
static int
211
archive_read_format_mtree_options(struct archive_read *a,
212
    const char *key, const char *val)
213
0
{
214
0
  struct mtree *mtree;
215
216
0
  mtree = (struct mtree *)(a->format->data);
217
0
  if (strcmp(key, "checkfs")  == 0) {
218
    /* Allows to read information missing from the mtree from the file system */
219
0
    if (val == NULL || val[0] == 0) {
220
0
      mtree->checkfs = 0;
221
0
    } else {
222
0
      mtree->checkfs = 1;
223
0
    }
224
0
    return (ARCHIVE_OK);
225
0
  }
226
227
  /* Note: The "warn" return is just to inform the options
228
   * supervisor that we didn't handle it.  It will generate
229
   * a suitable error if no one used this option. */
230
0
  return (ARCHIVE_WARN);
231
0
}
232
233
static void
234
free_options(struct mtree_option *head)
235
0
{
236
0
  struct mtree_option *next;
237
238
0
  for (; head != NULL; head = next) {
239
0
    next = head->next;
240
0
    free(head->value);
241
0
    free(head);
242
0
  }
243
0
}
244
245
static int
246
mtree_cmp_node(const struct archive_rb_node *n1,
247
    const struct archive_rb_node *n2)
248
0
{
249
0
  const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
250
0
  const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
251
252
0
  return (strcmp(e1->name, e2->name));
253
0
}
254
255
static int
256
mtree_cmp_key(const struct archive_rb_node *n, const void *key)
257
0
{
258
0
  const struct mtree_entry *e = (const struct mtree_entry *)n;
259
260
0
  return (strcmp(e->name, key));
261
0
}
262
263
int
264
archive_read_support_format_mtree(struct archive *_a)
265
7.50k
{
266
7.50k
  static const struct archive_rb_tree_ops rb_ops = {
267
7.50k
    mtree_cmp_node, mtree_cmp_key,
268
7.50k
  };
269
7.50k
  struct archive_read *a = (struct archive_read *)_a;
270
7.50k
  struct mtree *mtree;
271
7.50k
  int r;
272
273
7.50k
  archive_check_magic(_a, ARCHIVE_READ_MAGIC,
274
7.50k
      ARCHIVE_STATE_NEW, "archive_read_support_format_mtree");
275
276
7.50k
  mtree = (struct mtree *)calloc(1, sizeof(*mtree));
277
7.50k
  if (mtree == NULL) {
278
0
    archive_set_error(&a->archive, ENOMEM,
279
0
        "Can't allocate mtree data");
280
0
    return (ARCHIVE_FATAL);
281
0
  }
282
7.50k
  mtree->checkfs = 0;
283
7.50k
  mtree->fd = -1;
284
285
7.50k
  __archive_rb_tree_init(&mtree->rbtree, &rb_ops);
286
287
7.50k
  r = __archive_read_register_format(a, mtree, "mtree",
288
7.50k
           mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
289
290
7.50k
  if (r != ARCHIVE_OK)
291
0
    free(mtree);
292
7.50k
  return (ARCHIVE_OK);
293
7.50k
}
294
295
static int
296
cleanup(struct archive_read *a)
297
7.50k
{
298
7.50k
  struct mtree *mtree;
299
7.50k
  struct mtree_entry *p, *q;
300
301
7.50k
  mtree = (struct mtree *)(a->format->data);
302
303
7.50k
  p = mtree->entries;
304
7.50k
  while (p != NULL) {
305
0
    q = p->next;
306
0
    free(p->name);
307
0
    free_options(p->options);
308
0
    free(p);
309
0
    p = q;
310
0
  }
311
7.50k
  archive_string_free(&mtree->line);
312
7.50k
  archive_string_free(&mtree->current_dir);
313
7.50k
  archive_string_free(&mtree->contents_name);
314
7.50k
  archive_entry_linkresolver_free(mtree->resolver);
315
316
7.50k
  free(mtree->buff);
317
7.50k
  free(mtree);
318
7.50k
  (a->format->data) = NULL;
319
7.50k
  return (ARCHIVE_OK);
320
7.50k
}
321
322
static ssize_t
323
get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
324
1.73G
{
325
1.73G
  ssize_t len;
326
327
1.73G
  len = 0;
328
3.25G
  while (len < avail) {
329
3.25G
    switch (*b) {
330
2.69k
    case '\0':/* Non-ascii character or control character. */
331
2.69k
      if (nlsize != NULL)
332
2.69k
        *nlsize = 0;
333
2.69k
      return (-1);
334
90.4M
    case '\r':
335
90.4M
      if (avail-len > 1 && b[1] == '\n') {
336
14.3k
        if (nlsize != NULL)
337
14.3k
          *nlsize = 2;
338
14.3k
        return (len+2);
339
14.3k
      }
340
      /* FALL THROUGH */
341
1.73G
    case '\n':
342
1.73G
      if (nlsize != NULL)
343
1.73G
        *nlsize = 1;
344
1.73G
      return (len+1);
345
1.51G
    default:
346
1.51G
      b++;
347
1.51G
      len++;
348
1.51G
      break;
349
3.25G
    }
350
3.25G
  }
351
1.78k
  if (nlsize != NULL)
352
1.78k
    *nlsize = 0;
353
1.78k
  return (avail);
354
1.73G
}
355
356
/*
357
 *  <---------------- ravail --------------------->
358
 *  <-- diff ------> <---  avail ----------------->
359
 *                   <---- len ----------->
360
 * | Previous lines | line being parsed  nl extra |
361
 *                  ^
362
 *                  b
363
 *
364
 */
365
static ssize_t
366
next_line(struct archive_read *a,
367
    const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
368
1.73G
{
369
1.73G
  ssize_t len;
370
1.73G
  int quit;
371
  
372
1.73G
  quit = 0;
373
1.73G
  if (*avail == 0) {
374
666
    *nl = 0;
375
666
    len = 0;
376
666
  } else
377
1.73G
    len = get_line_size(*b, *avail, nl);
378
  /*
379
   * Read bytes more while it does not reach the end of line.
380
   */
381
1.73G
  while (*nl == 0 && len == *avail && !quit) {
382
2.40k
    ssize_t diff = *ravail - *avail;
383
2.40k
    size_t nbytes_req = (*ravail+1023) & ~1023U;
384
2.40k
    ssize_t tested;
385
386
    /*
387
     * Place an arbitrary limit on the line length.
388
     * mtree is almost free-form input and without line length limits,
389
     * it can consume a lot of memory.
390
     */
391
2.40k
    if (len >= MAX_LINE_LEN)
392
27
      return (-1);
393
394
    /* Increase reading bytes if it is not enough to at least
395
     * new two lines. */
396
2.37k
    if (nbytes_req < (size_t)*ravail + 160)
397
1.23k
      nbytes_req <<= 1;
398
399
2.37k
    *b = __archive_read_ahead(a, nbytes_req, avail);
400
2.37k
    if (*b == NULL) {
401
1.29k
      if (*ravail >= *avail)
402
1.16k
        return (0);
403
      /* Reading bytes reaches the end of file. */
404
134
      *b = __archive_read_ahead(a, *avail, avail);
405
134
      quit = 1;
406
134
    }
407
1.21k
    *ravail = *avail;
408
1.21k
    *b += diff;
409
1.21k
    *avail -= diff;
410
1.21k
    tested = len;/* Skip some bytes we already determined. */
411
1.21k
    len = get_line_size(*b + len, *avail - len, nl);
412
1.21k
    if (len >= 0)
413
1.18k
      len += tested;
414
1.21k
  }
415
1.73G
  return (len);
416
1.73G
}
417
418
/*
419
 * Compare characters with an mtree keyword.
420
 * Returns the length of an mtree keyword if matched.
421
 * Returns 0 if not matched.
422
 */
423
static int
424
bid_keycmp(const char *p, const char *key, ssize_t len)
425
44.3k
{
426
44.3k
  int match_len = 0;
427
428
175k
  while (len > 0 && *p && *key) {
429
133k
    if (*p == *key) {
430
131k
      --len;
431
131k
      ++p;
432
131k
      ++key;
433
131k
      ++match_len;
434
131k
      continue;
435
131k
    }
436
1.91k
    return (0);/* Not match */
437
133k
  }
438
42.4k
  if (*key != '\0')
439
0
    return (0);/* Not match */
440
441
  /* A following character should be specified characters */
442
42.4k
  if (p[0] == '=' || p[0] == ' ' || p[0] == '\t' ||
443
42.4k
      p[0] == '\n' || p[0] == '\r' ||
444
42.4k
     (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r')))
445
42.1k
    return (match_len);
446
281
  return (0);/* Not match */
447
42.4k
}
448
449
/*
450
 * Test whether the characters 'p' has is mtree keyword.
451
 * Returns the length of a detected keyword.
452
 * Returns 0 if any keywords were not found.
453
 */
454
static int
455
bid_keyword(const char *p,  ssize_t len)
456
35.3k
{
457
35.3k
  static const char * const keys_c[] = {
458
35.3k
    "content", "contents", "cksum", NULL
459
35.3k
  };
460
35.3k
  static const char * const keys_df[] = {
461
35.3k
    "device", "flags", NULL
462
35.3k
  };
463
35.3k
  static const char * const keys_g[] = {
464
35.3k
    "gid", "gname", NULL
465
35.3k
  };
466
35.3k
  static const char * const keys_il[] = {
467
35.3k
    "ignore", "inode", "link", NULL
468
35.3k
  };
469
35.3k
  static const char * const keys_m[] = {
470
35.3k
    "md5", "md5digest", "mode", NULL
471
35.3k
  };
472
35.3k
  static const char * const keys_no[] = {
473
35.3k
    "nlink", "nochange", "optional", NULL
474
35.3k
  };
475
35.3k
  static const char * const keys_r[] = {
476
35.3k
    "resdevice", "rmd160", "rmd160digest", NULL
477
35.3k
  };
478
35.3k
  static const char * const keys_s[] = {
479
35.3k
    "sha1", "sha1digest",
480
35.3k
    "sha256", "sha256digest",
481
35.3k
    "sha384", "sha384digest",
482
35.3k
    "sha512", "sha512digest",
483
35.3k
    "size", NULL
484
35.3k
  };
485
35.3k
  static const char * const keys_t[] = {
486
35.3k
    "tags", "time", "type", NULL
487
35.3k
  };
488
35.3k
  static const char * const keys_u[] = {
489
35.3k
    "uid", "uname", NULL
490
35.3k
  };
491
35.3k
  const char * const *keys;
492
35.3k
  int i;
493
494
35.3k
  switch (*p) {
495
198
  case 'c': keys = keys_c; break;
496
6
  case 'd': case 'f': keys = keys_df; break;
497
9.73k
  case 'g': keys = keys_g; break;
498
5
  case 'i': case 'l': keys = keys_il; break;
499
9
  case 'm': keys = keys_m; break;
500
3
  case 'n': case 'o': keys = keys_no; break;
501
7
  case 'r': keys = keys_r; break;
502
12
  case 's': keys = keys_s; break;
503
595
  case 't': keys = keys_t; break;
504
24.5k
  case 'u': keys = keys_u; break;
505
313
  default: return (0);/* Unknown key */
506
35.3k
  }
507
508
36.8k
  for (i = 0; keys[i] != NULL; i++) {
509
36.6k
    int l = bid_keycmp(p, keys[i], len);
510
36.6k
    if (l > 0)
511
34.9k
      return (l);
512
36.6k
  }
513
147
  return (0);/* Unknown key */
514
35.0k
}
515
516
/*
517
 * Test whether there is a set of mtree keywords.
518
 * Returns the number of keywords.
519
 * Returns -1 if we got incorrect sequence.
520
 * This function expects a set of "<space characters>keyword=value".
521
 * When "unset" is specified, expects a set of "<space characters>keyword".
522
 */
523
static int
524
bid_keyword_list(const char *p,  ssize_t len, int unset, int last_is_path)
525
15.5k
{
526
15.5k
  int l;
527
15.5k
  int keycnt = 0;
528
529
50.4k
  while (len > 0 && *p) {
530
49.9k
    int blank = 0;
531
532
    /* Test whether there are blank characters in the line. */
533
68.6M
    while (len >0 && (*p == ' ' || *p == '\t')) {
534
68.5M
      ++p;
535
68.5M
      --len;
536
68.5M
      blank = 1;
537
68.5M
    }
538
49.9k
    if (*p == '\n' || *p == '\r')
539
6.11k
      break;
540
43.8k
    if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))
541
1.11k
      break;
542
42.6k
    if (!blank && !last_is_path) /* No blank character. */
543
12
      return (-1);
544
42.6k
    if (last_is_path && len == 0)
545
33
        return (keycnt);
546
547
42.6k
    if (unset) {
548
7.71k
      l = bid_keycmp(p, "all", len);
549
7.71k
      if (l > 0)
550
7.25k
        return (1);
551
7.71k
    }
552
    /* Test whether there is a correct key in the line. */
553
35.3k
    l = bid_keyword(p, len);
554
35.3k
    if (l == 0)
555
460
      return (-1);/* Unknown keyword was found. */
556
34.9k
    p += l;
557
34.9k
    len -= l;
558
34.9k
    keycnt++;
559
560
    /* Skip value */
561
34.9k
    if (*p == '=') {
562
26.4k
      int value = 0;
563
26.4k
      ++p;
564
26.4k
      --len;
565
617k
      while (len > 0 && *p != ' ' && *p != '\t') {
566
590k
        ++p;
567
590k
        --len;
568
590k
        value = 1;
569
590k
      }
570
      /* A keyword should have a its value unless
571
       * "/unset" operation. */ 
572
26.4k
      if (!unset && value == 0)
573
5
        return (-1);
574
26.4k
    }
575
34.9k
  }
576
7.76k
  return (keycnt);
577
15.5k
}
578
579
static int
580
bid_entry(const char *p, ssize_t len, ssize_t nl, int *last_is_path)
581
1.47k
{
582
1.47k
  int f = 0;
583
1.47k
  static const unsigned char safe_char[256] = {
584
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
585
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
586
    /* !"$%&'()*+,-./  EXCLUSION:( )(#) */
587
1.47k
    0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
588
    /* 0123456789:;<>?  EXCLUSION:(=) */
589
1.47k
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
590
    /* @ABCDEFGHIJKLMNO */
591
1.47k
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
592
    /* PQRSTUVWXYZ[\]^_  */
593
1.47k
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
594
    /* `abcdefghijklmno */
595
1.47k
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
596
    /* pqrstuvwxyz{|}~ */
597
1.47k
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
598
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
599
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
600
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
601
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
602
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
603
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
604
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
605
1.47k
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
606
1.47k
  };
607
1.47k
  ssize_t ll;
608
1.47k
  const char *pp = p;
609
1.47k
  const char * const pp_end = pp + len;
610
611
1.47k
  *last_is_path = 0;
612
  /*
613
   * Skip the path-name which is quoted.
614
   */
615
289M
  for (;pp < pp_end; ++pp) {
616
289M
    if (!safe_char[*(const unsigned char *)pp]) {
617
1.47k
      if (*pp != ' ' && *pp != '\t' && *pp != '\r'
618
1.47k
          && *pp != '\n')
619
495
        f = 0;
620
1.47k
      break;
621
1.47k
    }
622
289M
    f = 1;
623
289M
  }
624
1.47k
  ll = pp_end - pp;
625
626
  /* If a path-name was not found at the first, try to check
627
   * a mtree format(a.k.a form D) ``NetBSD's mtree -D'' creates,
628
   * which places the path-name at the last. */
629
1.47k
  if (f == 0) {
630
495
    const char *pb = p + len - nl;
631
495
    int name_len = 0;
632
495
    int slash;
633
634
    /* The form D accepts only a single line for an entry. */
635
495
    if (pb-2 >= p &&
636
495
        pb[-1] == '\\' && (pb[-2] == ' ' || pb[-2] == '\t'))
637
4
      return (-1);
638
491
    if (pb-1 >= p && pb[-1] == '\\')
639
20
      return (-1);
640
641
471
    slash = 0;
642
11.9M
    while (p <= --pb && *pb != ' ' && *pb != '\t') {
643
11.9M
      if (!safe_char[*(const unsigned char *)pb])
644
350
        return (-1);
645
11.9M
      name_len++;
646
      /* The pathname should have a slash in this
647
       * format. */
648
11.9M
      if (*pb == '/')
649
413
        slash = 1;
650
11.9M
    }
651
121
    if (name_len == 0 || slash == 0)
652
51
      return (-1);
653
    /* If '/' is placed at the first in this field, this is not
654
     * a valid filename. */
655
70
    if (pb[1] == '/')
656
2
      return (-1);
657
68
    ll = len - nl - name_len;
658
68
    pp = p;
659
68
    *last_is_path = 1;
660
68
  }
661
662
1.04k
  return (bid_keyword_list(pp, ll, 0, *last_is_path));
663
1.47k
}
664
665
10.5k
#define MAX_BID_ENTRY 3
666
667
static int
668
mtree_bid(struct archive_read *a, int best_bid)
669
5.70k
{
670
5.70k
  const char *signature = "#mtree";
671
5.70k
  const char *p;
672
673
5.70k
  (void)best_bid; /* UNUSED */
674
675
  /* Now let's look at the actual header and see if it matches. */
676
5.70k
  p = __archive_read_ahead(a, strlen(signature), NULL);
677
5.70k
  if (p == NULL)
678
717
    return (-1);
679
680
4.98k
  if (memcmp(p, signature, strlen(signature)) == 0)
681
1
    return (8 * (int)strlen(signature));
682
683
  /*
684
   * There is not a mtree signature. Let's try to detect mtree format.
685
   */
686
4.98k
  return (detect_form(a, NULL));
687
4.98k
}
688
689
static int
690
detect_form(struct archive_read *a, int *is_form_d)
691
4.98k
{
692
4.98k
  const char *p;
693
4.98k
  ssize_t avail, ravail;
694
4.98k
  ssize_t len, nl;
695
4.98k
  int entry_cnt = 0, multiline = 0;
696
4.98k
  int form_D = 0;/* The archive is generated by `NetBSD mtree -D'
697
      * (In this source we call it `form D') . */
698
699
4.98k
  if (is_form_d != NULL)
700
0
    *is_form_d = 0;
701
4.98k
  p = __archive_read_ahead(a, 1, &avail);
702
4.98k
  if (p == NULL)
703
0
    return (-1);
704
4.98k
  ravail = avail;
705
1.73G
  for (;;) {
706
1.73G
    len = next_line(a, &p, &avail, &ravail, &nl);
707
    /* The terminal character of the line should be
708
     * a new line character, '\r\n' or '\n'. */
709
1.73G
    if (len <= 0 || nl == 0)
710
3.93k
      break;
711
1.73G
    if (!multiline) {
712
      /* Leading whitespace is never significant,
713
       * ignore it. */
714
1.77G
      while (len > 0 && (*p == ' ' || *p == '\t')) {
715
41.7M
        ++p;
716
41.7M
        --avail;
717
41.7M
        --len;
718
41.7M
      }
719
      /* Skip comment or empty line. */ 
720
1.73G
      if (p[0] == '#' || p[0] == '\n' || p[0] == '\r') {
721
1.73G
        p += len;
722
1.73G
        avail -= len;
723
1.73G
        continue;
724
1.73G
      }
725
1.73G
    } else {
726
      /* A continuance line; the terminal
727
       * character of previous line was '\' character. */
728
6.28k
      if (bid_keyword_list(p, len, 0, 0) <= 0)
729
25
        break;
730
6.26k
      if (p[len-nl-1] != '\\') {
731
5.34k
        if (multiline == 1 &&
732
5.34k
            ++entry_cnt >= MAX_BID_ENTRY)
733
2
          break;
734
5.34k
        multiline = 0;
735
5.34k
      }
736
6.26k
      p += len;
737
6.26k
      avail -= len;
738
6.26k
      continue;
739
6.26k
    }
740
9.75k
    if (p[0] != '/') {
741
1.47k
      int last_is_path, keywords;
742
743
1.47k
      keywords = bid_entry(p, len, nl, &last_is_path);
744
1.47k
      if (keywords >= 0) {
745
646
        if (form_D == 0) {
746
612
          if (last_is_path)
747
21
            form_D = 1;
748
591
          else if (keywords > 0)
749
            /* This line is not `form D'. */
750
72
            form_D = -1;
751
612
        } else if (form_D == 1) {
752
16
          if (!last_is_path && keywords > 0)
753
            /* This this is not `form D'
754
             * and We cannot accept mixed
755
             * format. */
756
1
            break;
757
16
        }
758
645
        if (!last_is_path && p[len-nl-1] == '\\')
759
          /* This line continues. */
760
75
          multiline = 1;
761
570
        else {
762
          /* We've got plenty of correct lines
763
           * to assume that this file is an mtree
764
           * format. */
765
570
          if (++entry_cnt >= MAX_BID_ENTRY)
766
38
            break;
767
570
        }
768
645
      } else
769
824
        break;
770
8.28k
    } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
771
821
      if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
772
3
        break;
773
      /* This line continues. */
774
818
      if (p[len-nl-1] == '\\')
775
249
        multiline = 2;
776
7.46k
    } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
777
7.37k
      if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
778
65
        break;
779
      /* This line continues. */
780
7.30k
      if (p[len-nl-1] == '\\')
781
5.09k
        multiline = 2;
782
7.30k
    } else
783
94
      break;
784
785
    /* Test next line. */
786
8.73k
    p += len;
787
8.73k
    avail -= len;
788
8.73k
  }
789
4.98k
  if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) {
790
259
    if (is_form_d != NULL) {
791
0
      if (form_D == 1)
792
0
        *is_form_d = 1;
793
0
    }
794
259
    return (32);
795
259
  }
796
797
4.72k
  return (0);
798
4.98k
}
799
800
/*
801
 * The extended mtree format permits multiple lines specifying
802
 * attributes for each file.  For those entries, only the last line
803
 * is actually used.  Practically speaking, that means we have
804
 * to read the entire mtree file into memory up front.
805
 *
806
 * The parsing is done in two steps.  First, it is decided if a line
807
 * changes the global defaults and if it is, processed accordingly.
808
 * Otherwise, the options of the line are merged with the current
809
 * global options.
810
 */
811
static int
812
add_option(struct archive_read *a, struct mtree_option **global,
813
    const char *value, size_t len)
814
0
{
815
0
  struct mtree_option *opt;
816
817
0
  if ((opt = malloc(sizeof(*opt))) == NULL) {
818
0
    archive_set_error(&a->archive, errno, "Can't allocate memory");
819
0
    return (ARCHIVE_FATAL);
820
0
  }
821
0
  if ((opt->value = malloc(len + 1)) == NULL) {
822
0
    free(opt);
823
0
    archive_set_error(&a->archive, errno, "Can't allocate memory");
824
0
    return (ARCHIVE_FATAL);
825
0
  }
826
0
  memcpy(opt->value, value, len);
827
0
  opt->value[len] = '\0';
828
0
  opt->next = *global;
829
0
  *global = opt;
830
0
  return (ARCHIVE_OK);
831
0
}
832
833
static void
834
remove_option(struct mtree_option **global, const char *value, size_t len)
835
0
{
836
0
  struct mtree_option *iter, *last;
837
838
0
  last = NULL;
839
0
  for (iter = *global; iter != NULL; last = iter, iter = iter->next) {
840
0
    if (strncmp(iter->value, value, len) == 0 &&
841
0
        (iter->value[len] == '\0' ||
842
0
         iter->value[len] == '='))
843
0
      break;
844
0
  }
845
0
  if (iter == NULL)
846
0
    return;
847
0
  if (last == NULL)
848
0
    *global = iter->next;
849
0
  else
850
0
    last->next = iter->next;
851
852
0
  free(iter->value);
853
0
  free(iter);
854
0
}
855
856
static int
857
process_global_set(struct archive_read *a,
858
    struct mtree_option **global, const char *line)
859
0
{
860
0
  const char *next, *eq;
861
0
  size_t len;
862
0
  int r;
863
864
0
  line += 4;
865
0
  for (;;) {
866
0
    next = line + strspn(line, " \t\r\n");
867
0
    if (*next == '\0')
868
0
      return (ARCHIVE_OK);
869
0
    line = next;
870
0
    next = line + strcspn(line, " \t\r\n");
871
0
    eq = strchr(line, '=');
872
0
    if (eq > next)
873
0
      len = next - line;
874
0
    else
875
0
      len = eq - line;
876
877
0
    remove_option(global, line, len);
878
0
    r = add_option(a, global, line, next - line);
879
0
    if (r != ARCHIVE_OK)
880
0
      return (r);
881
0
    line = next;
882
0
  }
883
0
}
884
885
static int
886
process_global_unset(struct archive_read *a,
887
    struct mtree_option **global, const char *line)
888
0
{
889
0
  const char *next;
890
0
  size_t len;
891
892
0
  line += 6;
893
0
  if (strchr(line, '=') != NULL) {
894
0
    archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
895
0
        "/unset shall not contain `='");
896
0
    return ARCHIVE_FATAL;
897
0
  }
898
899
0
  for (;;) {
900
0
    next = line + strspn(line, " \t\r\n");
901
0
    if (*next == '\0')
902
0
      return (ARCHIVE_OK);
903
0
    line = next;
904
0
    len = strcspn(line, " \t\r\n");
905
906
0
    if (len == 3 && strncmp(line, "all", 3) == 0) {
907
0
      free_options(*global);
908
0
      *global = NULL;
909
0
    } else {
910
0
      remove_option(global, line, len);
911
0
    }
912
913
0
    line += len;
914
0
  }
915
0
}
916
917
static int
918
process_add_entry(struct archive_read *a, struct mtree *mtree,
919
    struct mtree_option **global, const char *line, ssize_t line_len,
920
    struct mtree_entry **last_entry, int is_form_d)
921
0
{
922
0
  struct mtree_entry *entry;
923
0
  struct mtree_option *iter;
924
0
  const char *next, *eq, *name, *end;
925
0
  size_t name_len, len;
926
0
  int r, i;
927
928
0
  if ((entry = malloc(sizeof(*entry))) == NULL) {
929
0
    archive_set_error(&a->archive, errno, "Can't allocate memory");
930
0
    return (ARCHIVE_FATAL);
931
0
  }
932
0
  entry->next = NULL;
933
0
  entry->options = NULL;
934
0
  entry->name = NULL;
935
0
  entry->used = 0;
936
0
  entry->full = 0;
937
938
  /* Add this entry to list. */
939
0
  if (*last_entry == NULL)
940
0
    mtree->entries = entry;
941
0
  else
942
0
    (*last_entry)->next = entry;
943
0
  *last_entry = entry;
944
945
0
  if (is_form_d) {
946
    /* Filename is last item on line. */
947
    /* Adjust line_len to trim trailing whitespace */
948
0
    while (line_len > 0) {
949
0
      char last_character = line[line_len - 1];
950
0
      if (last_character == '\r'
951
0
          || last_character == '\n'
952
0
          || last_character == '\t'
953
0
          || last_character == ' ') {
954
0
        line_len--;
955
0
      } else {
956
0
        break;
957
0
      }
958
0
    }
959
    /* Name starts after the last whitespace separator */
960
0
    name = line;
961
0
    for (i = 0; i < line_len; i++) {
962
0
      if (line[i] == '\r'
963
0
          || line[i] == '\n'
964
0
          || line[i] == '\t'
965
0
          || line[i] == ' ') {
966
0
        name = line + i + 1;
967
0
      }
968
0
    }
969
0
    name_len = line + line_len - name;
970
0
    end = name;
971
0
  } else {
972
    /* Filename is first item on line */
973
0
    name_len = strcspn(line, " \t\r\n");
974
0
    name = line;
975
0
    line += name_len;
976
0
    end = line + line_len;
977
0
  }
978
  /* name/name_len is the name within the line. */
979
  /* line..end brackets the entire line except the name */
980
981
0
  if ((entry->name = malloc(name_len + 1)) == NULL) {
982
0
    archive_set_error(&a->archive, errno, "Can't allocate memory");
983
0
    return (ARCHIVE_FATAL);
984
0
  }
985
986
0
  memcpy(entry->name, name, name_len);
987
0
  entry->name[name_len] = '\0';
988
0
  parse_escapes(entry->name, entry);
989
990
0
  entry->next_dup = NULL;
991
0
  if (entry->full) {
992
0
    if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
993
0
      struct mtree_entry *alt;
994
0
      alt = (struct mtree_entry *)__archive_rb_tree_find_node(
995
0
          &mtree->rbtree, entry->name);
996
0
      if (alt != NULL) {
997
0
        while (alt->next_dup)
998
0
          alt = alt->next_dup;
999
0
        alt->next_dup = entry;
1000
0
      }
1001
0
    }
1002
0
  }
1003
1004
0
  for (iter = *global; iter != NULL; iter = iter->next) {
1005
0
    r = add_option(a, &entry->options, iter->value,
1006
0
        strlen(iter->value));
1007
0
    if (r != ARCHIVE_OK)
1008
0
      return (r);
1009
0
  }
1010
1011
0
  for (;;) {
1012
0
    next = line + strspn(line, " \t\r\n");
1013
0
    if (*next == '\0')
1014
0
      return (ARCHIVE_OK);
1015
0
    if (next >= end)
1016
0
      return (ARCHIVE_OK);
1017
0
    line = next;
1018
0
    next = line + strcspn(line, " \t\r\n");
1019
0
    eq = strchr(line, '=');
1020
0
    if (eq == NULL || eq > next)
1021
0
      len = next - line;
1022
0
    else
1023
0
      len = eq - line;
1024
1025
0
    remove_option(&entry->options, line, len);
1026
0
    r = add_option(a, &entry->options, line, next - line);
1027
0
    if (r != ARCHIVE_OK)
1028
0
      return (r);
1029
0
    line = next;
1030
0
  }
1031
0
}
1032
1033
static int
1034
read_mtree(struct archive_read *a, struct mtree *mtree)
1035
0
{
1036
0
  ssize_t len;
1037
0
  uintmax_t counter;
1038
0
  char *p, *s;
1039
0
  struct mtree_option *global;
1040
0
  struct mtree_entry *last_entry;
1041
0
  int r, is_form_d;
1042
1043
0
  mtree->archive_format = ARCHIVE_FORMAT_MTREE;
1044
0
  mtree->archive_format_name = "mtree";
1045
1046
0
  global = NULL;
1047
0
  last_entry = NULL;
1048
1049
0
  (void)detect_form(a, &is_form_d);
1050
1051
0
  for (counter = 1; ; ++counter) {
1052
0
    r = ARCHIVE_OK;
1053
0
    len = readline(a, mtree, &p, 65536);
1054
0
    if (len == 0) {
1055
0
      mtree->this_entry = mtree->entries;
1056
0
      free_options(global);
1057
0
      return (ARCHIVE_OK);
1058
0
    }
1059
0
    if (len < 0) {
1060
0
      free_options(global);
1061
0
      return ((int)len);
1062
0
    }
1063
    /* Leading whitespace is never significant, ignore it. */
1064
0
    while (*p == ' ' || *p == '\t') {
1065
0
      ++p;
1066
0
      --len;
1067
0
    }
1068
    /* Skip content lines and blank lines. */
1069
0
    if (*p == '#')
1070
0
      continue;
1071
0
    if (*p == '\r' || *p == '\n' || *p == '\0')
1072
0
      continue;
1073
    /* Non-printable characters are not allowed */
1074
0
    for (s = p;s < p + len - 1; s++) {
1075
0
      if (!isprint((unsigned char)*s) && *s != '\t') {
1076
0
        r = ARCHIVE_FATAL;
1077
0
        break;
1078
0
      }
1079
0
    }
1080
0
    if (r != ARCHIVE_OK)
1081
0
      break;
1082
0
    if (*p != '/') {
1083
0
      r = process_add_entry(a, mtree, &global, p, len,
1084
0
          &last_entry, is_form_d);
1085
0
    } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
1086
0
      if (p[4] != ' ' && p[4] != '\t')
1087
0
        break;
1088
0
      r = process_global_set(a, &global, p);
1089
0
    } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
1090
0
      if (p[6] != ' ' && p[6] != '\t')
1091
0
        break;
1092
0
      r = process_global_unset(a, &global, p);
1093
0
    } else
1094
0
      break;
1095
1096
0
    if (r != ARCHIVE_OK) {
1097
0
      free_options(global);
1098
0
      return r;
1099
0
    }
1100
0
  }
1101
1102
0
  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1103
0
      "Can't parse line %ju", counter);
1104
0
  free_options(global);
1105
0
  return (ARCHIVE_FATAL);
1106
0
}
1107
1108
/*
1109
 * Read in the entire mtree file into memory on the first request.
1110
 * Then use the next unused file to satisfy each header request.
1111
 */
1112
static int
1113
read_header(struct archive_read *a, struct archive_entry *entry)
1114
0
{
1115
0
  struct mtree *mtree;
1116
0
  char *p;
1117
0
  int r, use_next;
1118
1119
0
  mtree = (struct mtree *)(a->format->data);
1120
1121
0
  if (mtree->fd >= 0) {
1122
0
    close(mtree->fd);
1123
0
    mtree->fd = -1;
1124
0
  }
1125
1126
0
  if (mtree->entries == NULL) {
1127
0
    mtree->resolver = archive_entry_linkresolver_new();
1128
0
    if (mtree->resolver == NULL)
1129
0
      return ARCHIVE_FATAL;
1130
0
    archive_entry_linkresolver_set_strategy(mtree->resolver,
1131
0
        ARCHIVE_FORMAT_MTREE);
1132
0
    r = read_mtree(a, mtree);
1133
0
    if (r != ARCHIVE_OK)
1134
0
      return (r);
1135
0
  }
1136
1137
0
  a->archive.archive_format = mtree->archive_format;
1138
0
  a->archive.archive_format_name = mtree->archive_format_name;
1139
1140
0
  for (;;) {
1141
0
    if (mtree->this_entry == NULL)
1142
0
      return (ARCHIVE_EOF);
1143
0
    if (strcmp(mtree->this_entry->name, "..") == 0) {
1144
0
      mtree->this_entry->used = 1;
1145
0
      if (archive_strlen(&mtree->current_dir) > 0) {
1146
        /* Roll back current path. */
1147
0
        p = mtree->current_dir.s
1148
0
            + mtree->current_dir.length - 1;
1149
0
        while (p >= mtree->current_dir.s && *p != '/')
1150
0
          --p;
1151
0
        if (p >= mtree->current_dir.s)
1152
0
          --p;
1153
0
        mtree->current_dir.length
1154
0
            = p - mtree->current_dir.s + 1;
1155
0
      }
1156
0
    }
1157
0
    if (!mtree->this_entry->used) {
1158
0
      use_next = 0;
1159
0
      r = parse_file(a, entry, mtree, mtree->this_entry,
1160
0
        &use_next);
1161
0
      if (use_next == 0)
1162
0
        return (r);
1163
0
    }
1164
0
    mtree->this_entry = mtree->this_entry->next;
1165
0
  }
1166
0
}
1167
1168
/*
1169
 * A single file can have multiple lines contribute specifications.
1170
 * Parse as many lines as necessary, then pull additional information
1171
 * from a backing file on disk as necessary.
1172
 */
1173
static int
1174
parse_file(struct archive_read *a, struct archive_entry *entry,
1175
    struct mtree *mtree, struct mtree_entry *mentry, int *use_next)
1176
0
{
1177
0
  const char *path;
1178
0
  struct stat st_storage, *st;
1179
0
  struct mtree_entry *mp;
1180
0
  struct archive_entry *sparse_entry;
1181
0
  int r = ARCHIVE_OK, r1, parsed_kws;
1182
1183
0
  mentry->used = 1;
1184
1185
  /* Initialize reasonable defaults. */
1186
0
  archive_entry_set_filetype(entry, AE_IFREG);
1187
0
  archive_entry_set_size(entry, 0);
1188
0
  archive_string_empty(&mtree->contents_name);
1189
1190
  /* Parse options from this line. */
1191
0
  parsed_kws = 0;
1192
0
  r = parse_line(a, entry, mtree, mentry, &parsed_kws);
1193
1194
0
  if (mentry->full) {
1195
0
    archive_entry_copy_pathname(entry, mentry->name);
1196
    /*
1197
     * "Full" entries are allowed to have multiple lines
1198
     * and those lines aren't required to be adjacent.  We
1199
     * don't support multiple lines for "relative" entries
1200
     * nor do we make any attempt to merge data from
1201
     * separate "relative" and "full" entries.  (Merging
1202
     * "relative" and "full" entries would require dealing
1203
     * with pathname canonicalization, which is a very
1204
     * tricky subject.)
1205
     */
1206
0
    mp = (struct mtree_entry *)__archive_rb_tree_find_node(
1207
0
        &mtree->rbtree, mentry->name);
1208
0
    for (; mp; mp = mp->next_dup) {
1209
0
      if (mp->full && !mp->used) {
1210
        /* Later lines override earlier ones. */
1211
0
        mp->used = 1;
1212
0
        r1 = parse_line(a, entry, mtree, mp, &parsed_kws);
1213
0
        if (r1 < r)
1214
0
          r = r1;
1215
0
      }
1216
0
    }
1217
0
  } else {
1218
    /*
1219
     * Relative entries require us to construct
1220
     * the full path and possibly update the
1221
     * current directory.
1222
     */
1223
0
    size_t n = archive_strlen(&mtree->current_dir);
1224
0
    if (n > 0)
1225
0
      archive_strcat(&mtree->current_dir, "/");
1226
0
    archive_strcat(&mtree->current_dir, mentry->name);
1227
0
    archive_entry_copy_pathname(entry, mtree->current_dir.s);
1228
0
    if (archive_entry_filetype(entry) != AE_IFDIR)
1229
0
      mtree->current_dir.length = n;
1230
0
  }
1231
1232
0
  if (mtree->checkfs) {
1233
    /*
1234
     * Try to open and stat the file to get the real size
1235
     * and other file info.  It would be nice to avoid
1236
     * this here so that getting a listing of an mtree
1237
     * wouldn't require opening every referenced contents
1238
     * file.  But then we wouldn't know the actual
1239
     * contents size, so I don't see a really viable way
1240
     * around this.  (Also, we may want to someday pull
1241
     * other unspecified info from the contents file on
1242
     * disk.)
1243
     */
1244
0
    mtree->fd = -1;
1245
0
    if (archive_strlen(&mtree->contents_name) > 0)
1246
0
      path = mtree->contents_name.s;
1247
0
    else
1248
0
      path = archive_entry_pathname(entry);
1249
1250
0
    if (archive_entry_filetype(entry) == AE_IFREG ||
1251
0
        archive_entry_filetype(entry) == AE_IFDIR) {
1252
0
      mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
1253
0
      __archive_ensure_cloexec_flag(mtree->fd);
1254
0
      if (mtree->fd == -1 && (
1255
#if defined(_WIN32) && !defined(__CYGWIN__)
1256
        /*
1257
         * On Windows, attempting to open a file with an
1258
         * invalid name result in EINVAL (Error 22)
1259
         */
1260
        (errno != ENOENT && errno != EINVAL)
1261
#else
1262
0
        errno != ENOENT
1263
0
#endif
1264
0
        || archive_strlen(&mtree->contents_name) > 0)) {
1265
0
        archive_set_error(&a->archive, errno,
1266
0
            "Can't open %s", path);
1267
0
        r = ARCHIVE_WARN;
1268
0
      }
1269
0
    }
1270
1271
0
    st = &st_storage;
1272
0
    if (mtree->fd >= 0) {
1273
0
      if (fstat(mtree->fd, st) == -1) {
1274
0
        archive_set_error(&a->archive, errno,
1275
0
            "Could not fstat %s", path);
1276
0
        r = ARCHIVE_WARN;
1277
        /* If we can't stat it, don't keep it open. */
1278
0
        close(mtree->fd);
1279
0
        mtree->fd = -1;
1280
0
        st = NULL;
1281
0
      }
1282
0
    }
1283
0
#ifdef HAVE_LSTAT
1284
0
    else if (lstat(path, st) == -1)
1285
#else
1286
    else if (la_stat(path, st) == -1)
1287
#endif
1288
0
    {
1289
0
      st = NULL;
1290
0
    }
1291
1292
    /*
1293
     * Check for a mismatch between the type in the specification
1294
     * and the type of the contents object on disk.
1295
     */
1296
0
    if (st != NULL) {
1297
0
      if (((st->st_mode & S_IFMT) == S_IFREG &&
1298
0
            archive_entry_filetype(entry) == AE_IFREG)
1299
0
#ifdef S_IFLNK
1300
0
        ||((st->st_mode & S_IFMT) == S_IFLNK &&
1301
0
            archive_entry_filetype(entry) == AE_IFLNK)
1302
0
#endif
1303
0
#ifdef S_IFSOCK
1304
0
        ||((st->st_mode & S_IFSOCK) == S_IFSOCK &&
1305
0
            archive_entry_filetype(entry) == AE_IFSOCK)
1306
0
#endif
1307
0
#ifdef S_IFCHR
1308
0
        ||((st->st_mode & S_IFMT) == S_IFCHR &&
1309
0
            archive_entry_filetype(entry) == AE_IFCHR)
1310
0
#endif
1311
0
#ifdef S_IFBLK
1312
0
        ||((st->st_mode & S_IFMT) == S_IFBLK &&
1313
0
            archive_entry_filetype(entry) == AE_IFBLK)
1314
0
#endif
1315
0
        ||((st->st_mode & S_IFMT) == S_IFDIR &&
1316
0
            archive_entry_filetype(entry) == AE_IFDIR)
1317
0
#ifdef S_IFIFO
1318
0
        ||((st->st_mode & S_IFMT) == S_IFIFO &&
1319
0
            archive_entry_filetype(entry) == AE_IFIFO)
1320
0
#endif
1321
0
      ) {
1322
        /* Types match. */
1323
0
      } else {
1324
        /* Types don't match; bail out gracefully. */
1325
0
        if (mtree->fd >= 0)
1326
0
          close(mtree->fd);
1327
0
        mtree->fd = -1;
1328
0
        if (parsed_kws & MTREE_HAS_OPTIONAL) {
1329
          /* It's not an error for an optional
1330
           * entry to not match disk. */
1331
0
          *use_next = 1;
1332
0
        } else if (r == ARCHIVE_OK) {
1333
0
          archive_set_error(&a->archive,
1334
0
              ARCHIVE_ERRNO_MISC,
1335
0
              "mtree specification has different"
1336
0
              " type for %s",
1337
0
              archive_entry_pathname(entry));
1338
0
          r = ARCHIVE_WARN;
1339
0
        }
1340
0
        return (r);
1341
0
      }
1342
0
    }
1343
1344
    /*
1345
     * If there is a contents file on disk, pick some of the
1346
     * metadata from that file.  For most of these, we only
1347
     * set it from the contents if it wasn't already parsed
1348
     * from the specification.
1349
     */
1350
0
    if (st != NULL) {
1351
0
      if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
1352
0
        (parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
1353
0
        (archive_entry_filetype(entry) == AE_IFCHR ||
1354
0
         archive_entry_filetype(entry) == AE_IFBLK))
1355
0
        archive_entry_set_rdev(entry, st->st_rdev);
1356
0
      if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME))
1357
0
        == 0 ||
1358
0
          (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1359
0
        archive_entry_set_gid(entry, st->st_gid);
1360
0
      if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME))
1361
0
        == 0 ||
1362
0
          (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1363
0
        archive_entry_set_uid(entry, st->st_uid);
1364
0
      if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
1365
0
          (parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
1366
#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
1367
        archive_entry_set_mtime(entry, st->st_mtime,
1368
            st->st_mtimespec.tv_nsec);
1369
#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
1370
        archive_entry_set_mtime(entry, st->st_mtime,
1371
0
            st->st_mtim.tv_nsec);
1372
#elif HAVE_STRUCT_STAT_ST_MTIME_N
1373
        archive_entry_set_mtime(entry, st->st_mtime,
1374
            st->st_mtime_n);
1375
#elif HAVE_STRUCT_STAT_ST_UMTIME
1376
        archive_entry_set_mtime(entry, st->st_mtime,
1377
            st->st_umtime*1000);
1378
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
1379
        archive_entry_set_mtime(entry, st->st_mtime,
1380
            st->st_mtime_usec*1000);
1381
#else
1382
        archive_entry_set_mtime(entry, st->st_mtime, 0);
1383
#endif
1384
0
      }
1385
0
      if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
1386
0
          (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1387
0
        archive_entry_set_nlink(entry, st->st_nlink);
1388
0
      if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
1389
0
          (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1390
0
        archive_entry_set_perm(entry, st->st_mode);
1391
0
      if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
1392
0
          (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1393
0
        archive_entry_set_size(entry, st->st_size);
1394
0
      archive_entry_set_ino(entry, st->st_ino);
1395
0
      archive_entry_set_dev(entry, st->st_dev);
1396
1397
0
      archive_entry_linkify(mtree->resolver, &entry,
1398
0
        &sparse_entry);
1399
0
    } else if (parsed_kws & MTREE_HAS_OPTIONAL) {
1400
      /*
1401
       * Couldn't open the entry, stat it or the on-disk type
1402
       * didn't match.  If this entry is optional, just
1403
       * ignore it and read the next header entry.
1404
       */
1405
0
      *use_next = 1;
1406
0
      return ARCHIVE_OK;
1407
0
    }
1408
0
  }
1409
1410
0
  mtree->cur_size = archive_entry_size(entry);
1411
0
  mtree->offset = 0;
1412
1413
0
  return r;
1414
0
}
1415
1416
/*
1417
 * Each line contains a sequence of keywords.
1418
 */
1419
static int
1420
parse_line(struct archive_read *a, struct archive_entry *entry,
1421
    struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws)
1422
0
{
1423
0
  struct mtree_option *iter;
1424
0
  int r = ARCHIVE_OK, r1;
1425
1426
0
  for (iter = mp->options; iter != NULL; iter = iter->next) {
1427
0
    r1 = parse_keyword(a, mtree, entry, iter, parsed_kws);
1428
0
    if (r1 < r)
1429
0
      r = r1;
1430
0
  }
1431
0
  if (r == ARCHIVE_OK && (*parsed_kws & MTREE_HAS_TYPE) == 0) {
1432
0
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1433
0
        "Missing type keyword in mtree specification");
1434
0
    return (ARCHIVE_WARN);
1435
0
  }
1436
0
  return (r);
1437
0
}
1438
1439
/*
1440
 * Device entries have one of the following forms:
1441
 *  - raw dev_t
1442
 *  - format,major,minor[,subdevice]
1443
 * When parsing succeeded, `pdev' will contain the appropriate dev_t value.
1444
 */
1445
1446
/* strsep() is not in C90, but strcspn() is. */
1447
/* Taken from http://unixpapa.com/incnote/string.html */
1448
static char *
1449
la_strsep(char **sp, const char *sep)
1450
0
{
1451
0
  char *p, *s;
1452
0
  if (sp == NULL || *sp == NULL || **sp == '\0')
1453
0
    return(NULL);
1454
0
  s = *sp;
1455
0
  p = s + strcspn(s, sep);
1456
0
  if (*p != '\0')
1457
0
    *p++ = '\0';
1458
0
  *sp = p;
1459
0
  return(s);
1460
0
}
1461
1462
static int
1463
parse_device(dev_t *pdev, struct archive *a, char *val)
1464
0
{
1465
0
#define MAX_PACK_ARGS 3
1466
0
  unsigned long numbers[MAX_PACK_ARGS];
1467
0
  char *p, *dev;
1468
0
  int argc;
1469
0
  pack_t *pack;
1470
0
  dev_t result;
1471
0
  const char *error = NULL;
1472
1473
0
  memset(pdev, 0, sizeof(*pdev));
1474
0
  if ((dev = strchr(val, ',')) != NULL) {
1475
    /*
1476
     * Device's major/minor are given in a specified format.
1477
     * Decode and pack it accordingly.
1478
     */
1479
0
    *dev++ = '\0';
1480
0
    if ((pack = pack_find(val)) == NULL) {
1481
0
      archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1482
0
          "Unknown format `%s'", val);
1483
0
      return ARCHIVE_WARN;
1484
0
    }
1485
0
    argc = 0;
1486
0
    while ((p = la_strsep(&dev, ",")) != NULL) {
1487
0
      if (*p == '\0') {
1488
0
        archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1489
0
            "Missing number");
1490
0
        return ARCHIVE_WARN;
1491
0
      }
1492
0
      if (argc >= MAX_PACK_ARGS) {
1493
0
        archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1494
0
            "Too many arguments");
1495
0
        return ARCHIVE_WARN;
1496
0
      }
1497
0
      numbers[argc++] = (unsigned long)mtree_atol(&p, 0);
1498
0
    }
1499
0
    if (argc < 2) {
1500
0
      archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1501
0
          "Not enough arguments");
1502
0
      return ARCHIVE_WARN;
1503
0
    }
1504
0
    result = (*pack)(argc, numbers, &error);
1505
0
    if (error != NULL) {
1506
0
      archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1507
0
          "%s", error);
1508
0
      return ARCHIVE_WARN;
1509
0
    }
1510
0
  } else {
1511
    /* file system raw value. */
1512
0
    result = (dev_t)mtree_atol(&val, 0);
1513
0
  }
1514
0
  *pdev = result;
1515
0
  return ARCHIVE_OK;
1516
0
#undef MAX_PACK_ARGS
1517
0
}
1518
1519
static int
1520
parse_hex_nibble(char c)
1521
0
{
1522
0
  if (c >= '0' && c <= '9')
1523
0
    return c - '0';
1524
0
  if (c >= 'a' && c <= 'f')
1525
0
    return 10 + c - 'a';
1526
#if 0
1527
  /* XXX: Is uppercase something we should support? */
1528
  if (c >= 'A' && c <= 'F')
1529
    return 10 + c - 'A';
1530
#endif
1531
1532
0
  return -1;
1533
0
}
1534
1535
static int
1536
parse_digest(struct archive_read *a, struct archive_entry *entry,
1537
    const char *digest, int type)
1538
0
{
1539
0
  unsigned char digest_buf[64];
1540
0
  int high, low;
1541
0
  size_t i, j, len;
1542
1543
0
  switch (type) {
1544
0
  case ARCHIVE_ENTRY_DIGEST_MD5:
1545
0
    len = sizeof(entry->digest.md5);
1546
0
    break;
1547
0
  case ARCHIVE_ENTRY_DIGEST_RMD160:
1548
0
    len = sizeof(entry->digest.rmd160);
1549
0
    break;
1550
0
  case ARCHIVE_ENTRY_DIGEST_SHA1:
1551
0
    len = sizeof(entry->digest.sha1);
1552
0
    break;
1553
0
  case ARCHIVE_ENTRY_DIGEST_SHA256:
1554
0
    len = sizeof(entry->digest.sha256);
1555
0
    break;
1556
0
  case ARCHIVE_ENTRY_DIGEST_SHA384:
1557
0
    len = sizeof(entry->digest.sha384);
1558
0
    break;
1559
0
  case ARCHIVE_ENTRY_DIGEST_SHA512:
1560
0
    len = sizeof(entry->digest.sha512);
1561
0
    break;
1562
0
  default:
1563
0
    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
1564
0
      "Internal error: Unknown digest type");
1565
0
    return ARCHIVE_FATAL;
1566
0
  }
1567
1568
0
  if (len > sizeof(digest_buf)) {
1569
0
    archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
1570
0
      "Internal error: Digest storage too large");
1571
0
    return ARCHIVE_FATAL;
1572
0
  }
1573
1574
0
  len *= 2;
1575
1576
0
  if (mtree_strnlen(digest, len+1) != len) {
1577
0
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1578
0
          "incorrect digest length, ignoring");
1579
0
    return ARCHIVE_WARN;
1580
0
  }
1581
1582
0
  for (i = 0, j = 0; i < len; i += 2, j++) {
1583
0
    high = parse_hex_nibble(digest[i]);
1584
0
    low = parse_hex_nibble(digest[i+1]);
1585
0
    if (high == -1 || low == -1) {
1586
0
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1587
0
            "invalid digest data, ignoring");
1588
0
      return ARCHIVE_WARN;
1589
0
    }
1590
1591
0
    digest_buf[j] = high << 4 | low;
1592
0
  }
1593
1594
0
  return archive_entry_set_digest(entry, type, digest_buf);
1595
0
}
1596
1597
/*
1598
 * Parse a single keyword and its value.
1599
 */
1600
static int
1601
parse_keyword(struct archive_read *a, struct mtree *mtree,
1602
    struct archive_entry *entry, struct mtree_option *opt, int *parsed_kws)
1603
0
{
1604
0
  char *val, *key;
1605
1606
0
  key = opt->value;
1607
1608
0
  if (*key == '\0')
1609
0
    return (ARCHIVE_OK);
1610
1611
0
  if (strcmp(key, "nochange") == 0) {
1612
0
    *parsed_kws |= MTREE_HAS_NOCHANGE;
1613
0
    return (ARCHIVE_OK);
1614
0
  }
1615
0
  if (strcmp(key, "optional") == 0) {
1616
0
    *parsed_kws |= MTREE_HAS_OPTIONAL;
1617
0
    return (ARCHIVE_OK);
1618
0
  }
1619
0
  if (strcmp(key, "ignore") == 0) {
1620
    /*
1621
     * The mtree processing is not recursive, so
1622
     * recursion will only happen for explicitly listed
1623
     * entries.
1624
     */
1625
0
    return (ARCHIVE_OK);
1626
0
  }
1627
1628
0
  val = strchr(key, '=');
1629
0
  if (val == NULL) {
1630
0
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1631
0
        "Malformed attribute \"%s\" (%d)", key, key[0]);
1632
0
    return (ARCHIVE_WARN);
1633
0
  }
1634
1635
0
  *val = '\0';
1636
0
  ++val;
1637
1638
0
  switch (key[0]) {
1639
0
  case 'c':
1640
0
    if (strcmp(key, "content") == 0
1641
0
        || strcmp(key, "contents") == 0) {
1642
0
      parse_escapes(val, NULL);
1643
0
      archive_strcpy(&mtree->contents_name, val);
1644
0
      return (ARCHIVE_OK);
1645
0
    }
1646
0
    if (strcmp(key, "cksum") == 0)
1647
0
      return (ARCHIVE_OK);
1648
0
    break;
1649
0
  case 'd':
1650
0
    if (strcmp(key, "device") == 0) {
1651
      /* stat(2) st_rdev field, e.g. the major/minor IDs
1652
       * of a char/block special file */
1653
0
      int r;
1654
0
      dev_t dev;
1655
1656
0
      *parsed_kws |= MTREE_HAS_DEVICE;
1657
0
      r = parse_device(&dev, &a->archive, val);
1658
0
      if (r == ARCHIVE_OK)
1659
0
        archive_entry_set_rdev(entry, dev);
1660
0
      return r;
1661
0
    }
1662
0
    break;
1663
0
  case 'f':
1664
0
    if (strcmp(key, "flags") == 0) {
1665
0
      *parsed_kws |= MTREE_HAS_FFLAGS;
1666
0
      archive_entry_copy_fflags_text(entry, val);
1667
0
      return (ARCHIVE_OK);
1668
0
    }
1669
0
    break;
1670
0
  case 'g':
1671
0
    if (strcmp(key, "gid") == 0) {
1672
0
      *parsed_kws |= MTREE_HAS_GID;
1673
0
      archive_entry_set_gid(entry, mtree_atol(&val, 10));
1674
0
      return (ARCHIVE_OK);
1675
0
    }
1676
0
    if (strcmp(key, "gname") == 0) {
1677
0
      *parsed_kws |= MTREE_HAS_GNAME;
1678
0
      archive_entry_copy_gname(entry, val);
1679
0
      return (ARCHIVE_OK);
1680
0
    }
1681
0
    break;
1682
0
  case 'i':
1683
0
    if (strcmp(key, "inode") == 0) {
1684
0
      archive_entry_set_ino(entry, mtree_atol(&val, 10));
1685
0
      return (ARCHIVE_OK);
1686
0
    }
1687
0
    break;
1688
0
  case 'l':
1689
0
    if (strcmp(key, "link") == 0) {
1690
0
      parse_escapes(val, NULL);
1691
0
      archive_entry_copy_symlink(entry, val);
1692
0
      return (ARCHIVE_OK);
1693
0
    }
1694
0
    break;
1695
0
  case 'm':
1696
0
    if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) {
1697
0
      return parse_digest(a, entry, val,
1698
0
          ARCHIVE_ENTRY_DIGEST_MD5);
1699
0
    }
1700
0
    if (strcmp(key, "mode") == 0) {
1701
0
      if (val[0] < '0' || val[0] > '7') {
1702
0
        archive_set_error(&a->archive,
1703
0
            ARCHIVE_ERRNO_FILE_FORMAT,
1704
0
            "Symbolic or non-octal mode \"%s\" unsupported", val);
1705
0
        return (ARCHIVE_WARN);
1706
0
      }
1707
0
      *parsed_kws |= MTREE_HAS_PERM;
1708
0
      archive_entry_set_perm(entry, (mode_t)mtree_atol(&val, 8));
1709
0
      return (ARCHIVE_OK);
1710
0
    }
1711
0
    break;
1712
0
  case 'n':
1713
0
    if (strcmp(key, "nlink") == 0) {
1714
0
      *parsed_kws |= MTREE_HAS_NLINK;
1715
0
      archive_entry_set_nlink(entry,
1716
0
        (unsigned int)mtree_atol(&val, 10));
1717
0
      return (ARCHIVE_OK);
1718
0
    }
1719
0
    break;
1720
0
  case 'r':
1721
0
    if (strcmp(key, "resdevice") == 0) {
1722
      /* stat(2) st_dev field, e.g. the device ID where the
1723
       * inode resides */
1724
0
      int r;
1725
0
      dev_t dev;
1726
1727
0
      r = parse_device(&dev, &a->archive, val);
1728
0
      if (r == ARCHIVE_OK)
1729
0
        archive_entry_set_dev(entry, dev);
1730
0
      return r;
1731
0
    }
1732
0
    if (strcmp(key, "rmd160") == 0 ||
1733
0
        strcmp(key, "rmd160digest") == 0) {
1734
0
      return parse_digest(a, entry, val,
1735
0
          ARCHIVE_ENTRY_DIGEST_RMD160);
1736
0
    }
1737
0
    break;
1738
0
  case 's':
1739
0
    if (strcmp(key, "sha1") == 0 ||
1740
0
        strcmp(key, "sha1digest") == 0) {
1741
0
      return parse_digest(a, entry, val,
1742
0
          ARCHIVE_ENTRY_DIGEST_SHA1);
1743
0
    }
1744
0
    if (strcmp(key, "sha256") == 0 ||
1745
0
        strcmp(key, "sha256digest") == 0) {
1746
0
      return parse_digest(a, entry, val,
1747
0
          ARCHIVE_ENTRY_DIGEST_SHA256);
1748
0
    }
1749
0
    if (strcmp(key, "sha384") == 0 ||
1750
0
        strcmp(key, "sha384digest") == 0) {
1751
0
      return parse_digest(a, entry, val,
1752
0
          ARCHIVE_ENTRY_DIGEST_SHA384);
1753
0
    }
1754
0
    if (strcmp(key, "sha512") == 0 ||
1755
0
        strcmp(key, "sha512digest") == 0) {
1756
0
      return parse_digest(a, entry, val,
1757
0
          ARCHIVE_ENTRY_DIGEST_SHA512);
1758
0
    }
1759
0
    if (strcmp(key, "size") == 0) {
1760
0
      archive_entry_set_size(entry, mtree_atol(&val, 10));
1761
0
      return (ARCHIVE_OK);
1762
0
    }
1763
0
    break;
1764
0
  case 't':
1765
0
    if (strcmp(key, "tags") == 0) {
1766
      /*
1767
       * Comma delimited list of tags.
1768
       * Ignore the tags for now, but the interface
1769
       * should be extended to allow inclusion/exclusion.
1770
       */
1771
0
      return (ARCHIVE_OK);
1772
0
    }
1773
0
    if (strcmp(key, "time") == 0) {
1774
0
      int64_t m;
1775
0
      int64_t my_time_t_max = get_time_t_max();
1776
0
      int64_t my_time_t_min = get_time_t_min();
1777
0
      long ns = 0;
1778
1779
0
      *parsed_kws |= MTREE_HAS_MTIME;
1780
0
      m = mtree_atol(&val, 10);
1781
      /* Replicate an old mtree bug:
1782
       * 123456789.1 represents 123456789
1783
       * seconds and 1 nanosecond. */
1784
0
      if (*val == '.') {
1785
0
        ++val;
1786
0
        ns = (long)mtree_atol(&val, 10);
1787
0
        if (ns < 0)
1788
0
          ns = 0;
1789
0
        else if (ns > 999999999)
1790
0
          ns = 999999999;
1791
0
      }
1792
0
      if (m > my_time_t_max)
1793
0
        m = my_time_t_max;
1794
0
      else if (m < my_time_t_min)
1795
0
        m = my_time_t_min;
1796
0
      archive_entry_set_mtime(entry, (time_t)m, ns);
1797
0
      return (ARCHIVE_OK);
1798
0
    }
1799
0
    if (strcmp(key, "type") == 0) {
1800
0
      switch (val[0]) {
1801
0
      case 'b':
1802
0
        if (strcmp(val, "block") == 0) {
1803
0
          *parsed_kws |= MTREE_HAS_TYPE;
1804
0
          archive_entry_set_filetype(entry,
1805
0
            AE_IFBLK);
1806
0
          return (ARCHIVE_OK);
1807
0
        }
1808
0
        break;
1809
0
      case 'c':
1810
0
        if (strcmp(val, "char") == 0) {
1811
0
          *parsed_kws |= MTREE_HAS_TYPE;
1812
0
          archive_entry_set_filetype(entry,
1813
0
            AE_IFCHR);
1814
0
          return (ARCHIVE_OK);
1815
0
        }
1816
0
        break;
1817
0
      case 'd':
1818
0
        if (strcmp(val, "dir") == 0) {
1819
0
          *parsed_kws |= MTREE_HAS_TYPE;
1820
0
          archive_entry_set_filetype(entry,
1821
0
            AE_IFDIR);
1822
0
          return (ARCHIVE_OK);
1823
0
        }
1824
0
        break;
1825
0
      case 'f':
1826
0
        if (strcmp(val, "fifo") == 0) {
1827
0
          *parsed_kws |= MTREE_HAS_TYPE;
1828
0
          archive_entry_set_filetype(entry,
1829
0
            AE_IFIFO);
1830
0
          return (ARCHIVE_OK);
1831
0
        }
1832
0
        if (strcmp(val, "file") == 0) {
1833
0
          *parsed_kws |= MTREE_HAS_TYPE;
1834
0
          archive_entry_set_filetype(entry,
1835
0
            AE_IFREG);
1836
0
          return (ARCHIVE_OK);
1837
0
        }
1838
0
        break;
1839
0
      case 'l':
1840
0
        if (strcmp(val, "link") == 0) {
1841
0
          *parsed_kws |= MTREE_HAS_TYPE;
1842
0
          archive_entry_set_filetype(entry,
1843
0
            AE_IFLNK);
1844
0
          return (ARCHIVE_OK);
1845
0
        }
1846
0
        break;
1847
0
      default:
1848
0
        break;
1849
0
      }
1850
0
      archive_set_error(&a->archive,
1851
0
          ARCHIVE_ERRNO_FILE_FORMAT,
1852
0
          "Unrecognized file type \"%s\"; "
1853
0
          "assuming \"file\"", val);
1854
0
      archive_entry_set_filetype(entry, AE_IFREG);
1855
0
      return (ARCHIVE_WARN);
1856
0
    }
1857
0
    break;
1858
0
  case 'u':
1859
0
    if (strcmp(key, "uid") == 0) {
1860
0
      *parsed_kws |= MTREE_HAS_UID;
1861
0
      archive_entry_set_uid(entry, mtree_atol(&val, 10));
1862
0
      return (ARCHIVE_OK);
1863
0
    }
1864
0
    if (strcmp(key, "uname") == 0) {
1865
0
      *parsed_kws |= MTREE_HAS_UNAME;
1866
0
      archive_entry_copy_uname(entry, val);
1867
0
      return (ARCHIVE_OK);
1868
0
    }
1869
0
    break;
1870
0
  default:
1871
0
    break;
1872
0
  }
1873
0
  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1874
0
      "Unrecognized key %s=%s", key, val);
1875
0
  return (ARCHIVE_WARN);
1876
0
}
1877
1878
static int
1879
read_data(struct archive_read *a, const void **buff, size_t *size,
1880
    int64_t *offset)
1881
0
{
1882
0
  size_t bytes_to_read;
1883
0
  ssize_t bytes_read;
1884
0
  struct mtree *mtree;
1885
1886
0
  mtree = (struct mtree *)(a->format->data);
1887
0
  if (mtree->fd < 0) {
1888
0
    *buff = NULL;
1889
0
    *offset = 0;
1890
0
    *size = 0;
1891
0
    return (ARCHIVE_EOF);
1892
0
  }
1893
0
  if (mtree->buff == NULL) {
1894
0
    mtree->buffsize = 64 * 1024;
1895
0
    mtree->buff = malloc(mtree->buffsize);
1896
0
    if (mtree->buff == NULL) {
1897
0
      archive_set_error(&a->archive, ENOMEM,
1898
0
          "Can't allocate memory");
1899
0
      return (ARCHIVE_FATAL);
1900
0
    }
1901
0
  }
1902
1903
0
  *buff = mtree->buff;
1904
0
  *offset = mtree->offset;
1905
0
  if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset)
1906
0
    bytes_to_read = (size_t)(mtree->cur_size - mtree->offset);
1907
0
  else
1908
0
    bytes_to_read = mtree->buffsize;
1909
0
  bytes_read = read(mtree->fd, mtree->buff, bytes_to_read);
1910
0
  if (bytes_read < 0) {
1911
0
    archive_set_error(&a->archive, errno, "Can't read");
1912
0
    return (ARCHIVE_WARN);
1913
0
  }
1914
0
  if (bytes_read == 0) {
1915
0
    *size = 0;
1916
0
    return (ARCHIVE_EOF);
1917
0
  }
1918
0
  mtree->offset += bytes_read;
1919
0
  *size = bytes_read;
1920
0
  return (ARCHIVE_OK);
1921
0
}
1922
1923
/* Skip does nothing except possibly close the contents file. */
1924
static int
1925
skip(struct archive_read *a)
1926
0
{
1927
0
  struct mtree *mtree;
1928
1929
0
  mtree = (struct mtree *)(a->format->data);
1930
0
  if (mtree->fd >= 0) {
1931
0
    close(mtree->fd);
1932
0
    mtree->fd = -1;
1933
0
  }
1934
0
  return (ARCHIVE_OK);
1935
0
}
1936
1937
/*
1938
 * Since parsing backslash sequences always makes strings shorter,
1939
 * we can always do this conversion in-place.
1940
 */
1941
static void
1942
parse_escapes(char *src, struct mtree_entry *mentry)
1943
0
{
1944
0
  char *dest = src;
1945
0
  char c;
1946
1947
0
  if (mentry != NULL && strcmp(src, ".") == 0)
1948
0
    mentry->full = 1;
1949
1950
0
  while (*src != '\0') {
1951
0
    c = *src++;
1952
0
    if (c == '/' && mentry != NULL)
1953
0
      mentry->full = 1;
1954
0
    if (c == '\\') {
1955
0
      switch (src[0]) {
1956
0
      case '0':
1957
0
        if (src[1] < '0' || src[1] > '7') {
1958
0
          c = 0;
1959
0
          ++src;
1960
0
          break;
1961
0
        }
1962
        /* FALLTHROUGH */
1963
0
      case '1':
1964
0
      case '2':
1965
0
      case '3':
1966
0
        if (src[1] >= '0' && src[1] <= '7' &&
1967
0
            src[2] >= '0' && src[2] <= '7') {
1968
0
          c = (src[0] - '0') << 6;
1969
0
          c |= (src[1] - '0') << 3;
1970
0
          c |= (src[2] - '0');
1971
0
          src += 3;
1972
0
        }
1973
0
        break;
1974
0
      case 'a':
1975
0
        c = '\a';
1976
0
        ++src;
1977
0
        break;
1978
0
      case 'b':
1979
0
        c = '\b';
1980
0
        ++src;
1981
0
        break;
1982
0
      case 'f':
1983
0
        c = '\f';
1984
0
        ++src;
1985
0
        break;
1986
0
      case 'n':
1987
0
        c = '\n';
1988
0
        ++src;
1989
0
        break;
1990
0
      case 'r':
1991
0
        c = '\r';
1992
0
        ++src;
1993
0
        break;
1994
0
      case 's':
1995
0
        c = ' ';
1996
0
        ++src;
1997
0
        break;
1998
0
      case 't':
1999
0
        c = '\t';
2000
0
        ++src;
2001
0
        break;
2002
0
      case 'v':
2003
0
        c = '\v';
2004
0
        ++src;
2005
0
        break;
2006
0
      case '\\':
2007
0
        c = '\\';
2008
0
        ++src;
2009
0
        break;
2010
0
      }
2011
0
    }
2012
0
    *dest++ = c;
2013
0
  }
2014
0
  *dest = '\0';
2015
0
}
2016
2017
/* Parse a hex digit. */
2018
static int
2019
parsedigit(char c)
2020
0
{
2021
0
  if (c >= '0' && c <= '9')
2022
0
    return c - '0';
2023
0
  else if (c >= 'a' && c <= 'f')
2024
0
    return c - 'a';
2025
0
  else if (c >= 'A' && c <= 'F')
2026
0
    return c - 'A';
2027
0
  else
2028
0
    return -1;
2029
0
}
2030
2031
/*
2032
 * Note that this implementation does not (and should not!) obey
2033
 * locale settings; you cannot simply substitute strtol here, since
2034
 * it does obey locale.
2035
 */
2036
static int64_t
2037
mtree_atol(char **p, int base)
2038
0
{
2039
0
  int64_t l, limit;
2040
0
  int digit, last_digit_limit;
2041
2042
0
  if (base == 0) {
2043
0
    if (**p != '0')
2044
0
      base = 10;
2045
0
    else if ((*p)[1] == 'x' || (*p)[1] == 'X') {
2046
0
      *p += 2;
2047
0
      base = 16;
2048
0
    } else {
2049
0
      base = 8;
2050
0
    }
2051
0
  }
2052
2053
0
  if (**p == '-') {
2054
0
    limit = INT64_MIN / base;
2055
0
    last_digit_limit = -(INT64_MIN % base);
2056
0
    ++(*p);
2057
2058
0
    l = 0;
2059
0
    digit = parsedigit(**p);
2060
0
    while (digit >= 0 && digit < base) {
2061
0
      if (l < limit || (l == limit && digit >= last_digit_limit))
2062
0
        return INT64_MIN;
2063
0
      l = (l * base) - digit;
2064
0
      digit = parsedigit(*++(*p));
2065
0
    }
2066
0
    return l;
2067
0
  } else {
2068
0
    limit = INT64_MAX / base;
2069
0
    last_digit_limit = INT64_MAX % base;
2070
2071
0
    l = 0;
2072
0
    digit = parsedigit(**p);
2073
0
    while (digit >= 0 && digit < base) {
2074
0
      if (l > limit || (l == limit && digit > last_digit_limit))
2075
0
        return INT64_MAX;
2076
0
      l = (l * base) + digit;
2077
0
      digit = parsedigit(*++(*p));
2078
0
    }
2079
0
    return l;
2080
0
  }
2081
0
}
2082
2083
/*
2084
 * Returns length of line (including trailing newline)
2085
 * or negative on error.  'start' argument is updated to
2086
 * point to first character of line.
2087
 */
2088
static ssize_t
2089
readline(struct archive_read *a, struct mtree *mtree, char **start,
2090
    ssize_t limit)
2091
0
{
2092
0
  ssize_t bytes_read;
2093
0
  ssize_t total_size = 0;
2094
0
  ssize_t find_off = 0;
2095
0
  const void *t;
2096
0
  void *nl;
2097
0
  char *u;
2098
2099
  /* Accumulate line in a line buffer. */
2100
0
  for (;;) {
2101
    /* Read some more. */
2102
0
    t = __archive_read_ahead(a, 1, &bytes_read);
2103
0
    if (t == NULL)
2104
0
      return (0);
2105
0
    if (bytes_read < 0)
2106
0
      return (ARCHIVE_FATAL);
2107
0
    nl = memchr(t, '\n', bytes_read);
2108
    /* If we found '\n', trim the read to end exactly there. */
2109
0
    if (nl != NULL) {
2110
0
      bytes_read = ((const char *)nl) - ((const char *)t) + 1;
2111
0
    }
2112
0
    if (total_size + bytes_read + 1 > limit) {
2113
0
      archive_set_error(&a->archive,
2114
0
          ARCHIVE_ERRNO_FILE_FORMAT,
2115
0
          "Line too long");
2116
0
      return (ARCHIVE_FATAL);
2117
0
    }
2118
0
    if (archive_string_ensure(&mtree->line,
2119
0
      total_size + bytes_read + 1) == NULL) {
2120
0
      archive_set_error(&a->archive, ENOMEM,
2121
0
          "Can't allocate working buffer");
2122
0
      return (ARCHIVE_FATAL);
2123
0
    }
2124
    /* Append new bytes to string. */
2125
0
    memcpy(mtree->line.s + total_size, t, bytes_read);
2126
0
    __archive_read_consume(a, bytes_read);
2127
0
    total_size += bytes_read;
2128
0
    mtree->line.s[total_size] = '\0';
2129
2130
0
    for (u = mtree->line.s + find_off; *u; ++u) {
2131
0
      if (u[0] == '\n') {
2132
        /* Ends with unescaped newline. */
2133
0
        *start = mtree->line.s;
2134
0
        return total_size;
2135
0
      } else if (u[0] == '#') {
2136
        /* Ends with comment sequence #...\n */
2137
0
        if (nl == NULL) {
2138
          /* But we've not found the \n yet */
2139
0
          break;
2140
0
        }
2141
0
      } else if (u[0] == '\\') {
2142
0
        if (u[1] == '\n') {
2143
          /* Trim escaped newline. */
2144
0
          total_size -= 2;
2145
0
          mtree->line.s[total_size] = '\0';
2146
0
          break;
2147
0
        } else if (u[1] != '\0') {
2148
          /* Skip the two-char escape sequence */
2149
0
          ++u;
2150
0
        }
2151
0
      }
2152
0
    }
2153
0
    find_off = u - mtree->line.s;
2154
0
  }
2155
0
}