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