Merge branch 'vendor/OPENSSH'
[dragonfly.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: 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 determined. */
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 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 (p[len-nl-1] != '\\') {
732                                 if (multiline == 1 &&
733                                     ++entry_cnt >= MAX_BID_ENTRY)
734                                         break;
735                                 multiline = 0;
736                         }
737                         p += len;
738                         avail -= len;
739                         continue;
740                 }
741                 if (p[0] != '/') {
742                         int last_is_path, keywords;
743
744                         keywords = bid_entry(p, len, nl, &last_is_path);
745                         if (keywords >= 0) {
746                                 if (form_D == 0) {
747                                         if (last_is_path)
748                                                 form_D = 1;
749                                         else if (keywords > 0)
750                                                 /* This line is not `form D'. */
751                                                 form_D = -1;
752                                 } else if (form_D == 1) {
753                                         if (!last_is_path && keywords > 0)
754                                                 /* This this is not `form D'
755                                                  * and We cannot accept mixed
756                                                  * format. */
757                                                 break;
758                                 }
759                                 if (!last_is_path && p[len-nl-1] == '\\')
760                                         /* This line continues. */
761                                         multiline = 1;
762                                 else {
763                                         /* We've got plenty of correct lines
764                                          * to assume that this file is a mtree
765                                          * format. */
766                                         if (++entry_cnt >= MAX_BID_ENTRY)
767                                                 break;
768                                 }
769                         } else
770                                 break;
771                 } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
772                         if (bid_keyword_list(p+4, len-4, 0, 0) <= 0)
773                                 break;
774                         /* This line continues. */
775                         if (p[len-nl-1] == '\\')
776                                 multiline = 2;
777                 } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
778                         if (bid_keyword_list(p+6, len-6, 1, 0) <= 0)
779                                 break;
780                         /* This line continues. */
781                         if (p[len-nl-1] == '\\')
782                                 multiline = 2;
783                 } else
784                         break;
785
786                 /* Test next line. */
787                 p += len;
788                 avail -= len;
789         }
790         if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0)) {
791                 if (is_form_d != NULL) {
792                         if (form_D == 1)
793                                 *is_form_d = 1;
794                 }
795                 return (32);
796         }
797
798         return (0);
799 }
800
801 /*
802  * The extended mtree format permits multiple lines specifying
803  * attributes for each file.  For those entries, only the last line
804  * is actually used.  Practically speaking, that means we have
805  * to read the entire mtree file into memory up front.
806  *
807  * The parsing is done in two steps.  First, it is decided if a line
808  * changes the global defaults and if it is, processed accordingly.
809  * Otherwise, the options of the line are merged with the current
810  * global options.
811  */
812 static int
813 add_option(struct archive_read *a, struct mtree_option **global,
814     const char *value, size_t len)
815 {
816         struct mtree_option *opt;
817
818         if ((opt = malloc(sizeof(*opt))) == NULL) {
819                 archive_set_error(&a->archive, errno, "Can't allocate memory");
820                 return (ARCHIVE_FATAL);
821         }
822         if ((opt->value = malloc(len + 1)) == NULL) {
823                 free(opt);
824                 archive_set_error(&a->archive, errno, "Can't allocate memory");
825                 return (ARCHIVE_FATAL);
826         }
827         memcpy(opt->value, value, len);
828         opt->value[len] = '\0';
829         opt->next = *global;
830         *global = opt;
831         return (ARCHIVE_OK);
832 }
833
834 static void
835 remove_option(struct mtree_option **global, const char *value, size_t len)
836 {
837         struct mtree_option *iter, *last;
838
839         last = NULL;
840         for (iter = *global; iter != NULL; last = iter, iter = iter->next) {
841                 if (strncmp(iter->value, value, len) == 0 &&
842                     (iter->value[len] == '\0' ||
843                      iter->value[len] == '='))
844                         break;
845         }
846         if (iter == NULL)
847                 return;
848         if (last == NULL)
849                 *global = iter->next;
850         else
851                 last->next = iter->next;
852
853         free(iter->value);
854         free(iter);
855 }
856
857 static int
858 process_global_set(struct archive_read *a,
859     struct mtree_option **global, const char *line)
860 {
861         const char *next, *eq;
862         size_t len;
863         int r;
864
865         line += 4;
866         for (;;) {
867                 next = line + strspn(line, " \t\r\n");
868                 if (*next == '\0')
869                         return (ARCHIVE_OK);
870                 line = next;
871                 next = line + strcspn(line, " \t\r\n");
872                 eq = strchr(line, '=');
873                 if (eq > next)
874                         len = next - line;
875                 else
876                         len = eq - line;
877
878                 remove_option(global, line, len);
879                 r = add_option(a, global, line, next - line);
880                 if (r != ARCHIVE_OK)
881                         return (r);
882                 line = next;
883         }
884 }
885
886 static int
887 process_global_unset(struct archive_read *a,
888     struct mtree_option **global, const char *line)
889 {
890         const char *next;
891         size_t len;
892
893         line += 6;
894         if (strchr(line, '=') != NULL) {
895                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
896                     "/unset shall not contain `='");
897                 return ARCHIVE_FATAL;
898         }
899
900         for (;;) {
901                 next = line + strspn(line, " \t\r\n");
902                 if (*next == '\0')
903                         return (ARCHIVE_OK);
904                 line = next;
905                 len = strcspn(line, " \t\r\n");
906
907                 if (len == 3 && strncmp(line, "all", 3) == 0) {
908                         free_options(*global);
909                         *global = NULL;
910                 } else {
911                         remove_option(global, line, len);
912                 }
913
914                 line += len;
915         }
916 }
917
918 static int
919 process_add_entry(struct archive_read *a, struct mtree *mtree,
920     struct mtree_option **global, const char *line, ssize_t line_len,
921     struct mtree_entry **last_entry, int is_form_d)
922 {
923         struct mtree_entry *entry;
924         struct mtree_option *iter;
925         const char *next, *eq, *name, *end;
926         size_t name_len, len;
927         int r, i;
928
929         if ((entry = malloc(sizeof(*entry))) == NULL) {
930                 archive_set_error(&a->archive, errno, "Can't allocate memory");
931                 return (ARCHIVE_FATAL);
932         }
933         entry->next = NULL;
934         entry->options = NULL;
935         entry->name = NULL;
936         entry->used = 0;
937         entry->full = 0;
938
939         /* Add this entry to list. */
940         if (*last_entry == NULL)
941                 mtree->entries = entry;
942         else
943                 (*last_entry)->next = entry;
944         *last_entry = entry;
945
946         if (is_form_d) {
947                 /* Filename is last item on line. */
948                 /* Adjust line_len to trim trailing whitespace */
949                 while (line_len > 0) {
950                         char last_character = line[line_len - 1];
951                         if (last_character == '\r'
952                             || last_character == '\n'
953                             || last_character == '\t'
954                             || last_character == ' ') {
955                                 line_len--;
956                         } else {
957                                 break;
958                         }
959                 }
960                 /* Name starts after the last whitespace separator */
961                 name = line;
962                 for (i = 0; i < line_len; i++) {
963                         if (line[i] == '\r'
964                             || line[i] == '\n'
965                             || line[i] == '\t'
966                             || line[i] == ' ') {
967                                 name = line + i + 1;
968                         }
969                 }
970                 name_len = line + line_len - name;
971                 end = name;
972         } else {
973                 /* Filename is first item on line */
974                 name_len = strcspn(line, " \t\r\n");
975                 name = line;
976                 line += name_len;
977                 end = line + line_len;
978         }
979         /* name/name_len is the name within the line. */
980         /* line..end brackets the entire line except the name */
981
982         if ((entry->name = malloc(name_len + 1)) == NULL) {
983                 archive_set_error(&a->archive, errno, "Can't allocate memory");
984                 return (ARCHIVE_FATAL);
985         }
986
987         memcpy(entry->name, name, name_len);
988         entry->name[name_len] = '\0';
989         parse_escapes(entry->name, entry);
990
991         entry->next_dup = NULL;
992         if (entry->full) {
993                 if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
994                         struct mtree_entry *alt;
995                         alt = (struct mtree_entry *)__archive_rb_tree_find_node(
996                             &mtree->rbtree, entry->name);
997                         while (alt->next_dup)
998                                 alt = alt->next_dup;
999                         alt->next_dup = entry;
1000                 }
1001         }
1002
1003         for (iter = *global; iter != NULL; iter = iter->next) {
1004                 r = add_option(a, &entry->options, iter->value,
1005                     strlen(iter->value));
1006                 if (r != ARCHIVE_OK)
1007                         return (r);
1008         }
1009
1010         for (;;) {
1011                 next = line + strspn(line, " \t\r\n");
1012                 if (*next == '\0')
1013                         return (ARCHIVE_OK);
1014                 if (next >= end)
1015                         return (ARCHIVE_OK);
1016                 line = next;
1017                 next = line + strcspn(line, " \t\r\n");
1018                 eq = strchr(line, '=');
1019                 if (eq == NULL || eq > next)
1020                         len = next - line;
1021                 else
1022                         len = eq - line;
1023
1024                 remove_option(&entry->options, line, len);
1025                 r = add_option(a, &entry->options, line, next - line);
1026                 if (r != ARCHIVE_OK)
1027                         return (r);
1028                 line = next;
1029         }
1030 }
1031
1032 static int
1033 read_mtree(struct archive_read *a, struct mtree *mtree)
1034 {
1035         ssize_t len;
1036         uintmax_t counter;
1037         char *p, *s;
1038         struct mtree_option *global;
1039         struct mtree_entry *last_entry;
1040         int r, is_form_d;
1041
1042         mtree->archive_format = ARCHIVE_FORMAT_MTREE;
1043         mtree->archive_format_name = "mtree";
1044
1045         global = NULL;
1046         last_entry = NULL;
1047
1048         (void)detect_form(a, &is_form_d);
1049
1050         for (counter = 1; ; ++counter) {
1051                 r = ARCHIVE_OK;
1052                 len = readline(a, mtree, &p, 65536);
1053                 if (len == 0) {
1054                         mtree->this_entry = mtree->entries;
1055                         free_options(global);
1056                         return (ARCHIVE_OK);
1057                 }
1058                 if (len < 0) {
1059                         free_options(global);
1060                         return ((int)len);
1061                 }
1062                 /* Leading whitespace is never significant, ignore it. */
1063                 while (*p == ' ' || *p == '\t') {
1064                         ++p;
1065                         --len;
1066                 }
1067                 /* Skip content lines and blank lines. */
1068                 if (*p == '#')
1069                         continue;
1070                 if (*p == '\r' || *p == '\n' || *p == '\0')
1071                         continue;
1072                 /* Non-printable characters are not allowed */
1073                 for (s = p;s < p + len - 1; s++) {
1074                         if (!isprint((unsigned char)*s)) {
1075                                 r = ARCHIVE_FATAL;
1076                                 break;
1077                         }
1078                 }
1079                 if (r != ARCHIVE_OK)
1080                         break;
1081                 if (*p != '/') {
1082                         r = process_add_entry(a, mtree, &global, p, len,
1083                             &last_entry, is_form_d);
1084                 } else if (len > 4 && strncmp(p, "/set", 4) == 0) {
1085                         if (p[4] != ' ' && p[4] != '\t')
1086                                 break;
1087                         r = process_global_set(a, &global, p);
1088                 } else if (len > 6 && strncmp(p, "/unset", 6) == 0) {
1089                         if (p[6] != ' ' && p[6] != '\t')
1090                                 break;
1091                         r = process_global_unset(a, &global, p);
1092                 } else
1093                         break;
1094
1095                 if (r != ARCHIVE_OK) {
1096                         free_options(global);
1097                         return r;
1098                 }
1099         }
1100
1101         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1102             "Can't parse line %ju", counter);
1103         free_options(global);
1104         return (ARCHIVE_FATAL);
1105 }
1106
1107 /*
1108  * Read in the entire mtree file into memory on the first request.
1109  * Then use the next unused file to satisfy each header request.
1110  */
1111 static int
1112 read_header(struct archive_read *a, struct archive_entry *entry)
1113 {
1114         struct mtree *mtree;
1115         char *p;
1116         int r, use_next;
1117
1118         mtree = (struct mtree *)(a->format->data);
1119
1120         if (mtree->fd >= 0) {
1121                 close(mtree->fd);
1122                 mtree->fd = -1;
1123         }
1124
1125         if (mtree->entries == NULL) {
1126                 mtree->resolver = archive_entry_linkresolver_new();
1127                 if (mtree->resolver == NULL)
1128                         return ARCHIVE_FATAL;
1129                 archive_entry_linkresolver_set_strategy(mtree->resolver,
1130                     ARCHIVE_FORMAT_MTREE);
1131                 r = read_mtree(a, mtree);
1132                 if (r != ARCHIVE_OK)
1133                         return (r);
1134         }
1135
1136         a->archive.archive_format = mtree->archive_format;
1137         a->archive.archive_format_name = mtree->archive_format_name;
1138
1139         for (;;) {
1140                 if (mtree->this_entry == NULL)
1141                         return (ARCHIVE_EOF);
1142                 if (strcmp(mtree->this_entry->name, "..") == 0) {
1143                         mtree->this_entry->used = 1;
1144                         if (archive_strlen(&mtree->current_dir) > 0) {
1145                                 /* Roll back current path. */
1146                                 p = mtree->current_dir.s
1147                                     + mtree->current_dir.length - 1;
1148                                 while (p >= mtree->current_dir.s && *p != '/')
1149                                         --p;
1150                                 if (p >= mtree->current_dir.s)
1151                                         --p;
1152                                 mtree->current_dir.length
1153                                     = p - mtree->current_dir.s + 1;
1154                         }
1155                 }
1156                 if (!mtree->this_entry->used) {
1157                         use_next = 0;
1158                         r = parse_file(a, entry, mtree, mtree->this_entry,
1159                                 &use_next);
1160                         if (use_next == 0)
1161                                 return (r);
1162                 }
1163                 mtree->this_entry = mtree->this_entry->next;
1164         }
1165 }
1166
1167 /*
1168  * A single file can have multiple lines contribute specifications.
1169  * Parse as many lines as necessary, then pull additional information
1170  * from a backing file on disk as necessary.
1171  */
1172 static int
1173 parse_file(struct archive_read *a, struct archive_entry *entry,
1174     struct mtree *mtree, struct mtree_entry *mentry, int *use_next)
1175 {
1176         const char *path;
1177         struct stat st_storage, *st;
1178         struct mtree_entry *mp;
1179         struct archive_entry *sparse_entry;
1180         int r = ARCHIVE_OK, r1, parsed_kws;
1181
1182         mentry->used = 1;
1183
1184         /* Initialize reasonable defaults. */
1185         archive_entry_set_filetype(entry, AE_IFREG);
1186         archive_entry_set_size(entry, 0);
1187         archive_string_empty(&mtree->contents_name);
1188
1189         /* Parse options from this line. */
1190         parsed_kws = 0;
1191         r = parse_line(a, entry, mtree, mentry, &parsed_kws);
1192
1193         if (mentry->full) {
1194                 archive_entry_copy_pathname(entry, mentry->name);
1195                 /*
1196                  * "Full" entries are allowed to have multiple lines
1197                  * and those lines aren't required to be adjacent.  We
1198                  * don't support multiple lines for "relative" entries
1199                  * nor do we make any attempt to merge data from
1200                  * separate "relative" and "full" entries.  (Merging
1201                  * "relative" and "full" entries would require dealing
1202                  * with pathname canonicalization, which is a very
1203                  * tricky subject.)
1204                  */
1205                 mp = (struct mtree_entry *)__archive_rb_tree_find_node(
1206                     &mtree->rbtree, mentry->name);
1207                 for (; mp; mp = mp->next_dup) {
1208                         if (mp->full && !mp->used) {
1209                                 /* Later lines override earlier ones. */
1210                                 mp->used = 1;
1211                                 r1 = parse_line(a, entry, mtree, mp, &parsed_kws);
1212                                 if (r1 < r)
1213                                         r = r1;
1214                         }
1215                 }
1216         } else {
1217                 /*
1218                  * Relative entries require us to construct
1219                  * the full path and possibly update the
1220                  * current directory.
1221                  */
1222                 size_t n = archive_strlen(&mtree->current_dir);
1223                 if (n > 0)
1224                         archive_strcat(&mtree->current_dir, "/");
1225                 archive_strcat(&mtree->current_dir, mentry->name);
1226                 archive_entry_copy_pathname(entry, mtree->current_dir.s);
1227                 if (archive_entry_filetype(entry) != AE_IFDIR)
1228                         mtree->current_dir.length = n;
1229         }
1230
1231         if (mtree->checkfs) {
1232                 /*
1233                  * Try to open and stat the file to get the real size
1234                  * and other file info.  It would be nice to avoid
1235                  * this here so that getting a listing of an mtree
1236                  * wouldn't require opening every referenced contents
1237                  * file.  But then we wouldn't know the actual
1238                  * contents size, so I don't see a really viable way
1239                  * around this.  (Also, we may want to someday pull
1240                  * other unspecified info from the contents file on
1241                  * disk.)
1242                  */
1243                 mtree->fd = -1;
1244                 if (archive_strlen(&mtree->contents_name) > 0)
1245                         path = mtree->contents_name.s;
1246                 else
1247                         path = archive_entry_pathname(entry);
1248
1249                 if (archive_entry_filetype(entry) == AE_IFREG ||
1250                                 archive_entry_filetype(entry) == AE_IFDIR) {
1251                         mtree->fd = open(path, O_RDONLY | O_BINARY | O_CLOEXEC);
1252                         __archive_ensure_cloexec_flag(mtree->fd);
1253                         if (mtree->fd == -1 &&
1254                                 (errno != ENOENT ||
1255                                  archive_strlen(&mtree->contents_name) > 0)) {
1256                                 archive_set_error(&a->archive, errno,
1257                                                 "Can't open %s", path);
1258                                 r = ARCHIVE_WARN;
1259                         }
1260                 }
1261
1262                 st = &st_storage;
1263                 if (mtree->fd >= 0) {
1264                         if (fstat(mtree->fd, st) == -1) {
1265                                 archive_set_error(&a->archive, errno,
1266                                                 "Could not fstat %s", path);
1267                                 r = ARCHIVE_WARN;
1268                                 /* If we can't stat it, don't keep it open. */
1269                                 close(mtree->fd);
1270                                 mtree->fd = -1;
1271                                 st = NULL;
1272                         }
1273                 } else if (lstat(path, st) == -1) {
1274                         st = NULL;
1275                 }
1276
1277                 /*
1278                  * Check for a mismatch between the type in the specification
1279                  * and the type of the contents object on disk.
1280                  */
1281                 if (st != NULL) {
1282                         if (((st->st_mode & S_IFMT) == S_IFREG &&
1283                               archive_entry_filetype(entry) == AE_IFREG)
1284 #ifdef S_IFLNK
1285                           ||((st->st_mode & S_IFMT) == S_IFLNK &&
1286                               archive_entry_filetype(entry) == AE_IFLNK)
1287 #endif
1288 #ifdef S_IFSOCK
1289                           ||((st->st_mode & S_IFSOCK) == S_IFSOCK &&
1290                               archive_entry_filetype(entry) == AE_IFSOCK)
1291 #endif
1292 #ifdef S_IFCHR
1293                           ||((st->st_mode & S_IFMT) == S_IFCHR &&
1294                               archive_entry_filetype(entry) == AE_IFCHR)
1295 #endif
1296 #ifdef S_IFBLK
1297                           ||((st->st_mode & S_IFMT) == S_IFBLK &&
1298                               archive_entry_filetype(entry) == AE_IFBLK)
1299 #endif
1300                           ||((st->st_mode & S_IFMT) == S_IFDIR &&
1301                               archive_entry_filetype(entry) == AE_IFDIR)
1302 #ifdef S_IFIFO
1303                           ||((st->st_mode & S_IFMT) == S_IFIFO &&
1304                               archive_entry_filetype(entry) == AE_IFIFO)
1305 #endif
1306                         ) {
1307                                 /* Types match. */
1308                         } else {
1309                                 /* Types don't match; bail out gracefully. */
1310                                 if (mtree->fd >= 0)
1311                                         close(mtree->fd);
1312                                 mtree->fd = -1;
1313                                 if (parsed_kws & MTREE_HAS_OPTIONAL) {
1314                                         /* It's not an error for an optional
1315                                          * entry to not match disk. */
1316                                         *use_next = 1;
1317                                 } else if (r == ARCHIVE_OK) {
1318                                         archive_set_error(&a->archive,
1319                                             ARCHIVE_ERRNO_MISC,
1320                                             "mtree specification has different"
1321                                             " type for %s",
1322                                             archive_entry_pathname(entry));
1323                                         r = ARCHIVE_WARN;
1324                                 }
1325                                 return (r);
1326                         }
1327                 }
1328
1329                 /*
1330                  * If there is a contents file on disk, pick some of the
1331                  * metadata from that file.  For most of these, we only
1332                  * set it from the contents if it wasn't already parsed
1333                  * from the specification.
1334                  */
1335                 if (st != NULL) {
1336                         if (((parsed_kws & MTREE_HAS_DEVICE) == 0 ||
1337                                 (parsed_kws & MTREE_HAS_NOCHANGE) != 0) &&
1338                                 (archive_entry_filetype(entry) == AE_IFCHR ||
1339                                  archive_entry_filetype(entry) == AE_IFBLK))
1340                                 archive_entry_set_rdev(entry, st->st_rdev);
1341                         if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME))
1342                                 == 0 ||
1343                             (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1344                                 archive_entry_set_gid(entry, st->st_gid);
1345                         if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME))
1346                                 == 0 ||
1347                             (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1348                                 archive_entry_set_uid(entry, st->st_uid);
1349                         if ((parsed_kws & MTREE_HAS_MTIME) == 0 ||
1350                             (parsed_kws & MTREE_HAS_NOCHANGE) != 0) {
1351 #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
1352                                 archive_entry_set_mtime(entry, st->st_mtime,
1353                                                 st->st_mtimespec.tv_nsec);
1354 #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
1355                                 archive_entry_set_mtime(entry, st->st_mtime,
1356                                                 st->st_mtim.tv_nsec);
1357 #elif HAVE_STRUCT_STAT_ST_MTIME_N
1358                                 archive_entry_set_mtime(entry, st->st_mtime,
1359                                                 st->st_mtime_n);
1360 #elif HAVE_STRUCT_STAT_ST_UMTIME
1361                                 archive_entry_set_mtime(entry, st->st_mtime,
1362                                                 st->st_umtime*1000);
1363 #elif HAVE_STRUCT_STAT_ST_MTIME_USEC
1364                                 archive_entry_set_mtime(entry, st->st_mtime,
1365                                                 st->st_mtime_usec*1000);
1366 #else
1367                                 archive_entry_set_mtime(entry, st->st_mtime, 0);
1368 #endif
1369                         }
1370                         if ((parsed_kws & MTREE_HAS_NLINK) == 0 ||
1371                             (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1372                                 archive_entry_set_nlink(entry, st->st_nlink);
1373                         if ((parsed_kws & MTREE_HAS_PERM) == 0 ||
1374                             (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1375                                 archive_entry_set_perm(entry, st->st_mode);
1376                         if ((parsed_kws & MTREE_HAS_SIZE) == 0 ||
1377                             (parsed_kws & MTREE_HAS_NOCHANGE) != 0)
1378                                 archive_entry_set_size(entry, st->st_size);
1379                         archive_entry_set_ino(entry, st->st_ino);
1380                         archive_entry_set_dev(entry, st->st_dev);
1381
1382                         archive_entry_linkify(mtree->resolver, &entry,
1383                                 &sparse_entry);
1384                 } else if (parsed_kws & MTREE_HAS_OPTIONAL) {
1385                         /*
1386                          * Couldn't open the entry, stat it or the on-disk type
1387                          * didn't match.  If this entry is optional, just
1388                          * ignore it and read the next header entry.
1389                          */
1390                         *use_next = 1;
1391                         return ARCHIVE_OK;
1392                 }
1393         }
1394
1395         mtree->cur_size = archive_entry_size(entry);
1396         mtree->offset = 0;
1397
1398         return r;
1399 }
1400
1401 /*
1402  * Each line contains a sequence of keywords.
1403  */
1404 static int
1405 parse_line(struct archive_read *a, struct archive_entry *entry,
1406     struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws)
1407 {
1408         struct mtree_option *iter;
1409         int r = ARCHIVE_OK, r1;
1410
1411         for (iter = mp->options; iter != NULL; iter = iter->next) {
1412                 r1 = parse_keyword(a, mtree, entry, iter, parsed_kws);
1413                 if (r1 < r)
1414                         r = r1;
1415         }
1416         if (r == ARCHIVE_OK && (*parsed_kws & MTREE_HAS_TYPE) == 0) {
1417                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1418                     "Missing type keyword in mtree specification");
1419                 return (ARCHIVE_WARN);
1420         }
1421         return (r);
1422 }
1423
1424 /*
1425  * Device entries have one of the following forms:
1426  *  - raw dev_t
1427  *  - format,major,minor[,subdevice]
1428  * When parsing succeeded, `pdev' will contain the appropriate dev_t value.
1429  */
1430
1431 /* strsep() is not in C90, but strcspn() is. */
1432 /* Taken from http://unixpapa.com/incnote/string.html */
1433 static char *
1434 la_strsep(char **sp, const char *sep)
1435 {
1436         char *p, *s;
1437         if (sp == NULL || *sp == NULL || **sp == '\0')
1438                 return(NULL);
1439         s = *sp;
1440         p = s + strcspn(s, sep);
1441         if (*p != '\0')
1442                 *p++ = '\0';
1443         *sp = p;
1444         return(s);
1445 }
1446
1447 static int
1448 parse_device(dev_t *pdev, struct archive *a, char *val)
1449 {
1450 #define MAX_PACK_ARGS 3
1451         unsigned long numbers[MAX_PACK_ARGS];
1452         char *p, *dev;
1453         int argc;
1454         pack_t *pack;
1455         dev_t result;
1456         const char *error = NULL;
1457
1458         memset(pdev, 0, sizeof(*pdev));
1459         if ((dev = strchr(val, ',')) != NULL) {
1460                 /*
1461                  * Device's major/minor are given in a specified format.
1462                  * Decode and pack it accordingly.
1463                  */
1464                 *dev++ = '\0';
1465                 if ((pack = pack_find(val)) == NULL) {
1466                         archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1467                             "Unknown format `%s'", val);
1468                         return ARCHIVE_WARN;
1469                 }
1470                 argc = 0;
1471                 while ((p = la_strsep(&dev, ",")) != NULL) {
1472                         if (*p == '\0') {
1473                                 archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1474                                     "Missing number");
1475                                 return ARCHIVE_WARN;
1476                         }
1477                         if (argc >= MAX_PACK_ARGS) {
1478                                 archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1479                                     "Too many arguments");
1480                                 return ARCHIVE_WARN;
1481                         }
1482                         numbers[argc++] = (unsigned long)mtree_atol(&p, 0);
1483                 }
1484                 if (argc < 2) {
1485                         archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1486                             "Not enough arguments");
1487                         return ARCHIVE_WARN;
1488                 }
1489                 result = (*pack)(argc, numbers, &error);
1490                 if (error != NULL) {
1491                         archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1492                             "%s", error);
1493                         return ARCHIVE_WARN;
1494                 }
1495         } else {
1496                 /* file system raw value. */
1497                 result = (dev_t)mtree_atol(&val, 0);
1498         }
1499         *pdev = result;
1500         return ARCHIVE_OK;
1501 #undef MAX_PACK_ARGS
1502 }
1503
1504 static int
1505 parse_hex_nibble(char c)
1506 {
1507         if (c >= '0' && c <= '9')
1508                 return c - '0';
1509         if (c >= 'a' && c <= 'f')
1510                 return 10 + c - 'a';
1511 #if 0
1512         /* XXX: Is uppercase something we should support? */
1513         if (c >= 'A' && c <= 'F')
1514                 return 10 + c - 'A';
1515 #endif
1516
1517         return -1;
1518 }
1519
1520 static int
1521 parse_digest(struct archive_read *a, struct archive_entry *entry,
1522     const char *digest, int type)
1523 {
1524         unsigned char digest_buf[64];
1525         int high, low;
1526         size_t i, j, len;
1527
1528         switch (type) {
1529         case ARCHIVE_ENTRY_DIGEST_MD5:
1530                 len = sizeof(entry->digest.md5);
1531                 break;
1532         case ARCHIVE_ENTRY_DIGEST_RMD160:
1533                 len = sizeof(entry->digest.rmd160);
1534                 break;
1535         case ARCHIVE_ENTRY_DIGEST_SHA1:
1536                 len = sizeof(entry->digest.sha1);
1537                 break;
1538         case ARCHIVE_ENTRY_DIGEST_SHA256:
1539                 len = sizeof(entry->digest.sha256);
1540                 break;
1541         case ARCHIVE_ENTRY_DIGEST_SHA384:
1542                 len = sizeof(entry->digest.sha384);
1543                 break;
1544         case ARCHIVE_ENTRY_DIGEST_SHA512:
1545                 len = sizeof(entry->digest.sha512);
1546                 break;
1547         default:
1548                 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
1549                         "Internal error: Unknown digest type");
1550                 return ARCHIVE_FATAL;
1551         }
1552
1553         if (len > sizeof(digest_buf)) {
1554                 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
1555                         "Internal error: Digest storage too large");
1556                 return ARCHIVE_FATAL;
1557         }
1558
1559         len *= 2;
1560
1561         if (mtree_strnlen(digest, len+1) != len) {
1562                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1563                                   "incorrect digest length, ignoring");
1564                 return ARCHIVE_WARN;
1565         }
1566
1567         for (i = 0, j = 0; i < len; i += 2, j++) {
1568                 high = parse_hex_nibble(digest[i]);
1569                 low = parse_hex_nibble(digest[i+1]);
1570                 if (high == -1 || low == -1) {
1571                         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1572                                           "invalid digest data, ignoring");
1573                         return ARCHIVE_WARN;
1574                 }
1575
1576                 digest_buf[j] = high << 4 | low;
1577         }
1578
1579         return archive_entry_set_digest(entry, type, digest_buf);
1580 }
1581
1582 /*
1583  * Parse a single keyword and its value.
1584  */
1585 static int
1586 parse_keyword(struct archive_read *a, struct mtree *mtree,
1587     struct archive_entry *entry, struct mtree_option *opt, int *parsed_kws)
1588 {
1589         char *val, *key;
1590
1591         key = opt->value;
1592
1593         if (*key == '\0')
1594                 return (ARCHIVE_OK);
1595
1596         if (strcmp(key, "nochange") == 0) {
1597                 *parsed_kws |= MTREE_HAS_NOCHANGE;
1598                 return (ARCHIVE_OK);
1599         }
1600         if (strcmp(key, "optional") == 0) {
1601                 *parsed_kws |= MTREE_HAS_OPTIONAL;
1602                 return (ARCHIVE_OK);
1603         }
1604         if (strcmp(key, "ignore") == 0) {
1605                 /*
1606                  * The mtree processing is not recursive, so
1607                  * recursion will only happen for explicitly listed
1608                  * entries.
1609                  */
1610                 return (ARCHIVE_OK);
1611         }
1612
1613         val = strchr(key, '=');
1614         if (val == NULL) {
1615                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1616                     "Malformed attribute \"%s\" (%d)", key, key[0]);
1617                 return (ARCHIVE_WARN);
1618         }
1619
1620         *val = '\0';
1621         ++val;
1622
1623         switch (key[0]) {
1624         case 'c':
1625                 if (strcmp(key, "content") == 0
1626                     || strcmp(key, "contents") == 0) {
1627                         parse_escapes(val, NULL);
1628                         archive_strcpy(&mtree->contents_name, val);
1629                         return (ARCHIVE_OK);
1630                 }
1631                 if (strcmp(key, "cksum") == 0)
1632                         return (ARCHIVE_OK);
1633                 break;
1634         case 'd':
1635                 if (strcmp(key, "device") == 0) {
1636                         /* stat(2) st_rdev field, e.g. the major/minor IDs
1637                          * of a char/block special file */
1638                         int r;
1639                         dev_t dev;
1640
1641                         *parsed_kws |= MTREE_HAS_DEVICE;
1642                         r = parse_device(&dev, &a->archive, val);
1643                         if (r == ARCHIVE_OK)
1644                                 archive_entry_set_rdev(entry, dev);
1645                         return r;
1646                 }
1647                 break;
1648         case 'f':
1649                 if (strcmp(key, "flags") == 0) {
1650                         *parsed_kws |= MTREE_HAS_FFLAGS;
1651                         archive_entry_copy_fflags_text(entry, val);
1652                         return (ARCHIVE_OK);
1653                 }
1654                 break;
1655         case 'g':
1656                 if (strcmp(key, "gid") == 0) {
1657                         *parsed_kws |= MTREE_HAS_GID;
1658                         archive_entry_set_gid(entry, mtree_atol(&val, 10));
1659                         return (ARCHIVE_OK);
1660                 }
1661                 if (strcmp(key, "gname") == 0) {
1662                         *parsed_kws |= MTREE_HAS_GNAME;
1663                         archive_entry_copy_gname(entry, val);
1664                         return (ARCHIVE_OK);
1665                 }
1666                 break;
1667         case 'i':
1668                 if (strcmp(key, "inode") == 0) {
1669                         archive_entry_set_ino(entry, mtree_atol(&val, 10));
1670                         return (ARCHIVE_OK);
1671                 }
1672                 break;
1673         case 'l':
1674                 if (strcmp(key, "link") == 0) {
1675                         parse_escapes(val, NULL);
1676                         archive_entry_copy_symlink(entry, val);
1677                         return (ARCHIVE_OK);
1678                 }
1679                 break;
1680         case 'm':
1681                 if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0) {
1682                         return parse_digest(a, entry, val,
1683                             ARCHIVE_ENTRY_DIGEST_MD5);
1684                 }
1685                 if (strcmp(key, "mode") == 0) {
1686                         if (val[0] < '0' || val[0] > '7') {
1687                                 archive_set_error(&a->archive,
1688                                     ARCHIVE_ERRNO_FILE_FORMAT,
1689                                     "Symbolic or non-octal mode \"%s\" unsupported", val);
1690                                 return (ARCHIVE_WARN);
1691                         }
1692                         *parsed_kws |= MTREE_HAS_PERM;
1693                         archive_entry_set_perm(entry, (mode_t)mtree_atol(&val, 8));
1694                         return (ARCHIVE_OK);
1695                 }
1696                 break;
1697         case 'n':
1698                 if (strcmp(key, "nlink") == 0) {
1699                         *parsed_kws |= MTREE_HAS_NLINK;
1700                         archive_entry_set_nlink(entry,
1701                                 (unsigned int)mtree_atol(&val, 10));
1702                         return (ARCHIVE_OK);
1703                 }
1704                 break;
1705         case 'r':
1706                 if (strcmp(key, "resdevice") == 0) {
1707                         /* stat(2) st_dev field, e.g. the device ID where the
1708                          * inode resides */
1709                         int r;
1710                         dev_t dev;
1711
1712                         r = parse_device(&dev, &a->archive, val);
1713                         if (r == ARCHIVE_OK)
1714                                 archive_entry_set_dev(entry, dev);
1715                         return r;
1716                 }
1717                 if (strcmp(key, "rmd160") == 0 ||
1718                     strcmp(key, "rmd160digest") == 0) {
1719                         return parse_digest(a, entry, val,
1720                             ARCHIVE_ENTRY_DIGEST_RMD160);
1721                 }
1722                 break;
1723         case 's':
1724                 if (strcmp(key, "sha1") == 0 ||
1725                     strcmp(key, "sha1digest") == 0) {
1726                         return parse_digest(a, entry, val,
1727                             ARCHIVE_ENTRY_DIGEST_SHA1);
1728                 }
1729                 if (strcmp(key, "sha256") == 0 ||
1730                     strcmp(key, "sha256digest") == 0) {
1731                         return parse_digest(a, entry, val,
1732                             ARCHIVE_ENTRY_DIGEST_SHA256);
1733                 }
1734                 if (strcmp(key, "sha384") == 0 ||
1735                     strcmp(key, "sha384digest") == 0) {
1736                         return parse_digest(a, entry, val,
1737                             ARCHIVE_ENTRY_DIGEST_SHA384);
1738                 }
1739                 if (strcmp(key, "sha512") == 0 ||
1740                     strcmp(key, "sha512digest") == 0) {
1741                         return parse_digest(a, entry, val,
1742                             ARCHIVE_ENTRY_DIGEST_SHA512);
1743                 }
1744                 if (strcmp(key, "size") == 0) {
1745                         archive_entry_set_size(entry, mtree_atol(&val, 10));
1746                         return (ARCHIVE_OK);
1747                 }
1748                 break;
1749         case 't':
1750                 if (strcmp(key, "tags") == 0) {
1751                         /*
1752                          * Comma delimited list of tags.
1753                          * Ignore the tags for now, but the interface
1754                          * should be extended to allow inclusion/exclusion.
1755                          */
1756                         return (ARCHIVE_OK);
1757                 }
1758                 if (strcmp(key, "time") == 0) {
1759                         int64_t m;
1760                         int64_t my_time_t_max = get_time_t_max();
1761                         int64_t my_time_t_min = get_time_t_min();
1762                         long ns = 0;
1763
1764                         *parsed_kws |= MTREE_HAS_MTIME;
1765                         m = mtree_atol(&val, 10);
1766                         /* Replicate an old mtree bug:
1767                          * 123456789.1 represents 123456789
1768                          * seconds and 1 nanosecond. */
1769                         if (*val == '.') {
1770                                 ++val;
1771                                 ns = (long)mtree_atol(&val, 10);
1772                                 if (ns < 0)
1773                                         ns = 0;
1774                                 else if (ns > 999999999)
1775                                         ns = 999999999;
1776                         }
1777                         if (m > my_time_t_max)
1778                                 m = my_time_t_max;
1779                         else if (m < my_time_t_min)
1780                                 m = my_time_t_min;
1781                         archive_entry_set_mtime(entry, (time_t)m, ns);
1782                         return (ARCHIVE_OK);
1783                 }
1784                 if (strcmp(key, "type") == 0) {
1785                         switch (val[0]) {
1786                         case 'b':
1787                                 if (strcmp(val, "block") == 0) {
1788                                         *parsed_kws |= MTREE_HAS_TYPE;
1789                                         archive_entry_set_filetype(entry,
1790                                                 AE_IFBLK);
1791                                         return (ARCHIVE_OK);
1792                                 }
1793                                 break;
1794                         case 'c':
1795                                 if (strcmp(val, "char") == 0) {
1796                                         *parsed_kws |= MTREE_HAS_TYPE;
1797                                         archive_entry_set_filetype(entry,
1798                                                 AE_IFCHR);
1799                                         return (ARCHIVE_OK);
1800                                 }
1801                                 break;
1802                         case 'd':
1803                                 if (strcmp(val, "dir") == 0) {
1804                                         *parsed_kws |= MTREE_HAS_TYPE;
1805                                         archive_entry_set_filetype(entry,
1806                                                 AE_IFDIR);
1807                                         return (ARCHIVE_OK);
1808                                 }
1809                                 break;
1810                         case 'f':
1811                                 if (strcmp(val, "fifo") == 0) {
1812                                         *parsed_kws |= MTREE_HAS_TYPE;
1813                                         archive_entry_set_filetype(entry,
1814                                                 AE_IFIFO);
1815                                         return (ARCHIVE_OK);
1816                                 }
1817                                 if (strcmp(val, "file") == 0) {
1818                                         *parsed_kws |= MTREE_HAS_TYPE;
1819                                         archive_entry_set_filetype(entry,
1820                                                 AE_IFREG);
1821                                         return (ARCHIVE_OK);
1822                                 }
1823                                 break;
1824                         case 'l':
1825                                 if (strcmp(val, "link") == 0) {
1826                                         *parsed_kws |= MTREE_HAS_TYPE;
1827                                         archive_entry_set_filetype(entry,
1828                                                 AE_IFLNK);
1829                                         return (ARCHIVE_OK);
1830                                 }
1831                                 break;
1832                         default:
1833                                 break;
1834                         }
1835                         archive_set_error(&a->archive,
1836                             ARCHIVE_ERRNO_FILE_FORMAT,
1837                             "Unrecognized file type \"%s\"; "
1838                             "assuming \"file\"", val);
1839                         archive_entry_set_filetype(entry, AE_IFREG);
1840                         return (ARCHIVE_WARN);
1841                 }
1842                 break;
1843         case 'u':
1844                 if (strcmp(key, "uid") == 0) {
1845                         *parsed_kws |= MTREE_HAS_UID;
1846                         archive_entry_set_uid(entry, mtree_atol(&val, 10));
1847                         return (ARCHIVE_OK);
1848                 }
1849                 if (strcmp(key, "uname") == 0) {
1850                         *parsed_kws |= MTREE_HAS_UNAME;
1851                         archive_entry_copy_uname(entry, val);
1852                         return (ARCHIVE_OK);
1853                 }
1854                 break;
1855         default:
1856                 break;
1857         }
1858         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1859             "Unrecognized key %s=%s", key, val);
1860         return (ARCHIVE_WARN);
1861 }
1862
1863 static int
1864 read_data(struct archive_read *a, const void **buff, size_t *size,
1865     int64_t *offset)
1866 {
1867         size_t bytes_to_read;
1868         ssize_t bytes_read;
1869         struct mtree *mtree;
1870
1871         mtree = (struct mtree *)(a->format->data);
1872         if (mtree->fd < 0) {
1873                 *buff = NULL;
1874                 *offset = 0;
1875                 *size = 0;
1876                 return (ARCHIVE_EOF);
1877         }
1878         if (mtree->buff == NULL) {
1879                 mtree->buffsize = 64 * 1024;
1880                 mtree->buff = malloc(mtree->buffsize);
1881                 if (mtree->buff == NULL) {
1882                         archive_set_error(&a->archive, ENOMEM,
1883                             "Can't allocate memory");
1884                         return (ARCHIVE_FATAL);
1885                 }
1886         }
1887
1888         *buff = mtree->buff;
1889         *offset = mtree->offset;
1890         if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset)
1891                 bytes_to_read = (size_t)(mtree->cur_size - mtree->offset);
1892         else
1893                 bytes_to_read = mtree->buffsize;
1894         bytes_read = read(mtree->fd, mtree->buff, bytes_to_read);
1895         if (bytes_read < 0) {
1896                 archive_set_error(&a->archive, errno, "Can't read");
1897                 return (ARCHIVE_WARN);
1898         }
1899         if (bytes_read == 0) {
1900                 *size = 0;
1901                 return (ARCHIVE_EOF);
1902         }
1903         mtree->offset += bytes_read;
1904         *size = bytes_read;
1905         return (ARCHIVE_OK);
1906 }
1907
1908 /* Skip does nothing except possibly close the contents file. */
1909 static int
1910 skip(struct archive_read *a)
1911 {
1912         struct mtree *mtree;
1913
1914         mtree = (struct mtree *)(a->format->data);
1915         if (mtree->fd >= 0) {
1916                 close(mtree->fd);
1917                 mtree->fd = -1;
1918         }
1919         return (ARCHIVE_OK);
1920 }
1921
1922 /*
1923  * Since parsing backslash sequences always makes strings shorter,
1924  * we can always do this conversion in-place.
1925  */
1926 static void
1927 parse_escapes(char *src, struct mtree_entry *mentry)
1928 {
1929         char *dest = src;
1930         char c;
1931
1932         if (mentry != NULL && strcmp(src, ".") == 0)
1933                 mentry->full = 1;
1934
1935         while (*src != '\0') {
1936                 c = *src++;
1937                 if (c == '/' && mentry != NULL)
1938                         mentry->full = 1;
1939                 if (c == '\\') {
1940                         switch (src[0]) {
1941                         case '0':
1942                                 if (src[1] < '0' || src[1] > '7') {
1943                                         c = 0;
1944                                         ++src;
1945                                         break;
1946                                 }
1947                                 /* FALLTHROUGH */
1948                         case '1':
1949                         case '2':
1950                         case '3':
1951                                 if (src[1] >= '0' && src[1] <= '7' &&
1952                                     src[2] >= '0' && src[2] <= '7') {
1953                                         c = (src[0] - '0') << 6;
1954                                         c |= (src[1] - '0') << 3;
1955                                         c |= (src[2] - '0');
1956                                         src += 3;
1957                                 }
1958                                 break;
1959                         case 'a':
1960                                 c = '\a';
1961                                 ++src;
1962                                 break;
1963                         case 'b':
1964                                 c = '\b';
1965                                 ++src;
1966                                 break;
1967                         case 'f':
1968                                 c = '\f';
1969                                 ++src;
1970                                 break;
1971                         case 'n':
1972                                 c = '\n';
1973                                 ++src;
1974                                 break;
1975                         case 'r':
1976                                 c = '\r';
1977                                 ++src;
1978                                 break;
1979                         case 's':
1980                                 c = ' ';
1981                                 ++src;
1982                                 break;
1983                         case 't':
1984                                 c = '\t';
1985                                 ++src;
1986                                 break;
1987                         case 'v':
1988                                 c = '\v';
1989                                 ++src;
1990                                 break;
1991                         case '\\':
1992                                 c = '\\';
1993                                 ++src;
1994                                 break;
1995                         }
1996                 }
1997                 *dest++ = c;
1998         }
1999         *dest = '\0';
2000 }
2001
2002 /* Parse a hex digit. */
2003 static int
2004 parsedigit(char c)
2005 {
2006         if (c >= '0' && c <= '9')
2007                 return c - '0';
2008         else if (c >= 'a' && c <= 'f')
2009                 return c - 'a';
2010         else if (c >= 'A' && c <= 'F')
2011                 return c - 'A';
2012         else
2013                 return -1;
2014 }
2015
2016 /*
2017  * Note that this implementation does not (and should not!) obey
2018  * locale settings; you cannot simply substitute strtol here, since
2019  * it does obey locale.
2020  */
2021 static int64_t
2022 mtree_atol(char **p, int base)
2023 {
2024         int64_t l, limit;
2025         int digit, last_digit_limit;
2026
2027         if (base == 0) {
2028                 if (**p != '0')
2029                         base = 10;
2030                 else if ((*p)[1] == 'x' || (*p)[1] == 'X') {
2031                         *p += 2;
2032                         base = 16;
2033                 } else {
2034                         base = 8;
2035                 }
2036         }
2037
2038         if (**p == '-') {
2039                 limit = INT64_MIN / base;
2040                 last_digit_limit = -(INT64_MIN % base);
2041                 ++(*p);
2042
2043                 l = 0;
2044                 digit = parsedigit(**p);
2045                 while (digit >= 0 && digit < base) {
2046                         if (l < limit || (l == limit && digit >= last_digit_limit))
2047                                 return INT64_MIN;
2048                         l = (l * base) - digit;
2049                         digit = parsedigit(*++(*p));
2050                 }
2051                 return l;
2052         } else {
2053                 limit = INT64_MAX / base;
2054                 last_digit_limit = INT64_MAX % base;
2055
2056                 l = 0;
2057                 digit = parsedigit(**p);
2058                 while (digit >= 0 && digit < base) {
2059                         if (l > limit || (l == limit && digit > last_digit_limit))
2060                                 return INT64_MAX;
2061                         l = (l * base) + digit;
2062                         digit = parsedigit(*++(*p));
2063                 }
2064                 return l;
2065         }
2066 }
2067
2068 /*
2069  * Returns length of line (including trailing newline)
2070  * or negative on error.  'start' argument is updated to
2071  * point to first character of line.
2072  */
2073 static ssize_t
2074 readline(struct archive_read *a, struct mtree *mtree, char **start,
2075     ssize_t limit)
2076 {
2077         ssize_t bytes_read;
2078         ssize_t total_size = 0;
2079         ssize_t find_off = 0;
2080         const void *t;
2081         void *nl;
2082         char *u;
2083
2084         /* Accumulate line in a line buffer. */
2085         for (;;) {
2086                 /* Read some more. */
2087                 t = __archive_read_ahead(a, 1, &bytes_read);
2088                 if (t == NULL)
2089                         return (0);
2090                 if (bytes_read < 0)
2091                         return (ARCHIVE_FATAL);
2092                 nl = memchr(t, '\n', bytes_read);
2093                 /* If we found '\n', trim the read to end exactly there. */
2094                 if (nl != NULL) {
2095                         bytes_read = ((const char *)nl) - ((const char *)t) + 1;
2096                 }
2097                 if (total_size + bytes_read + 1 > limit) {
2098                         archive_set_error(&a->archive,
2099                             ARCHIVE_ERRNO_FILE_FORMAT,
2100                             "Line too long");
2101                         return (ARCHIVE_FATAL);
2102                 }
2103                 if (archive_string_ensure(&mtree->line,
2104                         total_size + bytes_read + 1) == NULL) {
2105                         archive_set_error(&a->archive, ENOMEM,
2106                             "Can't allocate working buffer");
2107                         return (ARCHIVE_FATAL);
2108                 }
2109                 /* Append new bytes to string. */
2110                 memcpy(mtree->line.s + total_size, t, bytes_read);
2111                 __archive_read_consume(a, bytes_read);
2112                 total_size += bytes_read;
2113                 mtree->line.s[total_size] = '\0';
2114
2115                 for (u = mtree->line.s + find_off; *u; ++u) {
2116                         if (u[0] == '\n') {
2117                                 /* Ends with unescaped newline. */
2118                                 *start = mtree->line.s;
2119                                 return total_size;
2120                         } else if (u[0] == '#') {
2121                                 /* Ends with comment sequence #...\n */
2122                                 if (nl == NULL) {
2123                                         /* But we've not found the \n yet */
2124                                         break;
2125                                 }
2126                         } else if (u[0] == '\\') {
2127                                 if (u[1] == '\n') {
2128                                         /* Trim escaped newline. */
2129                                         total_size -= 2;
2130                                         mtree->line.s[total_size] = '\0';
2131                                         break;
2132                                 } else if (u[1] != '\0') {
2133                                         /* Skip the two-char escape sequence */
2134                                         ++u;
2135                                 }
2136                         }
2137                 }
2138                 find_off = u - mtree->line.s;
2139         }
2140 }