Coverage Report

Created: 2023-11-19 07:09

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