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